The idea that a process should live forever without being killed is debatable. For development, there are some requirements that you want to implement to ensure the arrival rate of messages. For users, unknown services have been living in my background processes. Like next door Lao Wang in hidden in the closet secretly output, is not very uncomfortable! For some processes, you can’t force users to whitelist you, so what can you do? We’ll just have to use some dark technology.


However, it is almost impossible to create an Android application that is not killed under any circumstances without whitelisting, and can only dramatically improve the survival rate of the process. Coercive hooligan tactics, somewhat immoral. What’s more, I am not QAQ ~ I just read their technical blog, write a few demo, demo record. First, understand the level of the process. In Android applications, processes can be divided into:

  1. The foreground process is visible on the phone page. For example, an Activity that is being onResume(); The Service that binds the Activity; Executing its onReceive() BroadcastReceiver.
  2. The visible process, while visible, is the Activity during the execution of onPause(). For example: pop-up dialog blocked Activity; The Service bound to the Activity is also downgraded.
  3. Service process, an application-independent process or a private process that is running the startService() method to start the service.
  4. The background process, with no Activity visible, executes the onStop() method.
  5. An empty process that does not contain any active application components

    The system has an oOM_adj value to identify the processes at different levels.

    Green identifies processes that are not easily recycled by the system. When the system runs out of memory, you need to run Lowmemorykiller to kill processes that are not important to the system. The rule of slicing is, according to the oOM_adj size. Start with the largest oOM_adj. When two oom_adj are of the same size, kill the one with the largest memory footprint first. Wow, this is my first time using ADB command. To see if a process is alive or dead, there has to be a place to look. The Android Studio command box works like this. When debugging with a real machine, adb shell does not enter root, the corresponding corner marked “$”, its permission can only see the corresponding process list, only after the phone root or using the emulator can see the process details. It’s also a #

    Can be achieved byCat /proc/process ID/oom_adjTo look at it. Returns a value corresponding to the table above, which directly shows the level of the corresponding process. What we want to do is to hope that the level of the process we want won’t be lowered, or not lowered much, when it’s made invisible. So there is a “black technology”.

The # one-pixel Activity method seems to be well known on the web. The implementation principle is to open and close the 1-pixel Activity by listening to the phone’s screen turn on and off. This requirement can only be done, after the screen goes black, the process level will not be lowered.

Interface ScreenStateListener {void onScreenOn(); void onScreenOff(); } /** * private class ScreenBroadcastReceiver extends BroadcastReceiver {private String action = null;  @Override public void onReceive(Context context, Intent intent) { action = intent.getAction();if(intent.action_screen_on.equals (action)) {// Open mListener.onscreenon (); }else if(intent.action_screen_off.equals (action)) {// Mlistener.onscreenoff (); }}}Copy the code

This is the management class created by the 1-pixel Activity. Because the Activity is frequently created and destroyed, it is placed in the weak reference stack to facilitate memory reclamation.

public class ScreenManager { private Context mContext; // WeakReference, LiveActivity finish under application visual, create frequent private WeakReference<Activity> mActivityWref; // WeakReference, LiveActivity finish under application visual, create frequent private WeakReference<Activity> mActivityWref; public static ScreenManager gDefualt; public static ScreenManager getInstance(Context pContext) {if (gDefualt == null) {
            gDefualt = new ScreenManager(pContext.getApplicationContext());
        }
        return gDefualt;
    }
    private ScreenManager(Context pContext) {
        this.mContext = pContext;
    }

    public void setActivity(Activity pActivity) {
        mActivityWref = new WeakReference<Activity>(pActivity);
    }

    public void startActivity() {
        LiveActivity.actionToLiveActivity(mContext);
    }

    public void finishActivity() {// End the LiveActivityif(mActivityWref ! = null) { Activity activity = mActivityWref.get();if(activity ! = null) { activity.finish(); }}}}Copy the code

The specific operation of LiveService is to enable the Service when the application process is started, and monitor the on-off screen

@override public int onStartCommand(Intent Intent, int flags, int startId) {// Start an Activity when the screen is closed. The tail shut off the Activity when final ScreenManager ScreenManager = ScreenManager. GetInstance (LiveService. This); ScreenBroadcastListener listener = new ScreenBroadcastListener(this); listener.registerListener(new ScreenBroadcastListener.ScreenStateListener() {
            @Override
            public void onScreenOn() {
                screenManager.finishActivity();
            }
            @Override
            public void onScreenOff() { screenManager.startActivity(); }});return START_REDELIVER_INTENT;
    }
Copy the code

The main principle is to secretly start an Activity with no interface when the screen goes off to tell the phone that the process is active. When the screen lights up, the Activity is destroyed and replaced by the existing interface UI. However, I found that when the application is placed in the background, the oOM_adj of the application changes to 6 (background process), so the process level cannot be maintained. I’m also cute enough to start this 1 pixel in the background when an Application enters. I do the same for the Activity in the Application life cycle. Helpless.. When I entered the background, after a while, the APP was pulled up again and displayed on the page. I can’t turn it off

  @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            }

            @Override
            public void onActivityStarted(Activity activity) {
                final ScreenManager screenManager = ScreenManager.getInstance(this);
                screenManager.finishActivity();

            }
                        
            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {
               screenManager.startActivity();                   
            }
            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            }
            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        });
    }
Copy the code

Since can’t satisfy, that can only change a way of thinking… Wechat is said to use this scheme, the implementation principle is to take advantage of the Android front end vulnerability. If API<180, call startForeground(ID, new Notification()). At API>18, you need to call a secondary Service, bind to the same ID, and stop the secondary Service so that the notification bar does not show anything

public class KeepLiveService extends Service {

    public static final int NOTIFICATION_ID=0x11;

    public KeepLiveService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() { super.onCreate(); // Below API 18, send Notification directly and put it foregroundif (Build.VERSION.SDK_INT <Build.VERSION_CODES.JELLY_BEAN_MR2) {
            startForeground(NOTIFICATION_ID, new Notification());
        } else{InnerService notification. Builder Builder = new notification. Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher); startForeground(NOTIFICATION_ID, builder.build()); startService(new Intent(this, FuZhuService.class)); }}}Copy the code
public  class  FuZhuService extends Service{
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        @Override
        public void onCreate() { super.onCreate(); // Send Notification with the same ID as in KeepLiveService, then cancel it and cancel its own front display notification. Builder Builder = new notification. Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher); startForeground(NOTIFICATION_ID, builder.build()); new Handler().postDelayed(newRunnable() {
                @Override
                public void run() {
                    stopForeground(true); NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); manager.cancel(NOTIFICATION_ID); stopSelf(); }}, 100); }}Copy the code

Finally, when the application clicks back and backsets the background, the application process keeps the degree of 0 to 1, which ensures the survival rate of the process

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_REDELIVER_INTENT;
}
Copy the code
  • START_STICKY If the system is destroyed after onStartCommand returns, the system will recreate the service and call onCreate and onStartCommand in sequence (note: Android4.0 can do this), which is equivalent to restarting the service and restoring it to its previous state.

  • START_NOT_STICKY If the system is destroyed after onStartCommand returns, the system will not restart the Service if the Service is killed after the onStartCommand method is executed.

  • START_REDELIVER_INTENT Compatible version of START_STICKY. The difference is that this version does not guarantee that the service can be restarted after being killed.

It seems not very clever after use, reserved use… # summary

In conclusion, as sensible developers, we all know that every time a user closes an application, our application should die completely and free up system resources. This simple truth applies not only to mobile application development, but also to any desktop application development.

But as developers, we are more in the face of product manager development, according to the needs of various market resources, always try their best. In the case of resident processes, you still need to use three, four, and four. Of course, special needs can be considered, for better user experience is nothing to say. This article is read more on the basis of standing on the Internet of various gurus, has not reached the level of creativity. Work slowly. Since then, thank the big people on the net cow write black technology 1 black technology 2