美文网首页
进程保活

进程保活

作者: Coder_Sven | 来源:发表于2019-12-18 11:38 被阅读0次

进程保活的关键点有两个,一个是进程优先级的理解,优先级越高存活几率越大。二是弄清楚哪些场景会导致进程会kill,然后采取下面的策略对各种场景进行优化:

  1. 提高进程的优先级
  2. 在进程被kill之后能够唤醒

进程优先级

Android一般的进程优先级划分:
​ 1.前台进程 (Foreground process)
​ 2.可见进程 (Visible process)
​ 3.服务进程 (Service process)
​ 4.后台进程 (Background process)
​ 5.空进程 (Empty process)
​ 这是一种粗略的划分,进程其实有一种具体的数值,称作oom_adj,注意:数值越大优先级越低:

1,Activity提权

原理:监控手机锁屏解锁事件,在屏幕锁屏时启动1个像素透明的 Activity,在用户解锁时将 Activity 销毁掉,从而达到提高进程优先级的作用。

造一个一个像素的Activity

public class KeepActivity extends Activity {
    private static final String TAG = "KeepActivity";
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG,"启动Keep");
        Window window = getWindow();
        //设置这个activity在左上角
        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);

        KeepManager.getInstance().setKeepActivity(this);
    }
}

监听系统开屏或者息屏的广播

public class KeepReceiver extends BroadcastReceiver {
    private static final String TAG = "KeepReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.e(TAG, "receive:" + action);
        if (TextUtils.equals(action, Intent.ACTION_SCREEN_OFF)) {
            //灭屏 开启1px activity
            KeepManager.getInstance().startKeep(context);
        } else if (TextUtils.equals(action, Intent.ACTION_SCREEN_ON)) {
            //亮屏 关闭
            KeepManager.getInstance().finishKeep();
        }
    }
}
public class KeepManager {
    private static final KeepManager ourInstance = new KeepManager();

    public static KeepManager getInstance() {
        return ourInstance;
    }

    private KeepManager() {
    }
    private KeepReceiver keepReceiver;
    private WeakReference<Activity> mKeepActivity;
    /**
     * 注册
     * @param context
     */
    public void registerKeepReceiver(Context context){
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        keepReceiver = new KeepReceiver();
        context.registerReceiver(keepReceiver, filter);
    }

    /**
     * 反注册
     * @param context
     */
    public void unRegisterKeepReceiver(Context context){
        if (null != keepReceiver) {
            context.unregisterReceiver(keepReceiver);
        }
    }

    /**
     * 启动1个像素的KeepActivity
     * @param context
     */
    public void startKeep(Context context) {
        Intent intent = new Intent(context, KeepActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    /**
     * finish1个像素的KeepActivity
     */
    public void finishKeep() {
        if (null != mKeepActivity) {
            Activity activity = mKeepActivity.get();
            if (null != activity) {
                activity.finish();
            }
            mKeepActivity = null;
        }
    }

    public void setKeepActivity(KeepActivity mKeepActivity) {
        this.mKeepActivity = new WeakReference<Activity>(mKeepActivity);
    }
}

2,Service提权

创建一个前台服务用于提高app在按下home键之后的进程优先级

startForeground(ID,Notification):使Service成为前台Service。 前台服务需要在通知栏显示一条通知

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

    @Override
    public void onCreate() {
        super.onCreate();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("sven", "sven",
                    NotificationManager.IMPORTANCE_LOW);
            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            if (manager == null)
                return;
            manager.createNotificationChannel(channel);

            Notification notification = new NotificationCompat.Builder(this, "sven").setAutoCancel(true).setCategory(
                    Notification.CATEGORY_SERVICE).setOngoing(true).setPriority(
                    NotificationManager.IMPORTANCE_LOW).build();
            startForeground(10, notification);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            //如果 18 以上的设备 启动一个Service startForeground给相同的id
            //然后结束那个Service
            startForeground(10, new Notification());
            startService(new Intent(this, InnnerService.class));
        } else {
            startForeground(10, new Notification());
        }
    }

    public static class InnnerService extends Service {

        @Override
        public void onCreate() {
            super.onCreate();

            //发送相同的Notification,然后将其取消并取消自己的前台显示
            Notification.Builder builder = new Notification.Builder(this);
            startForeground(10, new Notification());
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    stopForeground(true);
                    NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                    manager.cancel(10);
                    stopSelf();
                }
            },100);
        }

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

3,广播拉活

在发生特定系统事件时,系统会发出广播,通过在 AndroidManifest 中静态注册对应的广播监听器,即可在发生响应事件时拉活。但是从android 7.0开始,对广播进行了限制,而且在8.0更加严格

4,全家桶拉活

有多个app在用户设备上安装,只要开启其中一个就可以将其他的app也拉活。比如手机里装了手Q、QQ空间、兴趣部落等等,那么打开任意一个app后,其他的app也都会被唤醒。

5,Service机制(Sticky)拉活

将 Service 设置为 START_STICKY,利用系统机制在 Service 挂掉后自动拉活

只要 targetSdkVersion 不小于5,就默认是 START_STICKY。
但是某些ROM 系统不会拉活。并且经过测试,Service 第一次被异常杀死后很快被重启,第二次会比第一次慢,第三次又会比前一次慢,一旦在短时间内 Service 被杀死4-5次,则系统不再拉起。

6,JobScheduler拉活

JobScheduler允许在特定状态与特定时间间隔周期执行任务。可以利用它的这个特点完成保活的功能,效果即开启一个定时器,与普通定时器不同的是其调度由系统完成。

@SuppressLint("NewApi")
public class MyJobService extends JobService {
    private static final String TAG = "MyJobService";

    public static void startJob(Context context) {
        JobScheduler jobScheduler = (JobScheduler) context.getSystemService(
                Context.JOB_SCHEDULER_SERVICE);
        JobInfo.Builder builder = new JobInfo.Builder(10,
                new ComponentName(context.getPackageName(),
                        MyJobService.class.getName())).setPersisted(true);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            //7.0以上延迟1s执行
            builder.setMinimumLatency(1000);
        }else{
            //每隔1s执行一次job
            builder.setPeriodic(1000);
        }
        jobScheduler.schedule(builder.build());
    }

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        Log.e(TAG,"开启job");
        //7.0以上轮询
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            startJob(this);
        }

        return false;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        return false;
    }
}

7,推送拉活

根据终端不同,在小米手机(包括 MIUI)接入小米推送、华为手机接入华为推送。

8,Native拉活

Native fork子进程用于观察当前app主进程的存亡状态。对于5.0以上成功率极低。

9,双进程守护

两个进程共同运行,如果有其中一个进程被杀,那么另外一个进程就会将被杀的进程重新拉起

参考代码:

[https://github.com/games2sven/ProcessLiving]:

相关文章

  • 第十六周 进程保活

    话题:进程保活 这个问题时常在面试中被问到关键字:Android 进程保活招式大全 参考答案 1.进程保活方案 -...

  • 进程保活与拉活

    进程相关知识梳理 Activity 1像素保活 前台服务保活 账户同步拉活 JobScheduler 拉活 双进程...

  • 关于进程保活的两三事——新手升级经验卡

    首先,先搁下几个问题,什么是进程保活?为什么要有进程保活?最后才是进程保活要怎么实现??相信大家会迫不及待跳到最后...

  • Android进程保活实践总结

    Android进程保活

  • 深度剖析APP保活案例

    这是作者在去年处理的一个关于进程保活的案例 一. 引言 1.1 保活概述 什么是保活?保活就是在用户主动杀进程,或...

  • 关于 Android 进程保活

    关于 Android 进程保活 Android进程保活手段主要分3种: 1:利用不同的app进程使用广播来进...

  • 进程保活方案学习

    进程保活方案 进程保活主要有两个方案 提高进程优先级,降低死亡几率 在进程被杀死后进行拉活 进程为什么会死亡 从L...

  • 进程保活

    https://www.cnblogs.com/bugly/p/5765334.html

  • 进程保活

    https://mp.weixin.qq.com/s/r3-5Y_e_0fq3_7a8kdGWog

  • 进程保活

    Service service:是一个后台服务,专门用来处理常驻后台的工作的组件。 Service被强的原因: 内...

网友评论

      本文标题:进程保活

      本文链接:https://www.haomeiwen.com/subject/pqnxjctx.html