Android程序保活(二):利用 Notification 提升許可權
前一篇文章 —— Android程序保活(一):利用 Activity 提升許可權 講到了利用前臺的 Activity 保證系統管家不會殺死我們的應用。這只是一種討巧的技術手段,並沒有利用系統的漏洞。今天要說的方法適用性非常廣,應用間互不干擾,不存在像是我開啟一畫素 Activity 把你蓋住,然後你我爭奪焦點的問題。
在實踐之前還是先看看別人家的應用,比如騰訊新聞。adb shell 下輸入
dumpsys activity services com.tencent.news

騰訊新聞前臺 Service
看一下控制檯的輸出,顧名思義 PushService 應該是推送服務,ServiceRecord 指明瞭它是前臺服務。我們看一下它的 oom_adj 的值:
ps | grep com.tencent.news cat /proc/25890/oom_adj

程序優先順序
沒錯,PuseService 的優先順序是 2,屬於可感知程序,一般不會被殺死。下面有個關於 oom_adj 的說明。

oom_adj 說明
其中紅色部分代表比較容易被殺死的 Android 程序(OOM_ADJ >= 4),綠色部分表示不容易被殺死的 Android 程序,其他表示非 Android 程序(純 Linux 程序)。在 Lowmemorykiller 回收記憶體時會根據程序的級別優先殺死 OOM_ADJ 比較大的程序,對於優先順序相同的程序,則進一步受到程序所佔記憶體和程序存活時間的影響。
下面就來親身實踐一下。利用系統的漏洞開啟前臺服務,提升程序的優先順序。這裡有兩個思路:
- 思路一:API < 18,啟動前臺 Service 時直接傳入new Notification();
- 思路二:API >= 18,同時啟動兩個id相同的前臺 Service,然後再將後啟動的 Service 做 stop 處理;
// 要開啟前臺的 service @Override public int onStartCommand(Intent intent, int flags, int startId) { if (Build.VERSION.SDK_INT < 18) { startForeground(SERVICE_ID, new Notification()); } else { startForeground(SERVICE_ID, new Notification()); Intent sendIntend = new Intent(this, ChannelService.class); startService(sendIntend); } return super.onStartCommand(intent, flags, startId); } // 為開啟前臺 service 服務的傀儡 service @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(DaemonService.SERVICE_ID, new Notification()); stopForeground(true); stopSelf(); return super.onStartCommand(intent, flags, startId); }
這樣就完成了,我們再次用 shell 命令驗證一下。

自己的前臺服務
沒錯,它已經是前臺服務了,使用者看不見摸不著的前臺服務,系統是不會輕易殺死該服務的,可以放心大膽地搞事情啦~~
【附錄】

資料圖
需要資料的朋友可以加入Android架構交流QQ群聊:513088520
點選連結加入群聊【Android移動架構總群】: 加入群聊
獲取免費學習視訊,學習大綱另外還有像高階UI、效能優化、架構師課程、NDK、混合式開發(ReactNative+Weex)等Android高階開發資料免費分享。