美文网首页APP拉活-保活内容
Android保活/拉活(二)代码实现

Android保活/拉活(二)代码实现

作者: 普通的程序员 | 来源:发表于2018-03-05 14:48 被阅读0次

之前学习保活/拉活查资料写了一篇:
Android保活/拉活(一)教程检索
https://www.jianshu.com/p/b51e2dbf2311

用到了jobSchedule,但是一直在报错,然后又偶然接触到了NotificationListenerService,决定重新再折腾一次,完整代码见文章最后。

本文所有代码参考源为检索中的文章,做了整理注释及测试,转载请贴上检索链接
https://www.jianshu.com/p/b51e2dbf2311
https://www.jianshu.com/p/ce60fcedd3d6

----正文开始
假定你已经非常明白LMK的原理,那么保活的关键点在降低oom_adj值,这样app在打开后进入后台,抗击厂商清理/第三方清理,能多苟1s
建议绑定home键和back键事件

保活

环境情况

在没有任何的保活措施情况下,前台oom_adj=0,后台7
测试机型 红米4A root 6.0


只有一个主进程

方案1.开启前台服务降低oom_adj

关键代码在创建服务,开启一个带通知栏的服务(可以再开一个服务把常驻通知栏取消,实测不影响前台服务的oom_adj)

    public void onCreate() {
        super.onCreate();
        //如果API大于18,需要弹出一个可见通知
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
            Notification.Builder builder = new Notification.Builder(this);
            builder.setSmallIcon(R.mipmap.ic_launcher);
            builder.setContentTitle("");
            builder.setContentText("");
            startForeground(NOTICE_ID, builder.build());
            // 如果觉得常驻通知栏体验不好
            // 可以通过启动CancelNoticeService,将通知移除,oom_adj值不变
            Intent intent = new Intent(this, CancelNoticeService.class);
            startService(intent);
        } else {
            startForeground(NOTICE_ID, new Notification());
        }
    }

测试效果,主进程在变为后台时0->7,服务oom_adj不变


实测效果

*锁屏情况和按home键进入后台一样

方案2.监听锁屏事件开启1像素界面

关键代码在监听锁屏事件创建一个1像素的activity到前台

public class ScreenBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (mStateReceiverListener == null) return;
            String action = intent.getAction();
            Log.d("KeepAppAlive", "SreenLockReceiver-->监听到系统广播:" + action);
            if (action == null) return;
            switch (action) {
                case Intent.ACTION_SCREEN_ON:
                    mStateReceiverListener.onScreenOn();
                    break;
                case Intent.ACTION_SCREEN_OFF:
                    mStateReceiverListener.onScreenOff();
                    break;
                case Intent.ACTION_USER_PRESENT:
                    mStateReceiverListener.onUserPresent();
                    break;
            }
        }
    }

实测效果
前台主进程oom_adj=0,后台=7,锁屏时=0


image.png

当我们查看最顶层的activity,就是我们的1像素activity
我们的1像素activity要记得setFinishOnTouchOutside(true),
避免有时候解锁杀死1像素activity不及时导致的界面卡死
至于清单为什么这样设置,请参考


image.png

方案3.循环播放无声音乐

方案1的进阶版,进liu阶mang的地方在于开启播放音乐,一些ROM是不会干掉正在播放音乐的app,测试机 华为P9,7.0,EMUI 5.0。
另一些ROM会杀掉整个进程组,测试机一加5T,7.0&8.0,氢OS。

关键代码就是播放音乐

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

这个方案的缺点也非常明显,耗电。

拉活

方案1.JobScheduler

事务是官方推荐的做法。
我在业务中实现,然后bugly的报错信息


bugly报错

搜一下这个bug,发现是个原生bug
https://code.google.com/p/android/issues/detail?id=170814

Android Jobscheduler使用
https://www.jianshu.com/p/9fb882cae239

https://www.jianshu.com/p/045b75f7d35c

方案2.NotificationListenerService

核心在打开NLS,使得自己可以使用通知。
核心是获取通知监听权限,然后通过系统的保活来达到拉活目的。
集成NLS很简单参考
NotificationListenerService的那些事儿
关键是下面链接说的问题
https://www.zhihu.com/question/33540416
我集成之后测试,仍旧无法实现拉活效果。。。所以这一条我先写上坑。

方案3.监听系统广播并提高优先级

参考信鸽的集成方案


image.png

有三个系统广播已经在7.0关闭静态注册方式
https://www.cnblogs.com/JLZT1223/p/8108783.html

总结

因为众所周知的原因,我们没有一个统一的推送方案,如果用户不打开app,我们收不到推送的消息。
是当用户打开app后,我们尽最大努力在后台情况下活下来--保活

拉活的目的,是当app已经被杀死的情况下,尽最大努力调起--拉活

就先这样吧

代码地址:
https://github.com/lamster2018/learnDaemon

相关文章

网友评论

    本文标题:Android保活/拉活(二)代码实现

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