有些業務需要service在後臺持續的運行,所以就要有後臺保活機制,包括lowMemory防殺和自啓。
防殺機制
基本就是提高進程優先級,保證在低內存時進程不被有限殺死,常用的方法就是利用系統bug提高進程優先級,灰色保活手段。
後臺自啓
大概包括
Receiver拉起
AlarmManager拉起
雙進程互相守護
利用推送SDK拉起進程
以上說的這幾種是常用的方法,對於原生和沒有深度定製的ROM有一定作用,但是對於像小米、魅族等這類深度定製的系統來說效果不是很好。
綁定系統服務
系統提供一些系統級的Service,比如AccessibilityService輔助服務、NotificationListenerService用於監聽通知消息。這篇文章主要講下怎樣利用NotificationListenerService用於監聽通知消息實現進程保活。
首先,如果想使用系統service,必須要用戶手動點開權限。我們可以添加一個設置的入口直接跳到系統設置通知權限的界面,顯示提示用戶需要開啓權限。
public static void goNLPermission(Context context) {
try {
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
context.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
界面就不截圖了,然後我們app中要有一個權限的狀態檢查用於提示用戶是否開啓了通知顯示權。
/**
* 檢查通知使用權
*/
public static boolean checkNotificationPermission(Context context) {
String pkg = context.getPackageName();
String flat = Settings.Secure.getString(context.getContentResolver(), "enabled_notification_listeners");
boolean enabled = flat != null && flat.contains(pkg);
return enabled;
}
註冊,聲明運行在com.package.pedometer進程中
<service< p="">
android:name=".service.MyListenerService"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:process=":pedometer">
然後需要繼承NotificationListenerService實現兩個方法
/**
* 監聽系統通知,需要用戶手動開啓權限,那麼該進程可以不死
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class MyListenerService extends NotificationListenerService {
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
}
}
方法中什麼都不用實現,MyListenerService所在的進程就擁有了跟NotificationListenerService一樣的權限。可以試下手動強制停止進程會發現怎麼都結束不掉,強制停止的按鈕一直可以點擊。可以使用
adb shell ps | grep ***
命令查看進程是否存活。
cat /proc/12869/oom_adj
0
查看進程的oom_adj的值爲0,那麼我們知道在灰色保活手段上基本就是提高oom_adj的值,越小越不容易被殺死,這種方法一步到位。
那麼怎麼應用到我們自己的service中呢?很簡單,將service跟MyListenerService運行在同一個進程就可以了。
<service< p="">
android:name=".service.StepCounterService"
android:exported="true"
android:process=":pedometer">
這樣基本就可以保證service所在的進程不被殺死了。當然,如果ROM廠商在系統級別攔截掉了,這種方法也會無效了。