美文网首页
日更挑战-安卓开发之后台保活

日更挑战-安卓开发之后台保活

作者: 愿你我皆是黑马 | 来源:发表于2021-05-17 23:40 被阅读0次

    越不懂的越爱装
    大家都同等:IT世界没有难不难,只有是否了解过

    挑战目录

    由于同事经常迟到,拜托我写一个自动打卡的工具。发现现在安卓上的保活不太起作用。由于对保活这块不是特别了解,于是就花了点时间看了下这个。最终实现了一个简单的打卡工具。由于还要工作原因导致大部分时间都被占用了。


    问题1: 什么是后台保活?

    解 答:

    当应用需要有一个一直在运行的进程时,为了防止系统杀死进程的一种手段。

    进程? (下面方法的执行和开在其中开线程的区别?)

    前台进程:(内存过低,连这些进程都无法继续运行,才会终止这些进程)
    1. onResume()方法已被调用(正在用户的互动屏幕上运行一个 Activity)
    2. BroadcastReceiver.onReceive() 方法正在执行
    3. Service.onCreate()、Service.onStart()、Service.onDestroy()...方法正在执行
    4. 按下Home或Back键的Activity,但是有前台service运行(比如音乐播放器等)
    可见进程:(为了使前台进程运行而终止它们,否则不会这么做)
    1. onPause()方法已被调用(Activity在屏幕上对用户可见,但不在前台)
    2. Service通过 Service.startForeground() 作为"前台服务(用户知晓的看得见的)"运行
    3. 系统正在使用其托管的服务实现用户知晓的特定功能,例如动态壁纸、输入法服务等?
    服务进程:(会始终保持运行,除非没有内存来保留前台和可见进程)
    1. 使用startService()方法启动的Service坐着用户看不见的事情(网络数据上传下载等).
      由于使用LRU 列表,执行时间越长越容易被回收。
    2. 按下HOME或Back键后的Activity。有普通service运行
    后台进程:(系统可能随时终止它们,以回收内存供上述三种进程使用)
    1. 按下HOME键后的Activity。(对用户不可见的Activity的进程)
    空进程:(不含任何活动应用组件的进程)
    1. 应用按Back按键的Activity。(不含任何活动组件的进程。保留的唯一目的是用作缓存,缩短下次所需的启动时间)

    系统如何杀死进程?

    由于系统的内存是有限的,内存不足时系统就会清理进程。另外由于为了 " 节约手机电量 ",系统会清理进程。

    Android 5.0 以上:

    系统以 uid 杀进程,杀死整个进程组,包括java进程和native进程。
    

    Android 6.0 以上:

    引入了待机模式(doze):拔下电源,屏幕关闭后的一段时间杀死后台进程。
    

    Android 7.0 以上:

    待机模式不再要求设备静止。
    移除了一些隐式广播,App 无法再通过监听这些广播拉起自己
    

    Android 8.0 以上:

    无法使用 Mainifest 注册大部分隐式广播
    限制未在前台运行的应用的某些行为 
    

    Android 9.0 以上:

    省电模式功能加入应用待机分组,长时间不用的 App 和刚装的App都处理危险的地位;
    当系统监测到应用消耗过多资源时,会询问用户是否限制该应用的后台活动
    

    对于锁屏熄屏来说:

    锁屏事件后一段时间(一般为5分钟以内)内会杀死后台进程,以达到省电的目的问题
    

    对于服务Service来说

    onStartCommand返回值在保活中的具体有何作用上的意义:
    1.
    2.
    3.
    4.
    
    杀死APP进程的主要分为如下
    1. LowmemoryKiller
    2. killBackgroundProcesses:系统会在需要的时候再次重启被我们杀死的进程(公开的方法)

    需要权限android.Manifest.permission.KILL_BACKGROUND_PROCESSES

    public void killBackgroundProcesses(String packageName) {  
       try {   
    ActivityManagerNative.getDefault().killBackgroundProcesses(packageName,UserHandle.myUserId());  
            } catch (RemoteException e) {  
            }  
        }  
    
    3. removeTask:
    4. forceStopPackage(@hide隐藏的方法):首先杀掉目标进程,以uid为单位杀掉进程组(双进程守护的方式实现保活失效),然后清理残留在 system_server 内的四大组件信息。

    杀掉进程组时:循环 40 遍不停滴杀进程 组 ,每次杀完之后等 5ms
    上述的缺陷:

        public void forceStopPackage(String packageName) {  
            try {  
                ActivityManagerNative.getDefault().forceStopPackage(packageName,  
                        UserHandle.myUserId());  
            } catch (RemoteException e) {  
            }  
        }
    

    如何防止被杀死(高版本适用低版本)?

    主要通过如下方法:

     1. 提高进程优先级,降低进程被杀死的概率
     2. 降低APP的内存占用量,在oom_adj相同的时候,会优先干掉内存消耗大的进程
     3. 在进程被杀死后,进行拉活
    
    Android 5.0及以下:
    通过 native 方式 fork 出来的进程是不受系统管控的,系统在杀 App 进程的时候,只会去杀 App 启动的 Java 进程
    Android 6.0及以下:(5.0后以uid为标识,能杀死整个进程组native进程也会杀掉)
    Android 7.0及以下:(6.0引入待机模式,拔下电源,屏幕关闭后进入低电耗模式)
    Android 8.0及以下:
    1.提升进程的优先级
    2. 监听广播:
    3. 双进程(NDK方式Fork子进程)、双Service守护:
    4. 提高Service优先级:
    5. 添加app进入白名单:
    6. 推送互相唤醒复活:极光、友盟、以及各大厂商的推送:
    7. 同派系APP广播互相唤醒:
    8. 故意在后台播放无声的音乐:
    9. 监听锁屏广播打开1像素Activity:
    10. 使用JobScheduler唤醒Service:

    透明悬浮窗
    前台服务
    独立进程

    TIM保活方法:
    创建 2 个进程 p1, p2,这两个进程通过文件锁互相关联,一个被杀之后拉起另外一个;
    同时 p1 经过 2 次 fork 产生孤儿进程 c1,p2 经过 2 次 fork 产生孤儿进程 c2,
    c1 和 c2 之间建立文件锁关联。
    这样假设 p1 被杀,那么 p2 会立马感知到,然后 p1 和 c1 同属一个进程组,
    p1 被杀会触发 c1 被杀,c1 死后 c2 立马感受到从而拉起 p1,
    因此这四个进程三三之间形成了铁三角,从而保证了存活率。
    
    11. 白名单

    不同安卓版本的保活代码

    Android 5.0及以下:

    相关文章

      网友评论

          本文标题:日更挑战-安卓开发之后台保活

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