?;钍侄?/h1>
當前業界的Android進程?;钍侄沃饕譃?strong>黑、白、灰三種,其大致的實現思路如下:
黑色保活:
不同的app進程,用廣播相互喚醒(包括利用系統提供的廣播進行喚醒)
白色?;睿?/h5>
啟動前臺Service(體驗不太好)
灰色?;睿?/h5>
利用系統的漏洞啟動前臺Service
黑色保活
所謂黑色保活,就是利用不同的app進程使用廣播來進行相互喚醒。舉個3個比較常見的場景:
場景1:
開機,網絡切換、拍照、拍視頻時候,利用系統產生的廣播喚醒app(Google陸續取消了這部分的系統廣播)
場景2:
接入第三方SDK也會喚醒相應的app進程,如微信sdk會喚醒微信,支付寶sdk會喚醒支付寶。由此發散開去,就會直接觸發了下面的 場景3
場景3:
假如你手機里裝了支付寶、淘寶、天貓、UC等阿里系的app,那么你打開任意一個阿里系的app后,有可能就順便把其他阿里系的app給喚醒了。(導致手機很卡)
白色?;?/h2>
就是調用系統api啟動一個前臺的Service進程,這樣會在系統的通知欄生成一個Notification,用來讓用戶知道有這樣一個app在運行著,哪怕當前的app退到了后臺
缺個圖片
灰色?;?/h2>
灰色保活,這種?;钍侄问菓梅秶顝V泛。它是利用系統的漏洞來啟動一個前臺的Service進程,與普通的啟動方式區別在于,它不會在系統通知欄處出現一個Notification,看起來就如同運行著一個后臺Service進程一樣。這樣做帶來的好處就是,用戶無法察覺到你運行著一個前臺進程(因為看不到Notification),但你的進程優先級又是高于普通后臺進程的。那么如何利用系統的漏洞呢,大致的實現思路和代碼如下:
思路一:
API < 18,啟動前臺Service時直接傳入new Notification();
思路二:
API >= 18,同時啟動兩個id相同的前臺Service,然后再將后啟動的Service做stop處理;
public class GrayService extends Service {
private final static int GRAY_SERVICE_ID = 1001;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT < 18) {
startForeground(GRAY_SERVICE_ID, new Notification());//API < 18 ,此方法能有效隱藏Notification上的圖標
} else {
Intent innerIntent = new Intent(this, GrayInnerService.class);
startService(innerIntent);
startForeground(GRAY_SERVICE_ID, new Notification());
}
return super.onStartCommand(intent, flags, startId);
}
...
...
/**
* 給 API >= 18 的平臺上用的灰色?;钍侄危o態內部類)
*/
public static class GrayInnerService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(GRAY_SERVICE_ID, new Notification());
stopForeground(true);
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
}
其他拉活方法
利用系統Service機制拉活
Start_sticky.png
如下兩種情況無法拉活:
Service 第一次被異常殺死后會在5秒內重啟,第二次被殺死會在10秒內重啟,第三次會在20秒內重啟,一旦在短時間內 Service 被殺死達到5次,則系統不再拉起。
進程被取得 Root 權限的管理工具或系統工具通過 forestop 停止掉,無法重啟。
利用Native進程拉活
該方案主要適用于 Android5.0 以下版本手機。
該方案不受 forcestop 影響,被強制停止的應用依然可以被拉活,在 Android5.0 以下版本拉活效果非常好。
對于 Android5.0 以上手機,系統雖然會將native進程內的所有進程都殺死,這里其實就是系統“依次”殺死進程時間與拉活邏輯執行時間賽跑的問題,如果可以跑的比系統邏輯快,依然可以有效拉起。記得網上有人做過實驗,該結論是成立的,在某些 Android 5.0 以上機型有效。
總結
上面所提到的?;畈皇钦嬲淖尵€程不死,而只是讓線程的重要優先級提高,難以被殺死,殺進程回收內存的機制就叫 Low Memory Killer。LMB會根據oom_adj的值來選擇是否優先殺死。oom_adj是linux內核分配給每個系統進程的一個值,代表進程的優先級,越大越容易被殺死。(可以通過adb shell和線程ID來獲得這個oom_adj)
- 普通app進程的oom_adj>=0,系統進程的oom_adj才可能<0
- 有些手機廠家會把一些常用的app加入自己定制的Android版本的白名單里,通過讓這些app的oom_adj與系統進程一樣,來提高用戶體驗
最后提一下,?;顣斐蒩ndroid生態的混亂,可能會造成有些本來應該存在的線程被無關緊要的線程通過保活的手段頂掉。。大家都不想死,但是內存不足的時候還不是要死,所以?;钭尵€程不死是個偽命題,最后還是要從對應用的內存優化控制來下手。
轉自作者:D_clock愛吃蔥花
鏈接:http://www.lxweimin.com/p/63aafe3c12af
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
201907301711編輯:查看oom_adjhttps://blog.csdn.net/simon_yds/article/details/78607193