Android process keep alive (1)

insert image description here

Recently, according to the company's project requirements, it is necessary to add process keep alive to the application.
Here is a brief description of the requirements. Since the App is connected to Bluetooth to receive real-time data, and the amount of data is large;
when the user operates the App to obtain real-time data, it is impossible to keep looking at the mobile phone screen.
At this time, the mobile phone usually has a black screen or a locked screen. Sometimes it will lead to data loss;
in the application I made, data is very important, so data loss is also a fatal problem!

Android process keep alive (1)

Android process keep alive --- start page black screen and optimal solution (2)

On how to deal with this issue, I also read a lot of information.
After all, this problem has been solved or dealt with a long time ago,
but there are too many and complicated information on the Internet, and the practicability needs to be considered.
Today, I will summarize the solution that I have applied and the effect is very nice!


process keep alive

To solve this problem, there are a total of the following technologies:

1 Pixel Activity , Foreground Service , Account Synchronization , Jobscheduler , Mutual Awakening , System Service Bundling , 但是我在这里应用的是1像素Activity.

A preliminary understanding of the process

After each Android application is started, it corresponds to at least one process, and some have multiple processes, and the proportion of applications with multiple processes in mainstream applications is relatively large.

How to View Basic Process Information

adb shell ps|grep <package_name>

insert image description here

23924  进程ID
23902  进程的父进程ID
com.harry.glucose.application 进程名

process division

The process in Android is the same as the feudal society, divided into three classes and nine classes. The Android system divides the process into the following types (from high to low in importance), which have been summarized in detail by many great gods on the Internet (Note: Strictly speaking, it is a division 6 kinds).

Foreground process

Visible scene:

  1. A process holds an Activity that is interacting with the user and the Activity is in the resume state.
  2. A process holds a Service, and the Service is bound to the Activity that the user is interacting with.
  3. A process holds a Service, and the Service calls the startForeground() method to make it run in the foreground.
  4. A process holds a Service, and the Service is executing one of its life cycle callback methods, such as onCreate(),
    onStart() or onDestroy().
  5. A process holds a BroadcastReceiver, and the BroadcastReceiver is executing its onReceive() method.

Generally, the system will not kill the foreground process of the program that the user is using, unless the user forcibly stops the application or the system runs out of memory and other extreme circumstances will kill it.

Visible process

scenes to be used:

  1. Owns an Activity that is not in the foreground but is still visible to the user (onPause() has been called).
  2. Have a Service bound to a visible (or foreground) Activity.

The user is using it, can see it, but cannot touch it, does not cover the entire screen, and only a part of the screen. The visible process does not contain any foreground components. Generally, the system will not kill the visible process unless resources are tight. Keep one or more foreground processes alive.

Service process

Scenes:

  • A Service is running in a process and the Service is started by startService(), which is not directly related to the interface seen by the user.

In the case of insufficient memory to keep all foreground and visible processes running simultaneously, the service process will be killed.

Background process

Scenes:

  • After the user presses "back" or "home", the program itself cannot be seen, but the program that is actually still running, such as the Activity calling the onPause method, the system may terminate them at any time to reclaim memory.

Empty process

  • When a process does not contain any active components, the process will be set as an empty process. It is completely useless. Killing it will only benefit and not harm. Be the first to do it!

memory threshold

The above is the classification of the process, how is the process killed?

Considering the experience and performance of the system, the system does not actually kill the process when the app exits to the background, but caches it.

The more apps you have open, the more processes are cached in the background.

In the case of insufficient system memory, the system starts to judge which processes to kill based on its own set of process recycling mechanisms to free up memory to supply needed apps. This mechanism for killing processes and reclaiming memory is called Low Memory Killer.

Then how to define this deficiency, that is the memory threshold, we can use cat /sys/module/lowmemorykiller/parameters/minfree to check the memory threshold of a mobile phone.

insert image description here

In fact, the system also has a set of strict policies for process recycling similar to memory recycling. You can understand it by yourself. It is roughly like this. The larger the oom_adj is, the more physical memory it takes up, and it will be killed first . OK, so what about the process now? The problem of keeping alive is transformed into, 如何降低 oom_adj 的值,以及如何使得我们应用占的内存最少.

The manufacturer of each mobile phone may be different. The oom_adj value mainly has the following values, you can refer to it↓↓↓

insert image description here

Process keep alive scheme

The above several solutions, in the end I used 1 pixel Activity in the project application.

1 pixel principle:

The basic idea is that the system generally does not kill the foreground process. Therefore, to make the process permanent, you can pass the whitelist;

But when we use 1 pixel here, we only need to start an activity in this process when the screen is locked or black. In order to deceive users, the size of this activity is 1 pixel , and it is transparent without switching dynamics . When the screen is turned on, close the Activity.

If you start an Activity directly, when we press the back key to return to the desktop, as oom_adj的值是8mentioned above, this process is easy to be recycled when resources are insufficient.

Actual operation:

By monitoring the system lock screen broadcast, the process keeping alive solution is realized.

Create a 1 pixel Activity

/**
 * @author 拉莫帅
 * @date 2023/2/2
 * @address
 * @Desc 1像素
 */
public class PixelActivity extends Activity {
    
    

    private static final String TAG = PixelActivity.class.getSimpleName();

    public static void actionToLiveActivity(Context pContext){
    
    
        Intent intent = new Intent(pContext, PixelActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        pContext.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pixel);
        Log.e(TAG, "onCreate: " );

        Window window = getWindow();
        //放到左上角
        window.setGravity(Gravity.START | Gravity.TOP);
        WindowManager.LayoutParams attributes = window.getAttributes();
        //宽高设计为1个像素
        attributes.width = 1;
        attributes.height = 1;
        //起始坐标
        attributes.x = 0;
        attributes.y = 0;
        window.setAttributes(attributes);

        ScreenManager.getInstance(this).setActivity(this);
    }

    @Override
    protected void onStart() {
    
    
        super.onStart();
        Log.e(TAG, "onStart: " );
    }

    @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        Log.e(TAG, "onDestroy: " );
    }
}

set the current theme (exception)

There is another very important step here. Be sure to set a theme for the current 1-pixel Activity , otherwise 黑屏something will happen, and the next article will summarize it for you .

    <!-- 设置1像素主题-->
    <style name="APPTheme" parent="@android:style/Theme.Holo.NoActionBar">
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowAnimationStyle">@null</item>
        <item name="android:windowNoTitle">true</item>
    </style>

AndroidManifest.xml

<activity android:name=".PixelActivity"
            android:theme="@style/APPTheme"/>

Monitor system lock screen broadcast

Start PixelActivity when the screen is off, and turn off PixelActivity when the screen is on, so you need to monitor the system lock screen broadcast, and notify MainActivity to start or close PixelActivity in the form of an interface.

/**
 * @author 拉莫帅
 * @date 2023/2/2
 * @address
 * @Desc 监听系统开/锁屏广播
 */
public class ScreenBroadcastListener {
    
    

    private Context mContext;

    private ScreenBroadcastReceiver mScreenReceiver;

    private ScreenStateListener mListener;

    public ScreenBroadcastListener(Context context) {
    
    
        mContext = context.getApplicationContext();
        mScreenReceiver = new ScreenBroadcastReceiver();
    }

    interface ScreenStateListener {
    
    

        void onScreenOn();

        void onScreenOff();
    }

    /**
     * screen状态广播接收者
     */
    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)) {
    
     // 开屏
                mListener.onScreenOn();
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
    
     // 锁屏
                mListener.onScreenOff();
            }
        }
    }

    public void registerListener(ScreenStateListener listener) {
    
    
        mListener = listener;
        registerListener();
    }

    private void registerListener() {
    
    
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        mContext.registerReceiver(mScreenReceiver, filter);
    }
}
public class ScreenManager {
    
    

    private Context mContext;

    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() {
    
    
        PixelActivity.actionToLiveActivity(mContext);
    }

    public void finishActivity() {
    
    
        //结束掉LiveActivity
        if (mActivityWref != null) {
    
    
            Activity activity = mActivityWref.get();
            if (activity != null) {
    
    
                activity.finish();
            }
        }
    }
}

active page call

public class MainActivity extends Activity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ScreenManager screenManager = ScreenManager.getInstance(MainActivity.this);
        ScreenBroadcastListener listener = new ScreenBroadcastListener(this);
        listener.registerListener(new ScreenBroadcastListener.ScreenStateListener() {
    
    
            @Override
            public void onScreenOn() {
    
    
                screenManager.finishActivity();
            }

            @Override
            public void onScreenOff() {
    
    
                screenManager.startActivity();
            }
        });
    }
}

Start PixelActivity when the screen is off, and turn off PixelActivity when the screen is on, so you need to monitor the system lock screen broadcast, and notify MainActivity to start or close PixelActivity in the form of an interface.

results of testing

Finally, run to the real machine Huawei, Xiaomi, Redmi Android 6.0, 9.0, 11.0, 12.0 and the result is ojbk. Later, Hongmeng real machine needs to be debugged to see the result.

Extra Story

There is another solution, but I personally do not recommend it;
if the active page has many functions, adding this solution will not only consume time, but also consume power.

Loop silent music

Randomly find a silent music on the Internet, the main thing is to let it play the music in a continuous loop. The same test is the real machine Huawei P9, 7.0, EMUI 5.0.

Main function: play music

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    
    
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                startPlayMusic();
            }
        }).start();
        return START_STICKY;
    }


       Recently, I took a break from my busy schedule, ↓↓↓↓[ Who’s De Code Farmer Mr. Chen ]↓↓↓↓, I will share technical blog posts and high-energy information content with you regularly! Welcome all bosses to like and follow, you are my source of motivation!

Guess you like

Origin blog.csdn.net/chen_md/article/details/128867458