提高app进程存活率

Appp提高进程存活率

  • 系统由于体验和性能的考虑,app在退到后台时系统不会kill掉这个进程,而是将其缓存起来。
  • 打开应用越多,后台缓存的应用也越多。
  • 在系统内存不足的情况下,系统开始依据自身的一套进程进程回收机制来判断要kill哪些进程,来释放内存供前台应用使用。杀进程回收内存的机制叫做 Low Memory Killer
    avatar

我们所要做的就是尝试把处于后台的低优先级应用,提升到高优先级甚至关键优先级。
我们要了解一下内存阈值这个概念:当进程所使用的内存超过这个值的时候系统会抛出oom杀掉该进程,只是表示进程使用内存超过了限制而不是说现在内存不足了。每个手机有各自的不同的内存阈值。内存阈值可以通过adb shell 命令查看
真机必须是root的才可以查看。

adb shell cat /sys/module/lowmemorykiller/parameters/minfree

一般会有6个输出值(单位为4KB)
输出的数值依次为:

  • 前台进程阈值
  • 可见进程阈值
  • 服务进程阈值
  • 后台进程阈值
  • contendProvider阈值
  • 空进程阈值
adj级别 解释
UNKNOWN_ADJ 16 预留的最低级别,一般对于缓存的进程才有可能设置成这个级别
CACHED_APP_MAX_ADJ 15 缓存进程,空进程,在内存不足的情况下就会优先被kill
CACHED_APP_MIN_ADJ 9 缓存进程,也就是空进程
SERVICE_B_ADJ 8 不活跃的进程
PREVIOUS_APP_ADJ 7
HOME_APP_ADJ 6 与Home交互的进程
SERVICE_ADJ 5 有Service的进程
HEAVY_WEIGHT_APP_ADJ 4 高权重进程
BACKUP_APP_ADJ 3 正在备份的进程
PERCEPTIBLE_APP_ADJ 2 可感知的进程,比如那种播放音乐
VISIBLE_APP_ADJ 1 可见进程
FOREGROUND_APP_ADJ 0 前台进程
PERSISTENT_SERVICE_ADJ -11 重要进程
PERSISTENT_PROC_ADJ -12 核心进程
SYSTEM_ADJ -16 系统进程
NATIVE_ADJ -17 系统起的Native进程
adj值越高越容易被干掉
一般adj值超过3就容易被干掉

//
通过前台服务提高进程存活率
public class ForegroundService extends Service {
public static final int ID = 0x11;

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

public ForegroundService() {
}

private static final String TAG = "ForegroundService";
@Override
public void onCreate() {
    Log.d(TAG, "onCreate: ");
    super.onCreate();
    createNotificationChannel(getApplicationContext());
    NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
    Notification notification = builder.setSmallIcon(R.drawable.ic_launcher_foreground).build();
    NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());
    startForeground(ID, notification);
    startService(new Intent(this, InnerService.class));
}

public static final String CHANNEL_ID = "ForeGround";

public void createNotificationChannel(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Log.d(TAG, "createNotificationChannel: ");
        CharSequence name = "channel_name";
        String description = "channel_description";
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this
        NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

private static class InnerService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private static final String TAG = "InnerService";
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");
        //发送与KeepLiveService中ID相同的Notification,然后将其取消并取消自己的前台显示
        Notification.Builder builder = new Notification.Builder(getApplicationContext(), CHANNEL_ID);
        builder.setSmallIcon(R.drawable.ic_launcher_foreground);
        startForeground(ID, builder.build());
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "run: ");
                stopForeground(true);
                NotificationManagerCompat notificationManagerCompat = (NotificationManagerCompat) NotificationManagerCompat.from(getApplicationContext());
                notificationManagerCompat.cancel(ID);
                stopSelf();

            }
        }, 100);
    }
}

}

adb shell cat /proc/6091/oom_adj
6091:为进程id,可以在AndroidStudio上查看

// 没有前台服务时,应用退到后台进程adj值为11,使用前台进程时,app退到后台adj值为3(huaWei Nova4真机亲测)。

posted @ 2020-11-27 22:41  沙雕货  阅读(169)  评论(0编辑  收藏  举报