android程序保活
有些時候(國內通常是這樣)我們需要應用在 後臺存活,但是現在的很多手機room是在記憶體不足或者一定時間後銷燬程序的。
總結幾種android常用的保活手段。
系統出於體驗和效能上的考慮,app在退到後臺時系統並不會真正的kill掉這個程序,而是將其快取起來。開啟的應用越多,後臺快取的程序也越多。在系統記憶體不足的情況下,系統開始依據自身的一套程序回收機制來判斷要kill掉哪些程序,以騰出記憶體來供給需要的app, 這套殺程序回收記憶體的機制就叫 Low Memory Killer。
cat /sys/module/lowmemorykiller/parameters/minfree //檢視記憶體閾值
程序的優先順序通過程序的adj值來反映,它是linux核心分配給每個系統程序的一個值,程序回收機制根據這個值來決定是否進行回收。adj的值越小,程序的優先順序越高。
cat /proc/32393/oom_adj 檢視程序的adj值
一,提升程序優先順序
1)Activity提權
監聽應用退入後臺以後就啟動一個透明的1px大小的activity
2)Service提權
建立一個前臺服務用於提高app在按下home鍵之後的程序優先順序startForeground(ID,Notification):
API level < 18 :引數2 設定 new Notification(),圖示不會顯示。
API level >= 18:在需要提優先順序的service A啟動一個InnerService。兩個服務都startForeground,且繫結同樣的 ID。Stop 掉InnerService ,通知欄圖示被移除。
3)廣播拉活
在發生特定系統事件時,系統會發出廣播,通過在 AndroidManifest 中靜態註冊對應的廣播監聽器,即可在發生響應事件時拉活。
但是從android 7.0開始,對廣播進行了限制,而且在8.0更加嚴格
4)賬戶同步 拉活
手機系統設定裡會有“帳戶”一項功能,任何第三方APP都可以通過此功能將資料在一定時間內同步到伺服器中去。系統在將APP帳戶同步時,會將未啟動的APP程序拉活。(過程過於麻煩,而且不能控制重啟時間)
5)JobScheduler 拉活
JobScheduler允許在特定狀態與特定時間間隔週期執行任務。可以利用它的這個特點完成保活的功能,效果即開啟一個定時器,與普通定時器不同的是其排程由系統完成。
同樣在某些ROM可能並不能達到需要的效果(某米)
public static void StartJob(Context context) {
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context
.JOB_SCHEDULER_SERVICE);
// setPersisted 在裝置重啟依然執行
JobInfo.Builder builder = new JobInfo.Builder(10, new ComponentName(context
.getPackageName(), MyJobService.class
.getName())).setPersisted(true);
//小於7.0
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
// 每隔1s 執行一次 job
builder.setPeriodic(1_000);
} else {
//延遲執行任務
builder.setMinimumLatency(1_000);
}
jobScheduler.schedule(builder.build());
}
private static final String TAG = "MyJobService";
@Override
public boolean onStartJob(JobParameters params) {
Log.e(TAG, "開啟job");
//如果7.0以上 輪訓
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StartJob(this);
}
return false;
}
不能保證適配所有機型
6)雙程序守護
這個是目前來說最靠譜的了,但是也不是一定可以(有些可以一鍵清理後臺程序的)。
class ServiceConnection implements android.content.ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//服務連線後回撥
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG,"主程序可能被幹掉了,拉活");
//連線中斷後回撥
startService(new Intent(RemoteService.this, LocalService.class));
bindService(new Intent(RemoteService.this, LocalService.class), serviceConnection,
BIND_AUTO_CREATE);
}
}
另外還有native fork程序監聽主程序的,這個5.0之前還行,之後就廢了。