Android desktop suspension window effect realization, imitation 360 mobile guard suspension window effect

From: http://blog.csdn.net/guolin_blog/article/details/8689140

Hello, everybody. Today I'm going to give you a tutorial that imitates the effect of 360 mobile phone guard suspension window. Before we start, please allow me to say a few irrelevant nonsense.


Unconsciously I found myself in contact. Android It has been nearly three years. During this period, all kinds of growth can not be achieved without the help of your masters. There are always many masters who like to write their own experience on the Internet for you to learn. I have also benefited a lot from it. Here I am deeply grateful. But I find that I have never shared some of my usual experience with you, learning together, too devoted. So I decided to start blogging today, hoping to point out the developers behind me and get into the Android developer ranks more quickly.


Okay, so much nonsense, let's start with today's topic.


360 Mobile Guardian I believe you all know that many mobile phones will be equipped with this software, then we will surely be familiar with the effect of a desktop suspension window. See the following picture:


           


First, a small suspension window shows how much memory is currently used. Clicking on a small suspension window will pop up a large suspension window, which can be accelerated by one click. Well, let's now simulate a similar effect.


Let's start with the basic implementation principle. This desktop suspension window works much like Widget, but it's much more flexible than Widget. Mainly through the Windows Manager class, call the addView method of this class to add a suspension window, updateViewLayout method to update the parameters of the suspension window, removeView to remove the suspension window. The parameters of the suspension window need to be explained in detail.


The Windows Manager.LayoutParams class is used to provide the parameters needed for the suspension window. There are several variables that are often used:

The type value is used to determine the type of suspension window, usually set to 2002, which is above all applications, but below the status bar.

flags values are used to determine the behavior of suspended windows, such as unfocusable, non-modal dialog boxes, etc. There are many attributes, you can view documents.

gravity value is used to determine the alignment mode of the suspension window, which is generally set to the upper left corner alignment, so that coordinates can be easily calculated when the suspension window is dragged.

The x value is used to determine the position of the suspension window. If you want to move the suspension window horizontally, you need to change this value.

The y value is used to determine the position of the suspension window, which needs to be changed if the suspension window is to be moved vertically.

The width value is used to specify the width of the suspension window.

The height value is used to specify the height of the suspension window.


Creating a suspended window is a form that requires permission from the user, so you need to add <uses-permission and roid: name="android.permission.SYSTEM_ALERT_WINDOW"/> in Android Manifest.xml.


This is the end of the introduction. Let's start with code. First, create a new Android project in Eclipse called 360Float Windows Demo. Then write the layout file. The layout file is very simple. There is only one button. Open or create activity_main.xml. Add the following code:

  1. <RelativeLayout 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.     <Button  
  7.         android:id="@+id/start_float_window"  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="Start Float Window" >  
  11.     </Button>  
  12. </RelativeLayout>  

Then a new layout file named float_window_small.xml is created for the layout of the small suspension window, in which the following code is added:

  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>  
A new layout file named float_window_big.xml is created for the layout of the large suspension window. The following code is added to it:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <LinearLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:id="@+id/big_window_layout"  
  5.     android:layout_width="200dip"  
  6.     android:layout_height="100dip"  
  7.     android:background="@drawable/bg_big"  
  8.     android:orientation="vertical"  
  9.     >  
  10.     <Button   
  11.         android:id="@+id/close"  
  12.         android:layout_width="100dip"  
  13.         android:layout_height="40dip"  
  14.         android:layout_gravity="center_horizontal"  
  15.         android:layout_marginTop="12dip"  
  16.         android:text="Close the suspension window"  
  17.         />  
  18.     <Button   
  19.         android:id="@+id/back"  
  20.         android:layout_width="100dip"  
  21.         android:layout_height="40dip"  
  22.         android:layout_gravity="center_horizontal"  
  23.         android:text="Return"  
  24.         />  
  25. </LinearLayout>  

Two floating window layout files used in the image resources, you can easily find some pictures to replace, at the same time I will give the source code, you can also extract from the source code.


Then open or create MainActivity, which is the main interface of the project, and add the following code in it:

  1. public class MainActivity extends Activity {  
  2.     @Override  
  3.     protected void onCreate(Bundle savedInstanceState) {  
  4.         super.onCreate(savedInstanceState);  
  5.         setContentView(R.layout.activity_main);  
  6.         Button startFloatWindow = (Button) findViewById(R.id.start_float_window);  
  7.         startFloatWindow.setOnClickListener(new OnClickListener() {  
  8.             @Override  
  9.             public void onClick(View arg0) {  
  10.                 Intent intent = new Intent(MainActivity.this, FloatWindowService.class);  
  11.                 startService(intent);  
  12.                 finish();  
  13.             }  
  14.         });  
  15.     }  
  16. }  
As you can see here, MainActivity's code is not simple, it registers a click event for the button that opens the suspension window to open a service and then closes the current Activity. The logic for creating suspended windows is left to the service. Okay, now let's create this service. Create a new class named Float Windows Service, which inherits from Service and adds the following code:
  1. public class FloatWindowService extends Service {  
  2.   
  3.     /** 
  4.      * Used to create or remove suspended windows in threads. 
  5.      */  
  6.     private Handler handler = new Handler();  
  7.   
  8.     /** 
  9.      * Timer to check whether the suspension window should be created or removed at the moment. 
  10.      */  
  11.     private Timer timer;  
  12.   
  13.     @Override  
  14.     public IBinder onBind(Intent intent) {  
  15.         return null;  
  16.     }  
  17.   
  18.     @Override  
  19.     public int onStartCommand(Intent intent, int flags, int startId) {  
  20.         //Turn on the timer and refresh it every 0.5 seconds  
  21.         if (timer == null) {  
  22.             timer = new Timer();  
  23.             timer.scheduleAtFixedRate(new RefreshTask(), 0500);  
  24.         }  
  25.         return super.onStartCommand(intent, flags, startId);  
  26.     }  
  27.   
  28.     @Override  
  29.     public void onDestroy() {  
  30.         super.onDestroy();  
  31.         //The Service is terminated while the timer continues to run  
  32.         timer.cancel();  
  33.         timer = null;  
  34.     }  
  35.   
  36.     class RefreshTask extends TimerTask {  
  37.   
  38.         @Override  
  39.         public void run() {  
  40.             //If the current interface is desktop and there is no suspension window display, the suspension window is created.  
  41.             if (isHome() && !MyWindowManager.isWindowShowing()) {  
  42.                 handler.post(new Runnable() {  
  43.                     @Override  
  44.                     public void run() {  
  45.                         MyWindowManager.createSmallWindow(getApplicationContext());  
  46.                     }  
  47.                 });  
  48.             }  
  49.             //If the current interface is not a desktop and has a suspension window display, the suspension window is removed.  
  50.             else if (!isHome() && MyWindowManager.isWindowShowing()) {  
  51.                 handler.post(new Runnable() {  
  52.                     @Override  
  53.                     public void run() {  
  54.                         MyWindowManager.removeSmallWindow(getApplicationContext());  
  55.                         MyWindowManager.removeBigWindow(getApplicationContext());  
  56.                     }  
  57.                 });  
  58.             }  
  59.             //The current interface is the desktop, and if it has a suspended window display, the memory data is updated.  
  60.             else if (isHome() && MyWindowManager.isWindowShowing()) {  
  61.                 handler.post(new Runnable() {  
  62.                     @Override  
  63.                     public void run() {  
  64.                         MyWindowManager.updateUsedPercent(getApplicationContext());  
  65.                     }  
  66.                 });  
  67.             }  
  68.         }  
  69.   
  70.     }  
  71.   
  72.     /** 
  73.      * Determine if the current interface is a desktop? 
  74.      */  
  75.     private boolean isHome() {  
  76.         ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);  
  77.         List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);  
  78.         return getHomes().contains(rti.get(0).topActivity.getPackageName());  
  79.     }  
  80.   
  81.     /** 
  82.      * Get the name of the application package that belongs to the desktop 
  83.      *  
  84.      * @return Returns a list of strings containing all package names 
  85.      */  
  86.     private List<String> getHomes() {  
  87.         List<String> names = new ArrayList<String>();  
  88.         PackageManager packageManager = this.getPackageManager();  
  89.         Intent intent = new Intent(Intent.ACTION_MAIN);  
  90.         intent.addCategory(Intent.CATEGORY_HOME);  
  91.         List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,  
  92.                 PackageManager.MATCH_DEFAULT_ONLY);  
  93.         for (ResolveInfo ri : resolveInfo) {  
  94.             names.add(ri.activityInfo.packageName);  
  95.         }  
  96.         return names;  
  97.     }  
  98. }  

In Float Windows Service's onStartCommand method, a timer is turned on and RefreshTask is executed every 500 milliseconds. In RefreshTask, if the mobile phone is currently on the desktop, it should display the suspension window. If the mobile phone opens an application, it should remove the suspension window. If the mobile phone is on the desktop, it should update the data of the percentage of memory usage. When the Float Windows Service is destroyed, the timer should be stopped, otherwise it will still be running.


From the above code, we can also see that creating and removing suspension windows and updating data in suspension windows are managed by MyWindows Manager class, which is much better than writing these codes directly in Activity or Service, using a special tool class to manage them. However, to create a suspended window, you need to write out the View of the suspended window first.


Create a new class called Float Windows SmallView, which inherits from LinearLayout. A new class called Float Windows BigView is also inherited from LinearLayout.


Add the following code in Float Windows SmallView:

  1. public class FloatWindowSmallView extends LinearLayout {  
  2.   
  3.     /** 
  4.      * Record the width of the small suspension window 
  5.      */  
  6.     public static int viewWidth;  
  7.   
  8.     /** 
  9.      * Record the height of the small suspension window 
  10.      */  
  11.     public static int viewHeight;  
  12.   
  13.     /** 
  14.      * Record the height of the system status bar 
  15.      */  
  16.      private static int statusBarHeight;  
  17.   
  18.     /** 
  19.      * Used to update the position of the small suspension window 
  20.      */  
  21.     private WindowManager windowManager;  
  22.   
  23.     /** 
  24.      * Parameters of Small Suspension Window 
  25.      */  
  26.     private WindowManager.LayoutParams mParams;  
  27.   
  28.     /** 
  29.      * Record the abscissa values of the current finger position on the screen 
  30.      */  
  31.     private float xInScreen;  
  32.   
  33.     /** 
  34.      * Record the ordinate values of the current finger position on the screen 
  35.      */  
  36.     private float yInScreen;  
  37.   
  38.     /** 
  39.      * Record the abscissa values on the screen when the finger is pressed 
  40.      */  
  41.     private float xDownInScreen;  
  42.   
  43.     /** 
  44.      * Record the value of the ordinates on the screen when the finger is pressed 
  45.      */  
  46.     private float yDownInScreen;  
  47.   
  48.     /** 
  49.      * Record the abscissa values on the View of the small suspension window when the finger is pressed 
  50.      */  
  51.     private float xInView;  
  52.   
  53.     /** 
  54.      * Record the value of the longitudinal coordinates on the View of the small suspension window when the finger is pressed 
  55.      */  
  56.     private float yInView;  
  57.   
  58.     public FloatWindowSmallView(Context context) {  
  59.         super(context);  
  60.         windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  
  61.         LayoutInflater.from(context).inflate(R.layout.float_window_small, this);  
  62.         View view = findViewById(R.id.small_window_layout);  
  63.         viewWidth = view.getLayoutParams().width;  
  64.         viewHeight = view.getLayoutParams().height;  
  65.         TextView percentView = (TextView) findViewById(R.id.percent);  
  66.         percentView.setText(MyWindowManager.getUsedPercentValue(context));  
  67.     }  
  68.   
  69.     @Override  
  70.     public boolean onTouchEvent(MotionEvent event) {  
  71.         switch (event.getAction()) {  
  72.         case MotionEvent.ACTION_DOWN:  
  73.             //Record the necessary data when the finger is pressed, and the values of the ordinates need to be subtracted from the height of the status bar.  
  74.             xInView = event.getX();  
  75.             yInView = event.getY();  
  76.             xDownInScreen = event.getRawX();  
  77.             yDownInScreen = event.getRawY() - getStatusBarHeight();  
  78.             xInScreen = event.getRawX();  
  79.             yInScreen = event.getRawY() - getStatusBarHeight();  
  80.             break;  
  81.         case MotionEvent.ACTION_MOVE:  
  82.             xInScreen = event.getRawX();  
  83.             yInScreen = event.getRawY() - getStatusBarHeight();  
  84.             //Update the position of the small suspension window when the finger moves  
  85.             updateViewPosition();  
  86.             break;  
  87.         case MotionEvent.ACTION_UP:  
  88.             //If the finger leaves the screen, xDownInScreen and xInScreen are equal, and yDownInScreen and yInScreen are equal, the click event is considered triggered.  
  89.             if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {  
  90.                 openBigWindow();  
  91.             }  
  92.             break;  
  93.         default:  
  94.             break;  
  95.         }  
  96.         return true;  
  97.     }  
  98.   
  99.     /** 
  100.      * The parameters of the small suspension window are passed in to update the position of the small suspension window. 
  101.      *  
  102.      * @param params 
  103.      *            Parameters of Small Suspension Window 
  104.      */  
  105.     public void setParams(WindowManager.LayoutParams params) {  
  106.         mParams = params;  
  107.     }  
  108.   
  109.     /** 
  110.      * Update the position of the small suspension window in the screen. 
  111.      */  
  112.     private void updateViewPosition() {  
  113.         mParams.x = (int) (xInScreen - xInView);  
  114.         mParams.y = (int) (yInScreen - yInView);  
  115.         windowManager.updateViewLayout(this, mParams);  
  116.     }  
  117.   
  118.     /** 
  119.      * Open the large suspension window and close the small suspension window. 
  120.      */  
  121.     private void openBigWindow() {  
  122.         MyWindowManager.createBigWindow(getContext());  
  123.         MyWindowManager.removeSmallWindow(getContext());  
  124.     }  
  125.   
  126.     /** 
  127.      * Used to get the height of the status bar. 
  128.      *  
  129.      * @return Returns the pixel value of the height of the status bar. 
  130.      */  
  131.     private int getStatusBarHeight() {  
  132.         if (statusBarHeight == 0) {  
  133.             try {  
  134.                 Class<?> c = Class.forName("com.android.internal.R$dimen");  
  135.                 Object o = c.newInstance();  
  136.                 Field field = c.getField("status_bar_height");  
  137.                 int x = (Integer) field.get(o);  
  138.                 statusBarHeight = getResources().getDimensionPixelSize(x);  
  139.             } catch (Exception e) {  
  140.                 e.printStackTrace();  
  141.             }  
  142.         }  
  143.         return statusBarHeight;  
  144.     }  

Among them, the onTouchEvent event of the View is rewritten to achieve drag and click effects. If the ACTION_DOWN event is found to have been triggered by the user, data such as coordinates when pressed will be recorded. If it is found that the user triggered the ACTION_MOVE event, the position of the suspension window in the screen is updated according to the currently moving coordinates. If the ACTION_UP event is triggered by the user, it will be compared with the coordinates recorded in ACTION_DOWN. If it is found to be the same, it will be considered that the user clicked on the suspension window. Click on the small suspension window to open the large suspension window, and then we can realize the view of the large suspension window.


Add the following code in Float Windows BigView:

  1. public class FloatWindowBigView extends LinearLayout {  
  2.   
  3.     /** 
  4.      * Recording Width of Large Suspension Window 
  5.      */  
  6.     public static int viewWidth;  
  7.   
  8.     /** 
  9.      * Recording the Height of Large Suspension Window 
  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.                 //When you click Close the Suspension Window, remove all the Suspension Windows and stop Service  
  25.                 MyWindowManager.removeBigWindow(context);  
  26.                 MyWindowManager.removeSmallWindow(context);  
  27.                 Intent intent = new Intent(getContext(), FloatWindowService.class);  
  28.                 context.stopService(intent);  
  29.             }  
  30.         });  
  31.         back.setOnClickListener(new OnClickListener() {  
  32.             @Override  
  33.             public void onClick(View v) {  
  34.                 //When clicking back, remove the large suspension window and create the small suspension window  
  35.                 MyWindowManager.removeBigWindow(context);  
  36.                 MyWindowManager.createSmallWindow(context);  
  37.             }  
  38.         });  
  39.     }  
  40. }  

Compared with Float Windows SmallView, Float Windows BigView is much simpler. There are only two buttons, click the close button, remove all the suspended windows and terminate the Service. Clicking the back button removes the large suspension window and recreates the small suspension window.


Now that both views of the suspension windows have been written, let's create MyWindows Manager. The code is as follows:

  1. public class MyWindowManager {  
  2.   
  3.     /** 
  4.      * Examples of Small Suspension Window View 
  5.      */  
  6.     private static FloatWindowSmallView smallWindow;  
  7.   
  8.     /** 
  9.      * Examples of Large Suspension Window View 
  10.      */  
  11.     private static FloatWindowBigView bigWindow;  
  12.   
  13.     /** 
  14.      * Parameters of View with Small Suspension Window 
  15.      */  
  16.     private static LayoutParams smallWindowParams;  
  17.   
  18.     /** 
  19.      * Parameters of View with Large Suspension Window 
  20.      */  
  21.     private static LayoutParams bigWindowParams;  
  22.   
  23.     /** 
  24.      * Used to control the addition or removal of suspended windows on the screen 
  25.      */  
  26.     private static WindowManager mWindowManager;  
  27.   
  28.     /** 
  29.      * Used to get the available memory of mobile phone 
  30.      */  
  31.     private static ActivityManager mActivityManager;  
  32.   
  33.     /** 
  34.      * Create a small suspension window. The initial position is in the middle of the right side of the screen. 
  35.      *  
  36.      * @param context 
  37.      *            Must be Context for the application. 
  38.      */  
  39.     public static void createSmallWindow(Context context) {  
  40.         WindowManager windowManager = getWindowManager(context);  
  41.         int screenWidth = windowManager.getDefaultDisplay().getWidth();  
  42.         int screenHeight = windowManager.getDefaultDisplay().getHeight();  
  43.         if (smallWindow == null) {  
  44.             smallWindow = new FloatWindowSmallView(context);  
  45.             if (smallWindowParams == null) {  
  46.                 smallWindowParams = new LayoutParams();  
  47.                 smallWindowParams.type = LayoutParams.TYPE_PHONE;  
  48.                 smallWindowParams.format = PixelFormat.RGBA_8888;  
  49.                 smallWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL  
  50.                         | LayoutParams.FLAG_NOT_FOCUSABLE;  
  51.                 smallWindowParams.gravity = Gravity.LEFT | Gravity.TOP;  
  52.                 smallWindowParams.width = FloatWindowSmallView.viewWidth;  
  53.                 smallWindowParams.height = FloatWindowSmallView.viewHeight;  
  54.                 smallWindowParams.x = screenWidth;  
  55.                 smallWindowParams.y = screenHeight / 2;  
  56.             }  
  57.             smallWindow.setParams(smallWindowParams);  
  58.             windowManager.addView(smallWindow, smallWindowParams);  
  59.         }  
  60.     }  
  61.   
  62.     /** 
  63.      * Remove the small suspension window from the screen. 
  64.      *  
  65.      * @param context 
  66.      *            Must be Context for the application. 
  67.      */  
  68.     public static void removeSmallWindow(Context context) {  
  69.         if (smallWindow != null) {  
  70.             WindowManager windowManager = getWindowManager(context);  
  71.             windowManager.removeView(smallWindow);  
  72.             smallWindow = null;  
  73.         }  
  74.     }  
  75.   
  76.     /** 
  77.      * Create a large suspension window. The position is in the middle of the screen. 
  78.      *  
  79.      * @param context 
  80.      *            Must be Context for the application. 
  81.      */  
  82.     public static void createBigWindow(Context context) {  
  83.         WindowManager windowManager = getWindowManager(context);  
  84.         int screenWidth = windowManager.getDefaultDisplay().getWidth();  
  85.         int screenHeight = windowManager.getDefaultDisplay().getHeight();  
  86.         if (bigWindow == null) {  
  87.             bigWindow = new FloatWindowBigView(context);  
  88.             if (bigWindowParams == null) {  
  89.                 bigWindowParams = new LayoutParams();  
  90.                 bigWindowParams.x = screenWidth / 2 - FloatWindowBigView.viewWidth / 2;  
  91.                 bigWindowParams.y = screenHeight / 2 - FloatWindowBigView.viewHeight / 2;  
  92.                 bigWindowParams.type = LayoutParams.TYPE_PHONE;  
  93.                 bigWindowParams.format = PixelFormat.RGBA_8888;  
  94.                 bigWindowParams.gravity = Gravity.LEFT | Gravity.TOP;  
  95.                 bigWindowParams.width = FloatWindowBigView.viewWidth;  
  96.                 bigWindowParams.height = FloatWindowBigView.viewHeight;  
  97.             }  
  98.             windowManager.addView(bigWindow, bigWindowParams);  
  99.         }  
  100.     }  
  101.   
  102.     /** 
  103.      * Remove the large suspension window from the screen. 
  104.      *  
  105.      * @param context 
  106.      *            Must be Context for the application. 
  107.      */  
  108.     public static void removeBigWindow(Context context) {  
  109.         if (bigWindow != null) {  
  110.             WindowManager windowManager = getWindowManager(context);  
  111.             windowManager.removeView(bigWindow);  
  112.             bigWindow = null;  
  113.         }  
  114.     }  
  115.   
  116.     /** 
  117.      * Update the data on the TextView of the small suspension window to show the percentage of memory usage. 
  118.      *  
  119.      * @param context 
  120.      *            The application context can be passed in. 
  121.      */  
  122.     public static void updateUsedPercent(Context context) {  
  123.         if (smallWindow != null) {  
  124.             TextView percentView = (TextView) smallWindow.findViewById(R.id.percent);  
  125.             percentView.setText(getUsedPercentValue(context));  
  126.         }  
  127.     }  
  128.   
  129.     /** 
  130.      * Whether there are suspension windows (including small suspension windows and large suspension windows) on the screen. 
  131.      *  
  132.      * @return A suspension window is displayed on the desktop to return true, and false if not. 
  133.      */  
  134.     public static boolean isWindowShowing() {  
  135.         return smallWindow != null || bigWindow != null;  
  136.     }  
  137.   
  138.     /** 
  139.      * If the Windows Manager has not been created, a new Windows Manager is created and returned. Otherwise, return the Windows Manager that you currently created. 
  140.      *  
  141.      * @param context 
  142.      *            Must be Context for the application. 
  143.      * @return WindowManager Examples for controlling the addition or removal of suspended windows on the screen. 
  144.      */  
  145.     private static WindowManager getWindowManager(Context context) {  
  146.         if (mWindowManager == null) {  
  147.             mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  
  148.         }  
  149.         return mWindowManager;  
  150.     }  
  151.   
  152.     /** 
  153.      * If the Activity Manager has not been created, a new Activity Manager is created and returned. Otherwise, return the ActiveyManager that is currently created. 
  154.      *  
  155.      * @param context 
  156.      *            The application context can be passed in. 
  157.      * @return ActivityManager An example is used to obtain the available memory of the mobile phone. 
  158.      */  
  159.     private static ActivityManager getActivityManager(Context context) {  
  160.         if (mActivityManager == null) {  
  161.             mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);  
  162.         }  
  163.         return mActivityManager;  
  164.     }  
  165.   
  166.     /** 
  167.      * Calculate the percentage of memory used and return it. 
  168.      *  
  169.      * @param context 
  170.      *            The application context can be passed in. 
  171.      * @return The percentage of memory used is returned as a string. 
  172.      */  
  173.     public static String getUsedPercentValue(Context context) {  
  174.         String dir = "/proc/meminfo";  
  175.         try {  
  176.             FileReader fr = new FileReader(dir);  
  177.             BufferedReader br = new BufferedReader(fr, 2048);  
  178.             String memoryLine = br.readLine();  
  179.             String subMemoryLine = memoryLine.substring(memoryLine.indexOf("MemTotal:"));  
  180.             br.close();  
  181.             long totalMemorySize = Integer.parseInt(subMemoryLine.replaceAll("\\D+"""));  
  182.             long availableSize = getAvailableMemory(context) / 1024;  
  183.             int percent = (int) ((totalMemorySize - availableSize) / (float) totalMemorySize * 100);  
  184.             return percent + "%";  
  185.         } catch (IOException e) {  
  186.             e.printStackTrace();  
  187.         }  
  188.         return "Suspension window";  
  189.     }  
  190.   
  191.     /** 
  192.      * Gets the currently available memory and returns data in bytes. 
  193.      *  
  194.      * @param context 
  195.      *            The application context can be passed in. 
  196.      * @return Currently available memory. 
  197.      */  
  198.     private static long getAvailableMemory(Context context) {  
  199.         ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();  
  200.         getActivityManager(context).getMemoryInfo(mi);  
  201.         return mi.availMem;  
  202.     }  
  203.   
  204. }  

This class is responsible for controlling the creation and removal of large suspension windows, small suspension windows, and the calculation of the percentage of system memory usage.


At this point, almost all the code has been written. Then let's take a look at the AndroidManifest.xml file, which contains the following code:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.demo.floatwindowdemo"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />  
  8.   
  9.     <uses-sdk  
  10.         android:minSdkVersion="8"  
  11.         android:targetSdkVersion="8" />  
  12.   
  13.     <application  
  14.         android:allowBackup="true"  
  15.         android:icon="@drawable/ic_launcher"  
  16.         android:label="@string/app_name"  
  17.         android:theme="@style/AppTheme" >  
  18.         <activity  
  19.             android:name="com.demo.floatwindowdemo.MainActivity"  
  20.             android:label="@string/app_name" >  
  21.             <intent-filter>  
  22.                 <action android:name="android.intent.action.MAIN" />  
  23.   
  24.                 <category android:name="android.intent.category.LAUNCHER" />  
  25.             </intent-filter>  
  26.         </activity>  
  27.           
  28.         <service android:name=".FloatWindowService"></service>  
  29.     </application>  
  30.   
  31. </manifest>  

Simple, remember to register Activity and Service in it. There is also a permission declaration to add android.permission.SYSTEM_ALERT_WINDOW, indicating that user authorization is required to allow the creation of system prompt window, that is, our desktop suspension window.


Now let's run the project. The effect is as follows. There is only one simple button in the main interface. After clicking the button, Activity is closed and the small suspension window is displayed on the desktop. It shows the percentage of current memory usage.


            


The small suspension window can be dragged freely. If other applications are opened, the small suspension window will be hidden automatically, and the small suspension window will appear again after returning to the desktop.


           


If you click on the small suspension window, it will pop up the large suspension window. Here, the large suspension window is easy to do. There are only two buttons. All other applications of the phone are not available when the large suspension window is displayed, because the focus is on the suspension window. Clicking the return button will reappear the small suspension window, clicking the close suspension window button, and the Service will stop together.




The 360 mobile phone guard's one-click acceleration function will not be done, just like the lonely nine swords, the important thing is swordsmanship rather than swordsmanship. I believe that after you learn the basic principles of creating suspension windows, you can make something more creative than 360.

If you have any questions, please leave a message below.


Friends interested in desktop suspension windows can continue reading. Android Desktop Suspension Window Advancement, QQ Mobile Housekeeping Rocket Effect Realization .


Download the source code, please click here


Supplement:

A friend responded to me that the above code would crash on Android 3.0 or above. I looked at it, and it was true. The main reason is that after 3.0, if you want to get a running task, you need to add a permission statement. Add in Android Manifest.xml
<uses-permission android:name="android.permission.GET_TASKS" /> 
This problem can be solved.

Keywords: Android Windows Mobile xml

Added by Ashoar on Thu, 27 Jun 2019 00:30:21 +0300