Android 进程保活总结

目标

我们观察到,当APP在后台运行或者使用清理工具清理后,无法再收到服务器的推送通知,有些非常重要的消息无法及时收到,为了收到这些消息并提示用户,我们需要保持APP后台推送接收一直在工作状态。

网上流传的保活方案

从APP结束的原因来看,APP的主要终结者是LMK和各类第三方清理工具,要保持app的活跃,一方面可以防止被杀入手,另一方面可以从被杀后再次启动入手,下面详细说明。

设置为系统应用

系统应用不会被杀的,具体设置方法是在AndroidManifest.xml中为入android:persistent=true,并将app安装到/system/app目录下。这个,一般应用做不到啊。

提升进程优先级,防止被LMK杀掉

The Android system tries to maintain an application process for as long as possible, but eventually needs to remove old processes to reclaim memory for new or more important processes. To determine which processes to keep and which to kill, the system places each process into an “importance hierarchy” based on the components running in the process and the state of those components. Processes with the lowest importance are eliminated first, then those with the next lowest importance, and so on, as necessary to recover system resources.

android系统尽可能保证APP长期运行,但是在资源不足的时候,会杀掉那些它认为不重要的进程,这个功能叫LMK,即Low memory killer。系统对进程进行了重要性分类:

  • Foreground process
  • Visible process
  • Service process
  • Background process
  • Empty process

优先级从高到低,系统会优先杀掉低级别的进程来释放资源,因此要防止被LMK杀掉,就要努力提升自己的优先级别或者在被杀掉后立即启动。

设置前台服务

public final void startForeground(int id, Notification notification);

使用这个方法,可以将service由Service process提升到Foreground process级别,可以极大地防止被LMK杀掉,会在通知栏上显示图标,隐藏图标的方法是用两个不同的service使用同样的消息ID调用startForeground,然后其中一个服务执行一次stopForeground(true),这样就可以隐藏通知栏图标了。

public class KeepAliveService extends Service {
    private static int NOTIFICATION_ID = 0x2333;

    void setForeground() {
        startForeground(NOTIFICATION_ID, new Notification());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            startService(new Intent(this, InnerService.class));
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        setForeground();
        return Service.START_STICKY;
    }

    public static class InnerService extends Service {
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            startForeground(NOTIFICATION_ID, new Notification());
            stopForeground(true);
            stopSelf();
            return super.onStartCommand(intent, flags, startId);
        }
    }
}

在服务的onStartCommand中返回START_STICKY

设置后在被LMK杀掉之后,如果有多余的资源,系统会启动此服务。

在服务的onDestroy中重新启动服务

这个可以用来对抗通过 应用管理-》正在运行-》停止 结束APP,但是对应用管理-》已下载-》强制停止无效。

    @Override
    public void onDestroy() {
        Log.i(TAG, "KeepAliveService destroy");
        mIsRunning = false;
        startService(new Intent(this, KeepAliveService.class));
    }

开机启动APP

 <receiver
     android:name=".KeepAliveReceiver"
     android:process=":keep_alive">
     <intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED" />
     </intent-filter>
 </receiver>

如果自动动权限被拦截,则不会开机启动

闹钟唤醒APP

注册闹钟,让闹钟唤醒APP

账号同步唤醒APP

创建一个账号并设置同步器,创建周期同步,系统会自动调用同步器,这样就能激活我们的APP,局限是国产机会修改最短同步周期(魅蓝NOTE2长达30分钟),并且需要联网才能使用。

native方案

这个在5.0以前一般都没有问题,适应绝大部分手机,主要实现原理是在native层建立两个进程互相监控,一旦发现对方死亡立即重启,在5.0及以上版本暂时没有找到可行方案(网上有实现说可以,但是亲测不行,可能只在部分手机上可以实现)。

推送平台唤醒

发现同一个推送平台,如果有一个APP收到推送消息,可能会唤醒使用同推送平台的其他APP.

提示用户将APP加入白名单

这个应该是最好的办法,但也是最难的办法,最好的意思是不会再被杀,最难是怎么提示用户去操作,因为各种定制的系统以及各种第三方APP的设置方法都不一样。比如魅族会在待机3分钟后只保留白名单里面的应用,比如小米的神隐模式会禁止应用访问网络,这样就需要做大量的适配工作。

参考文章

Processes and Threads
细数利用android系统机制的保活手段

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值