越不懂的越爱装
大家都同等:IT世界没有难不难,只有是否了解过
挑战目录
由于同事经常迟到,拜托我写一个自动打卡的工具。发现现在安卓上的保活不太起作用。由于对保活这块不是特别了解,于是就花了点时间看了下这个。最终实现了一个简单的打卡工具。由于还要工作原因导致大部分时间都被占用了。
问题1: 什么是后台保活?
解 答:
当应用需要有一个一直在运行的进程时,为了防止系统杀死进程的一种手段。
进程? (下面方法的执行和开在其中开线程的区别?)
前台进程:(内存过低,连这些进程都无法继续运行,才会终止这些进程)
- onResume()方法已被调用(正在用户的互动屏幕上运行一个 Activity)
- BroadcastReceiver.onReceive() 方法正在执行
- Service.onCreate()、Service.onStart()、Service.onDestroy()...方法正在执行
- 按下Home或Back键的Activity,但是有前台service运行(比如音乐播放器等)
可见进程:(为了使前台进程运行而终止它们,否则不会这么做)
- onPause()方法已被调用(Activity在屏幕上对用户可见,但不在前台)
- Service通过 Service.startForeground() 作为"前台服务(用户知晓的看得见的)"运行
- 系统正在使用其托管的服务实现用户知晓的特定功能,例如动态壁纸、输入法服务等?
服务进程:(会始终保持运行,除非没有内存来保留前台和可见进程)
- 使用startService()方法启动的Service坐着用户看不见的事情(网络数据上传下载等).
由于使用LRU 列表,执行时间越长越容易被回收。 - 按下HOME或Back键后的Activity。有普通service运行
后台进程:(系统可能随时终止它们,以回收内存供上述三种进程使用)
- 按下HOME键后的Activity。(对用户不可见的Activity的进程)
空进程:(不含任何活动应用组件的进程)
- 应用按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,
因此这四个进程三三之间形成了铁三角,从而保证了存活率。
网友评论