Low Memory Killer
- 系统出于体验和性能考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来
- 打开的应用越多,后台缓存的进程也越多
- 在系统内存不足的情况下,系统开始依据自身的一套进程回收棒棒的来判断要kill掉哪些进程
进程优先级
1、前台进程:当前运行的进程,除非APP的内存超过系统给定的最大内存,导致OOM才会被杀掉
2、可见进程、服务进程:当前可见、运行的音乐这种
3、空进程:给新打开的APP使用,优先级最低
如何判断进程的优先级
- 取值越低,则优先级越高
- 0以下为系统级保活,app无法实现
启动方式
Service 的启动方式有两种,一种是startService(),一种是bindService().这两种方式有有什么区别.
startService(),启动完之后该service就在后台运行,其生命周期跟启动它的Context没有任何关系。也不能跟Context通讯。
bindService()启动之后生命周期跟启动它的Context有关,比如Activity、fragment、service等。在Context中解绑之后,如果改Service没有任何绑定后该Service也就结束。
生命周期
Service 的生命周期跟启动方式有关。
stratService的生命周期: onCreate() -> onStartCommand() -> onDestroy()
bindService的生命周期: onCreate() -> onBind() -> onUnbind() -> onDestroy()
保活方案
1、 PowerManager 电源服务
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, AutoOpenLockService.class.getName());
wakeLock.acquire();
1.PARTIAL_WAKE_LOCK:保证CPU保持高性能运行,而屏幕和键盘背光(也可能是触摸按键的背光)关闭。一般情况下都会使用这个WakeLock。
2.ACQUIRE_CAUSES_WAKEUP:这个WakeLock除了会使CPU高性能运行外还会导致屏幕亮起,即使屏幕原先处于关闭的状态下。
3.ON_AFTER_RELEASE:如果释放WakeLock的时候屏幕处于亮着的状态,则在释放WakeLock之后让屏幕再保持亮一小会。如果释放WakeLock的时候屏幕本身就没亮,则不会有动作。
1.PARTIAL_WAKE_LOCK:保证CPU保持高性能运行,而屏幕和键盘背光(也可能是触摸按键的背光)关闭。一般情况下都会使用这个WakeLock。
2.ACQUIRE_CAUSES_WAKEUP:这个WakeLock除了会使CPU高性能运行外还会导致屏幕亮起,即使屏幕原先处于关闭的状态下。
3.ON_AFTER_RELEASE:如果释放WakeLock的时候屏幕处于亮着的状态,则在释放WakeLock之后让屏幕再保持亮一小会。如果释放WakeLock的时候屏幕本身就没亮,则不会有动作。
2、服务为前台服务(保活)
//设置service为前台服务,提高优先级
if (Build.VERSION.SDK_INT < 18) {
//Android4.3以下 ,此方法能有效隐藏Notification上的图标
service.startForeground(GRAY_SERVICE_ID, new Notification());
} else if(Build.VERSION.SDK_INT > 18 && Build.VERSION.SDK_INT < 25){
//Android4.3 - Android7.0,此方法能有效隐藏Notification上的图标
Intent innerIntent = new Intent(service, GrayInnerService.class);
service.startService(innerIntent);
service.startForeground(GRAY_SERVICE_ID, new Notification());
}
对于 API level < 18 :调用startForeground(ID, new Notification()),发送空的Notification ,图标则不会显示。
对于 API level >= 18:在需要提优先级的service A启动一个InnerService,两个服务同时startForeground,且绑定同样的 ID。Stop 掉InnerService ,这样通知栏图标即被移除。
3、1像素Acticity (效果不好)
public class PixelActivity extends Activity {
public static final String RECEIVER_ACTION_FINISH_A = "receiver_action_finish_a";
private FinishActivityRecevier mRecevier;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Window window = getWindow();
window.setGravity(Gravity.LEFT | Gravity.TOP);
WindowManager.LayoutParams params = window.getAttributes();
params.x = 0;
params.y = 0;
params.height = 1;
params.width = 1;
window.setAttributes(params);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(RECEIVER_ACTION_FINISH_A);
mRecevier = new FinishActivityRecevier();
registerReceiver(mRecevier, intentFilter);
KeepLiveManager.getInstance().setKeepLiveActivity(this);
}
private class FinishActivityRecevier extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//根据需求添加自己需要关闭页面的action
Log.i("keeplive","RECEIVER_ACTION_FINISH_A");
if (RECEIVER_ACTION_FINISH_A.equals(intent.getAction())) {
finish();
}
}
}
@Override
protected void onDestroy() {
if (mRecevier != null) {
unregisterReceiver(mRecevier);
}
super.onDestroy();
}
}
4、在后台播放一个无声的音频
5、利用JobScheduler机制拉活(高版本无效)
JobSchedule 允许在特定状态与特定时间间隔周期执行任务。我们可以利用它的这个特点来完成保活功能,效果就像开启一个定时器,与普通定时器不同的是其调度由系统来完成。
6、双进程守护
7、广播拉活
在发送特定系统事件时,系统会发出广播,通过在AndroidManifest中静态注册对应的广播监听,即可在发送响应事件时拉活。
但是Android7.0开始,对广播进行了限制,而且在8.0更加严格。
Android8.0开始对广播有了限制:很多隐式广播接收器不能在清单中静态注册。但清单注册广播接收器仍是可以的(豁免广播或自定义广播-注意,自定义广播要显式发送)。实现隐式广播(系统广播)的接收也是可以的,但只能通过动态注册来实现了。
有多个app在用户设备上安装,只要开启其中一个, 就可以将其他的app也拉活。
8、service系统机制拉活(真机只能拉活几次,模拟器无限次)
8、账户同步拉活
具體實現: https://blog.csdn.net/crazymo_/article/details/83026230
一、系统同步机制拉活
- 15分钟就会自动拉活一次
- 大厂都在用的最可靠方案
蓝牙问题:
https://zhuanlan.zhihu.com/p/263425181