引言
最近产品提出了一个非常BT的需求,说我们所做的APP要做到像微信和QQ那种即时用户清理了进程还是能收到消息的效果,当时心中就卧槽了一顿,虽然心里一万只曹尼玛翻滚着,但是功能还是要做啊,因为生活还得继续啊。
我们虽然做不到像微信、QQ这种白名单大佬(白名单指的是一些APP跟某些手机厂商合作,我们通过清理内存是杀不死这些进程的。)的效果,但是我们可以利用黑科技来尽量保证我们自己的APP不被系统杀死。现在市面上的保活和拉活方式有以下几种方案:
保活方式 | Activity 1像素保活、前台服务保活 |
---|---|
拉活方式 | 广播拉活、系统Service拉活、账户同步拉活、JobScheduler、双进程拉活、推送拉活、NDK fork拉活 |
进程被杀死无非就是由于系统内存过低,并且进程的优先级比较低,所以才会被系统kill掉,想要进程保活必须提高进程的优先级。下面是进程优先级高低图:
何时杀死进程?
内存阈值在不同的手机上不一样,一旦低于阈值,Android就会杀死对应优先级的进程,例如:当内存小于315MB(80640),就会杀死空进程。我们可以通过adb shell后输入`cat /sys/module/lowmemorykiller/parameters/minfree`来查看阈值,如下图所示(阈值的单位是4KB):![在这里插入图片描述](https://img-blog.csdnimg.cn/20190517151620712.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODIwMzY5Ng==,size_16,color_FFFFFF,t_70)
第一个值:18432(72MB)当阈值达到这个值时候,前台进程就会被杀死;
第二个值:23040(90MB)当阈值达到这个值的时候,可见进程就会被杀死;
第三个值:27648(108MB)当阈值达到这个值的时候,服务进程会被杀死;
第四个值:32256(126MB)当阈值达到这个值的时候,后台进程会被杀死;
第五个值:55296(216MB)当阈值达到这个值的时候,ContentProvider会被杀死;
第六个值:80640(315MB)当阈值达到这个值的时候,空进程会被杀死。
如何判断进程的优先级
- 红色部分是容易被回收的进程,属于android进程
- 绿色部分是较难被回收的进程,属于android进程
- 其他部分则不是android进程,也不会被系统回收,一般是ROM自带的app和服务才能拥有
通过oom_adj的值,判断进程的优先级,不同的手机的oom_adj的值可能不一样。oom_adj值越小,优先级越高,也就也难被杀死,我们日常开发的APP最高能达到的值是0,即前台进程。oom_adj的值我们可以通过 adb shell 直接输入cat /proc/你的process ID/oom_adj
来获取(有一个前提,手机必须是root过的才能获取到值)
如何保活?
1、activity 1像素保活
第一步:创建SinglePixelActivity,如
public class SinglePixelActivity extends AppCompatActivity {
private static final String TAG = "SinglePixelActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "启动1像素Activity");
Window window = getWindow();
window.setGravity(Gravity.START | Gravity.TOP);
WindowManager.LayoutParams params = window.getAttributes();
params.width = 1;
params.height = 1;
params.x= 0;
params.y = 0;
window.setAttributes(params);
KeepManager.getInstance().setKeepActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
FixMemLeak.fixLeak(this);
Log.e(TAG, "关闭1像素Activity");
}
}
第二步:创建KeepManager,和KeepReceiver用来监听屏幕是否息屏
KeepManager.class:
public class KeepManager {
private static final KeepManager mInstance = new KeepManager();
private KeepReceiver mKeepReceiver;
private WeakReference<Activity> mKeepActivity;
private KeepManager() {}
public static KeepManager getInstance(