Android -- 桌面悬浮,仿360

移动开发 Android
这种桌面悬浮窗的效果很类似与Widget,但是它比Widget要灵活的多。主要是通过WindowManager这个类来实现的,调用这个类的addView方法用于添加一个悬浮窗,updateViewLayout方法用于更新悬浮窗的参数,removeView用于移除悬浮窗。其中悬浮窗的参数有必要详细说明一下。

实现原理

这种桌面悬浮窗的效果很类似与Widget,但是它比Widget要灵活的多。主要是通过WindowManager这个类来实现的,调用这个类的addView方法用于添加一个悬浮窗,updateViewLayout方法用于更新悬浮窗的参数,removeView用于移除悬浮窗。其中悬浮窗的参数有必要详细说明一下。

WindowManager.LayoutParams这个类用于提供悬浮窗所需的参数,其中有几个经常会用到的变量:

type值用于确定悬浮窗的类型,一般设为2002,表示在所有应用程序之上,但在状态栏之下。

flags值用于确定悬浮窗的行为,比如说不可聚焦,非模态对话框等等,属性非常多,大家可以查看文档。

gravity值用于确定悬浮窗的对齐方式,一般设为左上角对齐,这样当拖动悬浮窗的时候方便计算坐标。

x值用于确定悬浮窗的位置,如果要横向移动悬浮窗,就需要改变这个值。

y值用于确定悬浮窗的位置,如果要纵向移动悬浮窗,就需要改变这个值。

width值用于指定悬浮窗的宽度。

height值用于指定悬浮窗的高度。

创建悬浮窗这种窗体需要向用户申请权限才可以的,因此还需要在AndroidManifest.xml中加入

  1. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 
  2. <uses-permission android:name="android.permission.GET_TASKS" /> 

code

activity_main.xml

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.     xmlns:tools="http://schemas.android.com/tools" 
  3.     android:layout_width="fill_parent" 
  4.     android:layout_height="fill_parent" 
  5.     tools:context=".MainActivity" 
  6.     android:orientation="vertical" > 
  7.  
  8.     <Button 
  9.         android:id="@+id/start_float_window" 
  10.         android:layout_width="fill_parent" 
  11.         android:layout_height="wrap_content" 
  12.         android:text="打开悬浮" > 
  13.     </Button> 
  14.  
  15. </LinearLayout> 

float_window_small.xml,用于做为小悬浮窗的布局

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <LinearLayout 
  3.     xmlns:android="http://schemas.android.com/apk/res/android" 
  4.     android:id="@+id/small_window_layout" 
  5.     android:layout_width="60dip" 
  6.     android:layout_height="25dip" 
  7.     android:background="@drawable/bg_small" 
  8.     > 
  9.     <TextView  
  10.         android:id="@+id/percent" 
  11.         android:layout_width="fill_parent" 
  12.         android:layout_height="fill_parent" 
  13.         android:gravity="center" 
  14.         android:textColor="#ffffff" 
  15.         /> 
  16. </LinearLayout> 

 

float_window_big.xml,用于做为大悬浮窗的布局

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:id="@+id/big_window_layout" 
  4.     android:layout_width="200dip" 
  5.     android:layout_height="100dip" 
  6.     android:background="@drawable/bg_big" 
  7.     android:orientation="vertical" > 
  8.  
  9.     <Button 
  10.         android:id="@+id/close" 
  11.         android:layout_width="100dip" 
  12.         android:layout_height="40dip" 
  13.         android:layout_gravity="center_horizontal" 
  14.         android:layout_marginTop="12dip" 
  15.         android:text="关闭悬浮窗" /> 
  16.  
  17.     <Button 
  18.         android:id="@+id/back" 
  19.         android:layout_width="100dip" 
  20.         android:layout_height="40dip" 
  21.         android:layout_gravity="center_horizontal" 
  22.         android:text="返回" /> 
  23.  
  24. </LinearLayout> 

然后打开MainActivity.java,这是项目的主界面

  1. @Override 
  2.     protected void onCreate(Bundle savedInstanceState) { 
  3.         super.onCreate(savedInstanceState); 
  4.         setContentView(R.layout.activity_main); 
  5.         Button startFloatWindow = (Button) findViewById(R.id.start_float_window); 
  6.         startFloatWindow.setOnClickListener(new OnClickListener() { 
  7.             @Override 
  8.             public void onClick(View arg0) { 
  9.                 // 开启服务 
  10.                 Intent intent = new Intent(MainActivity.this
  11.                         FloatWindowService.class); 
  12.                 startService(intent); 
  13.                 finish(); 
  14.             } 
  15.         }); 
  16.     } 

MainActivity的代码就是对开启悬浮窗的按钮注册了一个点击事件,用于打开一个服务,然后关闭当前Activity。

新建一个名为FloatWindowService的类,这个类继承自Service

  1. public class FloatWindowService extends Service { 
  2.  
  3.     /** 
  4.      * 用于在线程中创建或移除悬浮窗。 
  5.      */ 
  6.     private Handler handler = new Handler(); 
  7.  
  8.     /** 
  9.      * 定时器,定时进行检测当前应该创建还是移除悬浮窗。 
  10.      */ 
  11.     private Timer timer; 
  12.  
  13.     /** 
  14.      * 不是绑定的开启服务 
  15.      */ 
  16.     @Override 
  17.     public IBinder onBind(Intent intent) { 
  18.         return null
  19.     } 
  20.  
  21.     /** 
  22.      * Service的生命周期中会调用此函数 
  23.      */ 
  24.     @Override 
  25.     public int onStartCommand(Intent intent, int flags, int startId) { 
  26.         // 开启定时器,每隔0.5秒刷新一次 
  27.         if (timer == null) { 
  28.             timer = new Timer(); 
  29.             timer.scheduleAtFixedRate(new RefreshTask(), 0500); 
  30.         } 
  31.         return super.onStartCommand(intent, flags, startId); 
  32.     } 
  33.  
  34.     /** 
  35.      * Service终止 
  36.      */ 
  37.     @Override 
  38.     public void onDestroy() { 
  39.         super.onDestroy(); 
  40.         // Service被终止的同时也停止定时器继续运行 
  41.         timer.cancel(); 
  42.         timer = null
  43.     } 
  44.  
  45.     /** 
  46.      * 判断桌面上悬浮框状态 
  47.      *  
  48.      * @author sansung 
  49.      *  
  50.      */ 
  51.     class RefreshTask extends TimerTask { 
  52.  
  53.         @Override 
  54.         public void run() { 
  55.             // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。 
  56.             if (isHome() && !MyWindowManager.isWindowShowing()) { 
  57.                 handler.post(new Runnable() { 
  58.                     @Override 
  59.                     public void run() { 
  60.                         MyWindowManager 
  61.                                 .createSmallWindow(getApplicationContext()); 
  62.                     } 
  63.                 }); 
  64.             } 
  65.             // 当前界面不是桌面,且有悬浮窗显示,则移除悬浮窗。 
  66.             else if (!isHome() && MyWindowManager.isWindowShowing()) { 
  67.                 handler.post(new Runnable() { 
  68.                     @Override 
  69.                     public void run() { 
  70.                         MyWindowManager 
  71.                                 .removeSmallWindow(getApplicationContext()); 
  72.                         MyWindowManager 
  73.                                 .removeBigWindow(getApplicationContext()); 
  74.                     } 
  75.                 }); 
  76.             } 
  77.             // 当前界面是桌面,且有悬浮窗显示,则更新内存数据。 
  78.             else if (isHome() && MyWindowManager.isWindowShowing()) { 
  79.                 handler.post(new Runnable() { 
  80.                     @Override 
  81.                     public void run() { 
  82.                         MyWindowManager 
  83.                                 .updateUsedPercent(getApplicationContext()); 
  84.                     } 
  85.                 }); 
  86.             } 
  87.         } 
  88.  
  89.     } 
  90.  
  91.     /** 
  92.      * 判断当前界面是否是桌面 
  93.      */ 
  94.     private boolean isHome() { 
  95.         ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
  96.         List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1); 
  97.         // 如果在桌面,输出的是桌面的包名 
  98.         // 不在桌面的话输出的是打开的app的包名 
  99.         // System.out.println("getHomes().contains(rti.get(0).topActivity.getPackageName())+++"+rti.get(0).topActivity.getPackageName()); 
  100.         return getHomes().contains(rti.get(0).topActivity.getPackageName()); 
  101.     } 
  102.  
  103.     /** 
  104.      * 获得属于桌面的应用的应用包名称 
  105.      *  
  106.      * @return 返回包含所有包名的字符串列表 
  107.      */ 
  108.     private List<String> getHomes() { 
  109.         List<String> names = new ArrayList<String>(); 
  110.         PackageManager packageManager = this.getPackageManager(); 
  111.         Intent intent = new Intent(Intent.ACTION_MAIN); 
  112.         intent.addCategory(Intent.CATEGORY_HOME); 
  113.         List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities( 
  114.                 intent, PackageManager.MATCH_DEFAULT_ONLY); 
  115.         for (ResolveInfo ri : resolveInfo) { 
  116.             // 桌面包名 
  117.             // System.out.println("ri.activityInfo.packageName++++"+ri.activityInfo.packageName); 
  118.             names.add(ri.activityInfo.packageName); 
  119.         } 
  120.         return names; 
  121.     } 

FloatWindowService的onStartCommand方法中开启了一个定时器,每隔500毫秒就会执行RefreshTask。在 RefreshTask当中,要进行判断,如果手机当前是在桌面的话,就应该显示悬浮窗,如果手机打开了某一个应用程序,就应该移除悬浮窗,如果手机在桌 面的话,还应该更新内存使用百分比的数据。而当FloatWindowService被销毁的时候,应该将定时器停止,否则它还会一直运行。

创建和移除悬浮窗,以及更新悬浮窗内的数据,都是由MyWindowManager这个类来管理的,比起直接把这些代码写在Activity或Service当中,使用一个专门的工具类来管理要好的多。不过要想创建悬浮窗,还是先要把悬浮窗的View写出来。

新建一个名叫FloatWindowSmallView的类,继承自LinearLayout。新建一个名叫FloatWindowBigView的类,也继承自LinearLayout。

FloatWindowSmallView

  1. public class FloatWindowSmallView extends LinearLayout { 
  2.  
  3.     /** 
  4.      * 记录小悬浮窗的宽度 
  5.      */ 
  6.     public static int viewWidth; 
  7.  
  8.     /** 
  9.      * 记录小悬浮窗的高度 
  10.      */ 
  11.     public static int viewHeight; 
  12.  
  13.     /** 
  14.      * 记录系统状态栏的高度 
  15.      */ 
  16.     private static int statusBarHeight; 
  17.  
  18.     /** 
  19.      * 用于更新小悬浮窗的位置 
  20.      */ 
  21.     private WindowManager windowManager; 
  22.  
  23.     /** 
  24.      * 小悬浮窗的参数 
  25.      */ 
  26.     private WindowManager.LayoutParams mParams; 
  27.  
  28.     /** 
  29.      * 记录当前手指位置在屏幕上的横坐标值 
  30.      */ 
  31.     private float xInScreen; 
  32.  
  33.     /** 
  34.      * 记录当前手指位置在屏幕上的纵坐标值 
  35.      */ 
  36.     private float yInScreen; 
  37.  
  38.     /** 
  39.      * 记录手指按下时在屏幕上的横坐标的值 
  40.      */ 
  41.     private float xDownInScreen; 
  42.  
  43.     /** 
  44.      * 记录手指按下时在屏幕上的纵坐标的值 
  45.      */ 
  46.     private float yDownInScreen; 
  47.  
  48.     /** 
  49.      * 记录手指按下时在小悬浮窗的View上的横坐标的值 
  50.      */ 
  51.     private float xInView; 
  52.  
  53.     /** 
  54.      * 记录手指按下时在小悬浮窗的View上的纵坐标的值 
  55.      */ 
  56.     private float yInView; 
  57.  
  58.     /** 
  59.      * 构造函数 
  60.      *  
  61.      * @param context 
  62.      *            上下文 
  63.      */ 
  64.     public FloatWindowSmallView(Context context) { 
  65.         super(context); 
  66.         // 得到windowManager 
  67.         windowManager = (WindowManager) context 
  68.                 .getSystemService(Context.WINDOW_SERVICE); 
  69.         LayoutInflater.from(context).inflate(R.layout.float_window_small, this); 
  70.         View view = findViewById(R.id.small_window_layout); 
  71.         viewWidth = view.getLayoutParams().width; 
  72.         viewHeight = view.getLayoutParams().height; 
  73.         TextView percentView = (TextView) findViewById(R.id.percent); 
  74.         percentView.setText(MyWindowManager.getUsedPercentValue(context)); 
  75.     } 
  76.  
  77.     @Override 
  78.     public boolean onTouchEvent(MotionEvent event) { 
  79.         switch (event.getAction()) { 
  80.         case MotionEvent.ACTION_DOWN: 
  81.             // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度 
  82.             xInView = event.getX(); 
  83.             yInView = event.getY(); 
  84.             xDownInScreen = event.getRawX(); 
  85.             yDownInScreen = event.getRawY() - getStatusBarHeight(); 
  86.             xInScreen = event.getRawX(); 
  87.             yInScreen = event.getRawY() - getStatusBarHeight(); 
  88.             break
  89.         case MotionEvent.ACTION_MOVE: 
  90.             xInScreen = event.getRawX(); 
  91.             yInScreen = event.getRawY() - getStatusBarHeight(); 
  92.             // 手指移动的时候更新小悬浮窗的位置 
  93.             updateViewPosition(); 
  94.             break
  95.         case MotionEvent.ACTION_UP: 
  96.             // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。 
  97.             if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) { 
  98.                 openBigWindow(); 
  99.             } 
  100.             break
  101.         default
  102.             break
  103.         } 
  104.         return true
  105.     } 
  106.  
  107.     /** 
  108.      * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。 
  109.      *  
  110.      * @param params 
  111.      *            小悬浮窗的参数 
  112.      */ 
  113.     public void setParams(WindowManager.LayoutParams params) { 
  114.         mParams = params; 
  115.     } 
  116.  
  117.     /** 
  118.      * 更新小悬浮窗在屏幕中的位置。 
  119.      */ 
  120.     private void updateViewPosition() { 
  121.         mParams.x = (int) (xInScreen - xInView); 
  122.         mParams.y = (int) (yInScreen - yInView); 
  123.         windowManager.updateViewLayout(this, mParams); 
  124.     } 
  125.  
  126.     /** 
  127.      * 打开大悬浮窗,同时关闭小悬浮窗。 
  128.      */ 
  129.     private void openBigWindow() { 
  130.         MyWindowManager.createBigWindow(getContext()); 
  131.         MyWindowManager.removeSmallWindow(getContext()); 
  132.     } 
  133.  
  134.     /** 
  135.      * 用于获取状态栏的高度。 
  136.      *  
  137.      * @return 返回状态栏高度的像素值。 
  138.      */ 
  139.     private int getStatusBarHeight() { 
  140.         if (statusBarHeight == 0) { 
  141.             try { 
  142.                 Class<?> c = Class.forName("com.android.internal.R$dimen"); 
  143.                 Object o = c.newInstance(); 
  144.                 Field field = c.getField("status_bar_height"); 
  145.                 int x = (Integer) field.get(o); 
  146.                 statusBarHeight = getResources().getDimensionPixelSize(x); 
  147.             } catch (Exception e) { 
  148.                 e.printStackTrace(); 
  149.             } 
  150.         } 
  151.         return statusBarHeight; 
  152.     } 
  153.  

其中,对这个View的onTouchEvent事件进行了重写,用于实现拖动和点击的效果。如果发现用户触发了ACTION_DOWN事件,会记 录按下时的坐标等数据。如果发现用户触发了ACTION_MOVE事件,则根据当前移动的坐标更新悬浮窗在屏幕中的位置。如果发现用户触发了 ACTION_UP事件,会和ACTION_DOWN中记下的坐标对比,如果发现是相同的,则视为用户对悬浮窗进行了点击。点击小悬浮窗则打开大悬浮窗, 然后我们来实现大悬浮窗的View。

FloatWindowBigView

  1. public class FloatWindowBigView extends LinearLayout { 
  2.  
  3.     /** 
  4.      * 记录大悬浮窗的宽度 
  5.      */ 
  6.     public static int viewWidth; 
  7.  
  8.     /** 
  9.      * 记录大悬浮窗的高度 
  10.      */ 
  11.     public static int viewHeight; 
  12.  
  13.     public FloatWindowBigView(final Context context) { 
  14.         super(context); 
  15.         LayoutInflater.from(context).inflate(R.layout.float_window_big, this); 
  16.         View view = findViewById(R.id.big_window_layout); 
  17.         viewWidth = view.getLayoutParams().width; 
  18.         viewHeight = view.getLayoutParams().height; 
  19.         Button close = (Button) findViewById(R.id.close); 
  20.         Button back = (Button) findViewById(R.id.back); 
  21.         close.setOnClickListener(new OnClickListener() { 
  22.             @Override 
  23.             public void onClick(View v) { 
  24.                 // 点击关闭悬浮窗的时候,移除所有悬浮窗,并停止Service 
  25.                 MyWindowManager.removeBigWindow(context); 
  26.                 MyWindowManager.removeSmallWindow(context); 
  27.                 Intent intent = new Intent(getContext(), 
  28.                         FloatWindowService.class); 
  29.                 context.stopService(intent); 
  30.             } 
  31.         }); 
  32.         back.setOnClickListener(new OnClickListener() { 
  33.             @Override 
  34.             public void onClick(View v) { 
  35.                 // 点击返回的时候,移除大悬浮窗,创建小悬浮窗 
  36.                 MyWindowManager.removeBigWindow(context); 
  37.                 MyWindowManager.createSmallWindow(context); 
  38.             } 
  39.         }); 
  40.     } 

比起FloatWindowSmallView,FloatWindowBigView要简单的多,其中只有两个按钮,点击close按钮,将悬浮窗全部移除,并将Service终止。单击back按钮则移除大悬浮窗,重新创建小悬浮窗。

现在两个悬浮窗的View都已经写好了,我们来创建MyWindowManager

  1. public class MyWindowManager { 
  2.  
  3.     /** 
  4.      * 小悬浮窗View的实例 
  5.      */ 
  6.     private static FloatWindowSmallView smallWindow; 
  7.  
  8.     /** 
  9.      * 大悬浮窗View的实例 
  10.      */ 
  11.     private static FloatWindowBigView bigWindow; 
  12.  
  13.     /** 
  14.      * 小悬浮窗View的参数 
  15.      */ 
  16.     private static LayoutParams smallWindowParams; 
  17.  
  18.     /** 
  19.      * 大悬浮窗View的参数 
  20.      */ 
  21.     private static LayoutParams bigWindowParams; 
  22.  
  23.     /** 
  24.      * 用于控制在屏幕上添加或移除悬浮窗 
  25.      */ 
  26.     private static WindowManager mWindowManager; 
  27.  
  28.     /** 
  29.      * 用于获取手机可用内存 
  30.      */ 
  31.     private static ActivityManager mActivityManager; 
  32.  
  33.     /** 
  34.      * 创建一个小悬浮窗。初始位置为屏幕的右部中间位置。 
  35.      *  
  36.      * @param context 
  37.      *            必须为应用程序的Context. 
  38.      */ 
  39.     public static void createSmallWindow(Context context) { 
  40.         // 创建windowmanager 
  41.         WindowManager windowManager = getWindowManager(context); 
  42.         // 得到window长宽 
  43.         int screenWidth = windowManager.getDefaultDisplay().getWidth(); 
  44.         int screenHeight = windowManager.getDefaultDisplay().getHeight(); 
  45.         if (smallWindow == null) { 
  46.             smallWindow = new FloatWindowSmallView(context); 
  47.             if (smallWindowParams == null) { 
  48.                 smallWindowParams = new LayoutParams(); 
  49.                 smallWindowParams.type = LayoutParams.TYPE_PHONE; 
  50.                 smallWindowParams.format = PixelFormat.RGBA_8888; 
  51.                 smallWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL 
  52.                         | LayoutParams.FLAG_NOT_FOCUSABLE; 
  53.                 smallWindowParams.gravity = Gravity.LEFT | Gravity.TOP; 
  54.                 smallWindowParams.width = FloatWindowSmallView.viewWidth; 
  55.                 smallWindowParams.height = FloatWindowSmallView.viewHeight; 
  56.                 smallWindowParams.x = screenWidth; 
  57.                 smallWindowParams.y = screenHeight / 2
  58.             } 
  59.             // 配置 
  60.             smallWindow.setParams(smallWindowParams); 
  61.             // 在windowmanager中添加 
  62.             windowManager.addView(smallWindow, smallWindowParams); 
  63.         } 
  64.     } 
  65.  
  66.     /** 
  67.      * 将小悬浮窗从屏幕上移除。 
  68.      *  
  69.      * @param context 
  70.      *            必须为应用程序的Context. 
  71.      */ 
  72.     public static void removeSmallWindow(Context context) { 
  73.         if (smallWindow != null) { 
  74.             WindowManager windowManager = getWindowManager(context); 
  75.             windowManager.removeView(smallWindow); 
  76.             smallWindow = null
  77.         } 
  78.     } 
  79.  
  80.     /** 
  81.      * 创建一个大悬浮窗。位置为屏幕正中间。 
  82.      *  
  83.      * @param context 
  84.      *            必须为应用程序的Context. 
  85.      */ 
  86.     public static void createBigWindow(Context context) { 
  87.         WindowManager windowManager = getWindowManager(context); 
  88.         int screenWidth = windowManager.getDefaultDisplay().getWidth(); 
  89.         int screenHeight = windowManager.getDefaultDisplay().getHeight(); 
  90.         if (bigWindow == null) { 
  91.             bigWindow = new FloatWindowBigView(context); 
  92.             if (bigWindowParams == null) { 
  93.                 bigWindowParams = new LayoutParams(); 
  94.                 bigWindowParams.x = screenWidth / 2 
  95.                         - FloatWindowBigView.viewWidth / 2
  96.                 bigWindowParams.y = screenHeight / 2 
  97.                         - FloatWindowBigView.viewHeight / 2
  98.                 bigWindowParams.type = LayoutParams.TYPE_PHONE; 
  99.                 bigWindowParams.format = PixelFormat.RGBA_8888; 
  100.                 bigWindowParams.gravity = Gravity.LEFT | Gravity.TOP; 
  101.                 bigWindowParams.width = FloatWindowBigView.viewWidth; 
  102.                 bigWindowParams.height = FloatWindowBigView.viewHeight; 
  103.             } 
  104.             windowManager.addView(bigWindow, bigWindowParams); 
  105.         } 
  106.     } 
  107.  
  108.     /** 
  109.      * 将大悬浮窗从屏幕上移除。 
  110.      *  
  111.      * @param context 
  112.      *            必须为应用程序的Context. 
  113.      */ 
  114.     public static void removeBigWindow(Context context) { 
  115.         if (bigWindow != null) { 
  116.             WindowManager windowManager = getWindowManager(context); 
  117.             windowManager.removeView(bigWindow); 
  118.             bigWindow = null
  119.         } 
  120.     } 
  121.  
  122.     /** 
  123.      * 更新小悬浮窗的TextView上的数据,显示内存使用的百分比。 
  124.      *  
  125.      * @param context 
  126.      *            可传入应用程序上下文。 
  127.      */ 
  128.     public static void updateUsedPercent(Context context) { 
  129.         if (smallWindow != null) { 
  130.             TextView percentView = (TextView) smallWindow 
  131.                     .findViewById(R.id.percent); 
  132.             percentView.setText(getUsedPercentValue(context)); 
  133.         } 
  134.     } 
  135.  
  136.     /** 
  137.      * 是否有悬浮窗(包括小悬浮窗和大悬浮窗)显示在屏幕上。 
  138.      *  
  139.      * @return 有悬浮窗显示在桌面上返回true,没有的话返回false。 
  140.      */ 
  141.     public static boolean isWindowShowing() { 
  142.         return smallWindow != null || bigWindow != null
  143.     } 
  144.  
  145.     /** 
  146.      * 如果WindowManager还未创建,则创建一个新的WindowManager返回。否则返回当前已创建的WindowManager。 
  147.      *  
  148.      * @param context 
  149.      *            必须为应用程序的Context. 
  150.      * @return WindowManager的实例,用于控制在屏幕上添加或移除悬浮窗。 
  151.      */ 
  152.     private static WindowManager getWindowManager(Context context) { 
  153.         if (mWindowManager == null) { 
  154.             mWindowManager = (WindowManager) context 
  155.                     .getSystemService(Context.WINDOW_SERVICE); 
  156.         } 
  157.         return mWindowManager; 
  158.     } 
  159.  
  160.     /** 
  161.      * 如果ActivityManager还未创建,则创建一个新的ActivityManager返回。否则返回当前已创建的ActivityManager。 
  162.      *  
  163.      * @param context 
  164.      *            可传入应用程序上下文。 
  165.      * @return ActivityManager的实例,用于获取手机可用内存。 
  166.      */ 
  167.     private static ActivityManager getActivityManager(Context context) { 
  168.         if (mActivityManager == null) { 
  169.             mActivityManager = (ActivityManager) context 
  170.                     .getSystemService(Context.ACTIVITY_SERVICE); 
  171.         } 
  172.         return mActivityManager; 
  173.     } 
  174.  
  175.     /** 
  176.      * 计算已使用内存的百分比,并返回。 
  177.      *  
  178.      * @param context 
  179.      *            可传入应用程序上下文。 
  180.      * @return 已使用内存的百分比,以字符串形式返回。 
  181.      */ 
  182.     public static String getUsedPercentValue(Context context) { 
  183.         String dir = "/proc/meminfo"
  184.         try { 
  185.             FileReader fr = new FileReader(dir); 
  186.             BufferedReader br = new BufferedReader(fr, 2048); 
  187.             String memoryLine = br.readLine(); 
  188.             String subMemoryLine = memoryLine.substring(memoryLine 
  189.                     .indexOf("MemTotal:")); 
  190.             br.close(); 
  191.             long totalMemorySize = Integer.parseInt(subMemoryLine.replaceAll( 
  192.                     "\\D+""")); 
  193.             long availableSize = getAvailableMemory(context) / 1024
  194.             int percent = (int) ((totalMemorySize - availableSize) 
  195.                     / (float) totalMemorySize * 100); 
  196.             return percent + "%"
  197.         } catch (IOException e) { 
  198.             e.printStackTrace(); 
  199.         } 
  200.         return "悬浮窗"
  201.     } 
  202.  
  203.     /** 
  204.      * 获取当前可用内存,返回数据以字节为单位。 
  205.      *  
  206.      * @param context 
  207.      *            可传入应用程序上下文。 
  208.      * @return 当前可用内存。 
  209.      */ 
  210.     private static long getAvailableMemory(Context context) { 
  211.         ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); 
  212.         getActivityManager(context).getMemoryInfo(mi); 
  213.         return mi.availMem; 
  214.     } 
  215.  

本文链接:http://www.cnblogs.com/yydcdut/archive/2014/08/15/3909888.html

责任编辑:chenqingxiang 来源: cnblogs
相关推荐

2015-09-01 16:37:21

360手机卫士高仿

2012-08-13 10:20:30

Windowslinux桌面

2011-05-20 21:41:16

2017-01-06 13:12:11

AndroidRecyclerVie悬浮条

2015-10-23 13:36:22

2011-12-16 13:28:53

360预防感冒预防流感

2013-08-02 10:20:03

android时间轴

2016-11-29 11:20:08

Android

2012-10-07 15:11:48

钓鱼网站假冒网站360安全中心

2011-06-02 09:23:58

Android 效果

2015-01-22 15:44:55

Android源码音乐播放器

2011-07-22 13:43:30

2010-09-14 16:58:10

2017-05-12 14:55:39

Android绘制刻度盘

2015-02-06 18:29:09

仿滴滴打车android

2015-02-28 15:15:47

插件Android桌面插件

2011-10-11 09:46:28

2015-10-12 11:19:35

墨迹天气引导界面android

2011-09-07 10:58:07

Android wid

2015-02-27 15:46:09

Android源码桌面APP
点赞
收藏

51CTO技术栈公众号