进程保活

进程优先级:

Android一般的进程优先级划分:
1.前台进程 (Foreground process) :onResume的Activity,前台Service
2.可见进程 (Visible process):onPause的Activity
3.服务进程 (Service process)
4.后台进程 (Background process)
5.空进程 (Empty process)

进程被杀的场景:

1.点击home键使app长时间停留在后台,内存不足被kill
可以通过运行一个前台Service将进程的优先级从4提升到1,缺点是通知栏会有一条通知消息

2.进入锁屏状态一段时间,省电机制会kill后台进程
注册广播监听锁屏和解锁事件, 锁屏后启动一个1像素的透明Activity,提升进程优先级,解锁后销毁这个Activity

adb查看进程优先级:

首先进入adb shell,然后通过ps命令查询进程的pid,再用pid查询对应的优先级:

adb shell								//进入adb shell
ps										//查询进程的pid
cat /proc/&pid/oom_adj					//查询pid进程的优先级

这里查询优先级会得到一个数字,数字越小表明优先级越高
一般系统应用是一个负值,前台应用优先级是0,后台应用是一个正整数

进程保活方案:
方案1:息屏时通过广播打开一个1像素的Activity:
public class ProxyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Window window = getWindow();
        window.setGravity(Gravity.START | Gravity.TOP);
        WindowManager.LayoutParams attributes = window.getAttributes();

        attributes.width = 1;
        attributes.height = 1;

        attributes.x = 0;
        attributes.y = 0;
        window.setAttributes(attributes);
    }

    public static void launch(Activity activity) {
        Intent intent = new Intent(activity, ProxyActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        activity.startActivity(intent);
    }
}

监听屏幕的广播:

private class ScreenBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String  action = intent.getAction();
            if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏
                ProxyActivity.launch(activity)
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏
                ProxyActivity.close();
            }
        }
}

注册广播:

		ScreenBroadcastReceiver broadcast = new ScreenBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        registerReceiver(broadcast, intentFilter);

用adb查询进程优先级测试一下效果:

正常打开App,使app位于前台,或者当App位于前台时熄灭屏幕,查询优先级:

zerofltechn:/ $ cat /proc/32333/oom_adj
0

使App退到后台,或者退到后台再锁屏之后查询优先级,会得到:

zerofltechn:/ $ cat /proc/32333/oom_adj
11

采用息屏后开启Activity的方案后,将App退到后台再息屏打印该进程的优先级:

zerofltechn:/ $ cat /proc/4239/oom_adj
0

可见此方案可以在息屏情况下提升进程的优先级

方案2:用没有notification的前台Service提升App优先级

对于 API level < 18 :调用startForeground(ID, new Notification()),发送空的Notification ,图标则不会显示。
对于 API level >= 18:在需要提优先级的service A启动一个InnerService,两个服务同时startForeground,且绑定同样的 ID。Stop 掉InnerService ,这样通知栏图标即被移除。
例:

public class KeeAliveService extends Service {
    public static final int NOTIFICATION_ID = 0x11;
    @Override
    public void onCreate() {
        super.onCreate();
        if (Build.VERSION.SDK_INT < 18) {
         	//Android4.3以下 ,此方法能有效隐藏Notification上的图标
            startForeground(NOTIFICATION_ID, new Notification());
        } else if (Build.VERSION.SDK_INT >= 18 && Build.VERSION.SDK_INT < 25){
          	//Android4.3 - Android7.0,此方法能有效隐藏Notification上的图标
        	Notification.Builder builder = new Notification.Builder(this);
        	builder.setSmallIcon(R.mipmap.ic_launcher);
        	startForeground(NOTIFICATION_ID, builder.build());
        	//这里开启了另外一个前台Service,并在一段时间后杀死自己,这样可以使得KeeAliveService没有通知
        	startService(new Intent(this, InnerService.class));
        } else{
            //Android7.1 必须显示一条通知
            service.startForeground(GRAY_SERVICE_ID, new Notification());
        }
    }

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


    public static class InnerService extends Service {
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }

        @Override
        public void onCreate() {
            super.onCreate();
            //发送与KeepLiveService中ID相同的Notification,然后将其取消并取消自己的前台显示
            Notification.Builder builder = new Notification.Builder(this);
            builder.setSmallIcon(R.mipmap.ic_launcher);
            startForeground(NOTIFICATION_ID, builder.build());
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    stopForeground(true);
                    NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                    manager.cancel(NOTIFICATION_ID);
                    stopSelf();
                }
            }, 1000);
        }
    }
    
}

只要在App启动后开启KeeAliveService服务,App的优先级就会提高

基于Android7.0测试一下效果:
首先未开启这个服务时将App退到后台,或退到后台后息屏:

zerofltechn:/ $ cat /proc/9156/oom_adj
11

开启KeeAliveService,将应用退到后台,或者退到后台后息屏:

zerofltechn:/ $ cat /proc/9156/oom_adj
3

可见使用前台服务可以使App在后台时提升优先级

方案3:进程相互唤醒
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值