使用悬浮框监听内存的使用状态 -- 附源码
来源:互联网 发布:会话php 编辑:程序博客网 时间:2024/06/05 03:16
源码下载地址:http://download.csdn.net/detail/hewence1/8176601
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">先看一下效果: 显示当前内存使用率55% ,每一秒都刷新一次</span>
实现原理,在Service中创建一个悬浮框就可,在service中每秒钟访问计算一次单曲使用了多少的内存,并更新对应的控件
实现步骤:
1 创建一个Activity,此Activty自启动service即可,当然也可以加上其他界面
Activity代码:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent show = new Intent(this, FloatService.class); startService(show);}Xml代码就不贴了占篇幅,service代码现在也是空的也不贴了。
Manifest文件要注意:
加入权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
跟service
<service android:name="com.example.testfloating.FloatService"></service>
2. 增加悬浮框
要增加的悬浮框跟上图一样要重写一个圆形的View 并且可以使阴影(现在是使用绿色)来表示百分百,如50% 那么绿色就只有一半。另一半显示背景色
先看这个View的代码:
int width ;int height;int precent;Bitmap mBitmap ;int viewCorol = 0xff00ff00;public CircleView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onDraw(Canvas canvas) { // 先获得一个 bitmap吧 再super.onDraw(canvas);width = getMeasuredWidth();height = getMeasuredHeight();mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas mCanvas = new Canvas(mBitmap); Paint mPaint = new Paint(); mPaint.setColor(viewCorol); mPaint.setAntiAlias(true); mCanvas.drawCircle(width / 2, height / 2, width / 2, mPaint); canvas.drawBitmap(mBitmap, new Rect(0, height * (100 - precent) / 100, width, height) ,new Rect(0, height * (100 - precent) / 100, width, height), null);}public void setPrecent(int precent) {this.precent = precent;invalidate();}方法的实现请自己看代码, 不难理解
在setPrecent就是设计百分百比,这这里可以延伸一下的,
可以加入根据precent的大少来更改阴影的颜色,颜色的值要有一个递变的过程()
public void setPrecent(int precent) {this.precent = precent;if (precent >= 90){viewColor = .....}else if (precent >= 80){viewColor = .....}else if (precent >= 70){viewColor = .....}.precent........else{}invalidate();}
</pre><pre name="code" class="java">现在看布局文件:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/window" ><!-- android:descendantFocusability="blocksDescendants" --> <RelativeLayout android:id="@+id/circle_layout" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/window_bg" android:orientation="vertical" > <com.example.textfloatingwindow.CircleView android:id="@+id/window_circle" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerInParent="true" > </com.example.textfloatingwindow.CircleView> <TextView android:id="@+id/precent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="#ffffffff" android:textSize="20sp" /> </RelativeLayout></RelativeLayout>
service代码:
@Overridepublic void onCreate() {super.onCreate();createFloatView();Log.i(TAG , "onCreate");}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);mHandler.sendEmptyMessage(HANDLE_CHECK_ACTIVITY);Log.i(TAG , "onStart");}@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case HANDLE_CHECK_ACTIVITY:if (!isAdded) {Log.i(TAG , "wm.addView(mainView, params);");wm.addView(mainView, params);isAdded = true;}mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);break;}}};/** * 创建悬浮窗 */private void createFloatView() {wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);params = new WindowManager.LayoutParams();// 设置window typeparams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;/* * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 那么优先级会降低一些, * 即拉下通知栏不可见 */params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明// 设置Window flagparams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;/* * 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。 * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL | * LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE; */// 设置悬浮窗的长得宽params.width = params.WRAP_CONTENT;params.height = params.WRAP_CONTENT;if (null == inflater){inflater = LayoutInflater.from(getApplicationContext());mainView = inflater.inflate(R.layout.window_view, null);precent = (TextView) mainView.findViewById(R.id.precent);circleView = (CircleView) mainView.findViewById(R.id.window_circle);}}在onCreate里创建一个View ,但是没有加入到WindowManager中,在onStart中启动了Handler 每秒钟执行一次
if (!isAdded) {Log.i(TAG , "wm.addView(mainView, params);");wm.addView(mainView, params);isAdded = true;}通过这个来增加到WindowManager来实现悬浮框。
先的效果如图:
现在悬浮框中啥都没有,只有一个背景,在这里 我只是使用一个shape当做背景,大家可以使用更pl的UI素材。现在的内存使用率是没有显示出来的是没有设置的!
3. 实时监控内存的变化
在Handler中增加这个更新得到的数据:
得到数据数据的方法如下:
/** * 得到系统总内存 单位KB * @param context * @return */ public long getTotalMemory(Context context) { String str1 = "/proc/meminfo";// 系统内存信息文件 String str2; String[] arrayOfString; long initial_memory = 0; try { FileReader localFileReader = new FileReader(str1); BufferedReader localBufferedReader = new BufferedReader(localFileReader, 8192); str2 = localBufferedReader.readLine();// 读取meminfo第一行,系统总内存大小 arrayOfString = str2.split("\\s+"); /* for (String num : arrayOfString) { Log.i(str2, num + "\t"); }*/ initial_memory = Integer.valueOf(arrayOfString[1]).intValue() * 1024;// 获得系统总内存,单位是KB,乘以1024转换为Byte localBufferedReader.close(); } catch (IOException e) { } return initial_memory; } public long getAvailMemory(Context context) {// 获取android当前可用内存大小 ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); MemoryInfo mi = new MemoryInfo(); am.getMemoryInfo(mi); return mi.availMem; } private int getPrecent(){ long totalSize = getTotalMemory(getApplicationContext()); long aliSize = getAvailMemory(getApplicationContext()); int precent = 100 - (int) (aliSize * 100 / (float)totalSize); return precent; } Handler修改为:
<pre name="code" class="java">@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case HANDLE_CHECK_ACTIVITY:if (!isAdded) {Log.i(TAG , "wm.addView(mainView, params);");wm.addView(mainView, params);isAdded = true;}<span style="background-color: rgb(255, 153, 0);">precent.setText(getPrecent() + "%");circleView.setPrecent(getPrecent());</span>mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);break;}}};
现在效果就是:
机器的任何都是有它的存在的,所有就实现了实时监听
4. 可拖动到界面任何一个地方
现在的悬浮框中能在最中间,现在我们就把他推动到你要想的位置:
增加onTouch处理
// 设置悬浮窗的Touch监听mainView.setOnTouchListener(new OnTouchListener() {int lastX, lastY;int paramX, paramY;public boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:lastX = (int) event.getRawX();lastY = (int) event.getRawY();paramX = params.x;paramY = params.y;break;case MotionEvent.ACTION_MOVE:int dx = (int) event.getRawX() - lastX;int dy = (int) event.getRawY() - lastY;params.x = paramX + dx;params.y = paramY + dy;// 更新悬浮窗位置wm.updateViewLayout(mainView, params);break;}// return true的 click事件是没有反应的,至于为什么 大家去了解触摸事件分发与处理 就知道了return false;}});
5.只在主界面显示
现在的悬浮框在所有的界面都显示了,有些不合理,在桌面才显示这个悬浮框(这里可以设置一个设置项 是否只显示在主界面)
判断是否是在桌面的方法如下:
/** 获得属于桌面的应用的应用包名称 * * @return 返回包含所有包名的字符串列表 */private List<String> getHomes() {List<String> names = new ArrayList<String>();PackageManager packageManager = this.getPackageManager();// 属性Intent intent = new Intent(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_HOME);List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);for (ResolveInfo ri : resolveInfo) {names.add(ri.activityInfo.packageName);}return names;}/** * 判断当前界面是否是桌面 */public boolean isHome() {if (mActivityManager == null) {mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);}List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);return homeList.contains(rti.get(0).topActivity.getPackageName());}
@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case HANDLE_CHECK_ACTIVITY:if (isHome()){if (!isAdded) {Log.i(TAG , "wm.addView(mainView, params);");wm.addView(mainView, params);isAdded = true;}// 只有主界面才更新precent.setText(getPrecent() + "%");circleView.setPrecent(getPrecent());}else{if (isAdded){wm.removeView(mainView);isAdded = false;}}mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);break;}}};
</pre><pre name="code" class="java">@Overridepublic void onCreate() {super.onCreate();homeList = getHomes();createFloatView();Log.i(TAG , "onCreate");}
这样可以保证只有在桌面时才显示悬浮框
6.增加悬浮框的响应事件
现在的悬浮框点击是无效的,我们想要点击时 退出 或者跳转到应用,或者启动某个 Intent等
可以在点击悬浮框时弹出一个另外的一排按钮,来适应大家的要求,再次点击时移除这一排按钮
修改布局文件为:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/window" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:id="@+id/circle_layout" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/window_bg" android:orientation="vertical" > <com.example.textfloatingwindow.CircleView android:id="@+id/window_circle" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerInParent="true" > </com.example.textfloatingwindow.CircleView> <TextView android:id="@+id/precent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="#ffffffff" android:textSize="20sp" /> </RelativeLayout> <LinearLayout android:id="@+id/menu_layout" android:layout_width="80dp" android:layout_height="60dp" android:layout_toRightOf="@id/circle_layout" android:visibility="gone" android:orientation="vertical" > <TextView android:id="@+id/menu0" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="打开应用" /> <TextView android:id="@+id/menu1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="返回" /> <TextView android:id="@+id/menu2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="退出悬浮框" /> </LinearLayout></RelativeLayout>
增加代码:
menu0.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Intent it = new Intent(FloatService.this , MainActivity.class);it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(it);}});menu1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {menu.setVisibility(View.GONE);}});menu2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {isAdded = false;wm.removeView(mainView);// 记得要移动掉handler 否则还是一秒运行一次mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);stopSelf();}});效果如下:
界面不怎么好看,这个请自己布局
点击都是有作用的!
1 0
- 使用悬浮框监听内存的使用状态 -- 附源码
- CI面包屑的使用,附源码
- 使用BroadcastReceiver监听网络状态
- PopupWindow(悬浮框)的基本使用
- SharedPreferences基本使用(附源码)
- API的使用——监听的状态参数
- 使用ConnectivityManager来获取、监听当前的网络状态
- 使用苹果自带的Reachability监听网络状态
- Android:使用Broadcast Receiver监听网络连接状态的改变
- 查看JVM内存状态的工具使用
- 查看MyEclipse的内存使用状态
- Toast的悬浮窗使用
- android的SQLite数据库的使用(附源码)
- Android中include和merge标签的使用(附源码)
- JAVA复用类之组合语法的使用(附源码)
- 使用ajax方法实现form表单的提交(附源码)
- MFC开发的一个类似鲁大师悬浮框小工具(可以检测CPU 内存使用)
- network: android 使用广播监听网络状态
- vector::erase()方法的详细介绍及问题解答
- Java 测试代码
- Linux watchdog
- poj 2137 Cowties dp
- storage class specified for parameter
- 使用悬浮框监听内存的使用状态 -- 附源码
- ios中图片加载并显示图标
- php学习笔记(七)
- Access restriction: The type BASE64Encoder is not accessible due to restrict
- 高斯日记
- android:configChanges
- Maven 设置编译 jdk 版本 1.7
- AD属性对照表 LDAP以及简单示例
- 文件下载