溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何對(duì)Android中的進(jìn)程進(jìn)行?;?/h1>
發(fā)布時(shí)間:2020-11-26 15:54:56 來(lái)源:億速云 閱讀:199 作者:Leah 欄目:移動(dòng)開(kāi)發(fā)

本篇文章給大家分享的是有關(guān)如何對(duì)Android中的進(jìn)程進(jìn)行?;?,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

?;钍侄?/strong>

當(dāng)前業(yè)界的Android進(jìn)程?;钍侄沃饕譃?黑、白、灰 三種,其大致的實(shí)現(xiàn)思路如下:

黑色保活:不同的app進(jìn)程,用廣播相互喚醒(包括利用系統(tǒng)提供的廣播進(jìn)行喚醒)

白色?;睿?jiǎn)?dòng)前臺(tái)Service

灰色?;睿豪孟到y(tǒng)的漏洞啟動(dòng)前臺(tái)Service

黑色?;?/strong>

所謂黑色?;?,就是利用不同的app進(jìn)程使用廣播來(lái)進(jìn)行相互喚醒。舉個(gè)3個(gè)比較常見(jiàn)的場(chǎng)景:

場(chǎng)景1:開(kāi)機(jī),網(wǎng)絡(luò)切換、拍照、拍視頻時(shí)候,利用系統(tǒng)產(chǎn)生的廣播喚醒a(bǔ)pp

場(chǎng)景2:接入第三方SDK也會(huì)喚醒相應(yīng)的app進(jìn)程,如微信sdk會(huì)喚醒微信,支付寶sdk會(huì)喚醒支付寶。由此發(fā)散開(kāi)去,就會(huì)直接觸發(fā)了下面的 場(chǎng)景3

場(chǎng)景3:假如你手機(jī)里裝了支付寶、淘寶、天貓、UC等阿里系的app,那么你打開(kāi)任意一個(gè)阿里系的app后,有可能就順便把其他阿里系的app給喚醒了。(只是拿阿里打個(gè)比方,其實(shí)BAT系都差不多)

沒(méi)錯(cuò),我們的Android手機(jī)就是一步一步的被上面這些場(chǎng)景給拖卡機(jī)的。

針對(duì)場(chǎng)景1,估計(jì)Google已經(jīng)開(kāi)始意識(shí)到這些問(wèn)題,所以在最新的Android N取消了 ACTION_NEW_PICTURE(拍照),ACTION_NEW_VIDEO(拍視頻),CONNECTIVITY_ACTION(網(wǎng)絡(luò)切換)等三種廣播,無(wú)疑給了很多app沉重的打擊。我猜他們的心情是下面這樣的

而開(kāi)機(jī)廣播的話,記得有一些定制ROM的廠商早已經(jīng)將其去掉。

針對(duì)場(chǎng)景2和場(chǎng)景3,因?yàn)檎{(diào)用SDK喚醒a(bǔ)pp進(jìn)程屬于正常行為,此處不討論。但是在借助LBE分析app之間的喚醒路徑的時(shí)候,發(fā)現(xiàn)了兩個(gè)問(wèn)題:

1.很多推送SDK也存在喚醒a(bǔ)pp的功能

2.app之間的喚醒路徑真是多,且錯(cuò)綜復(fù)雜

我把自己使用的手機(jī)測(cè)試結(jié)果給大家圍觀一下(我的手機(jī)是小米4C,刷了原生的Android5.1系統(tǒng),且已經(jīng)獲得Root權(quán)限才能查看這些喚醒路徑)

如何對(duì)Android中的進(jìn)程進(jìn)行保活

15組相互喚醒路徑

如何對(duì)Android中的進(jìn)程進(jìn)行?;?></p><p>全部喚醒路徑</p><p>我們直接點(diǎn)開(kāi) 簡(jiǎn)書(shū) 的喚醒路徑進(jìn)行查看</p><p><img src=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上的圖標(biāo)     } else {       Intent innerIntent = new Intent(this, GrayInnerService.class);       startService(innerIntent);       startForeground(GRAY_SERVICE_ID, new Notification());     }     return super.onStartCommand(intent, flags, startId);   }   ...   ...   /**    * 給 API >= 18 的平臺(tái)上用的灰色?;钍侄?    */   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);     }   } }

代碼大致就是這樣,能讓你神不知鬼不覺(jué)的啟動(dòng)著一個(gè)前臺(tái)Service。其實(shí)市面上很多app都用著這種灰色?;畹氖侄?,什么?你不信?好吧,我們來(lái)驗(yàn)證一下。流程很簡(jiǎn)單,打開(kāi)一個(gè)app,看下系統(tǒng)通知欄有沒(méi)有一個(gè) Notification,如果沒(méi)有,我們就進(jìn)入手機(jī)的adb shell模式,然后輸入下面的shell命令

dumpsys activity services PackageName

打印出指定包名的所有進(jìn)程中的Service信息,看下有沒(méi)有 isForeground=true 的關(guān)鍵信息。如果通知欄沒(méi)有看到屬于app的 Notification 且又看到 isForeground=true 則說(shuō)明了,此app利用了這種灰色?;畹氖侄巍?/p>

下面分別是我手機(jī)上微信、qq、支付寶、陌陌的測(cè)試結(jié)果,大家有興趣也可以自己驗(yàn)證一下。

如何對(duì)Android中的進(jìn)程進(jìn)行?;?></p><p>微信</p><p><img src=

陌陌

其實(shí)Google察覺(jué)到了此漏洞的存在,并逐步進(jìn)行封堵。這就是為什么這種?;罘绞椒?API >= 18 和 API < 18 兩種情況,從Android5.0的ServiceRecord類(lèi)的postNotification函數(shù)源代碼中可以看到這樣的一行注釋

如何對(duì)Android中的進(jìn)程進(jìn)行保活

當(dāng)某一天 API >= 18 的方案也失效的時(shí)候,我們就又要另謀出路了。需要注意的是,使用灰色保活并不代表著你的Service就永生不死了,只能說(shuō)是提高了進(jìn)程的優(yōu)先級(jí)。如果你的app進(jìn)程占用了大量的內(nèi)存,按照回收進(jìn)程的策略,同樣會(huì)干掉你的app。感興趣于灰色保活是如何利用系統(tǒng)漏洞不顯示 Notification 的童鞋,可以研究一下系統(tǒng)的 ServiceRecord、NotificationManagerService 等相關(guān)源代碼,因?yàn)椴皇潜疚牡闹攸c(diǎn),所以不做詳述。

嘮叨的分割線

到這里基本就介紹完了 黑、白、灰 三種實(shí)現(xiàn)方式,僅僅從代碼層面去講?;钍遣粔虻?,我希望能夠通過(guò)系統(tǒng)的進(jìn)程回收機(jī)制來(lái)理解?;睿@樣能夠讓我們更好的避免踩到進(jìn)程被殺的坑。

進(jìn)程回收機(jī)制

熟悉Android系統(tǒng)的童鞋都知道,系統(tǒng)出于體驗(yàn)和性能上的考慮,app在退到后臺(tái)時(shí)系統(tǒng)并不會(huì)真正的kill掉這個(gè)進(jìn)程,而是將其緩存起來(lái)。打開(kāi)的應(yīng)用越多,后臺(tái)緩存的進(jìn)程也越多。在系統(tǒng)內(nèi)存不足的情況下,系統(tǒng)開(kāi)始依據(jù)自身的一套進(jìn)程回收機(jī)制來(lái)判斷要kill掉哪些進(jìn)程,以騰出內(nèi)存來(lái)供給需要的app。這套殺進(jìn)程回收內(nèi)存的機(jī)制就叫 Low Memory Killer ,它是基于Linux內(nèi)核的 OOM Killer(Out-Of-Memory killer)機(jī)制誕生。

了解完 Low Memory Killer,再科普一下oom_adj。什么是oom_adj?它是linux內(nèi)核分配給每個(gè)系統(tǒng)進(jìn)程的一個(gè)值,代表進(jìn)程的優(yōu)先級(jí),進(jìn)程回收機(jī)制就是根據(jù)這個(gè)優(yōu)先級(jí)來(lái)決定是否進(jìn)行回收。對(duì)于oom_adj的作用,你只需要記住以下幾點(diǎn)即可:

  • 進(jìn)程的oom_adj越大,表示此進(jìn)程優(yōu)先級(jí)越低,越容易被殺回收;越小,表示進(jìn)程優(yōu)先級(jí)越高,越不容易被殺回收

  • 普通app進(jìn)程的oom_adj>=0,系統(tǒng)進(jìn)程的oom_adj才可能<0

那么我們?nèi)绾尾榭催M(jìn)程的oom_adj值呢,需要用到下面的兩個(gè)shell命令

ps | grep PackageName //獲取你指定的進(jìn)程信息

如何對(duì)Android中的進(jìn)程進(jìn)行保活

這里是以我寫(xiě)的demo代碼為例子,紅色圈中部分別為下面三個(gè)進(jìn)程的ID

  • UI進(jìn)程:com.clock.daemon

  • 普通后臺(tái)進(jìn)程:com.clock.daemon:bg

  • 灰色?;钸M(jìn)程:com.clock.daemon:gray

當(dāng)然,這些進(jìn)程的id也可以通過(guò)AndroidStudio獲得

如何對(duì)Android中的進(jìn)程進(jìn)行?;?></p><p>接著我們來(lái)再來(lái)獲取三個(gè)進(jìn)程的oom_adj<br/></p><p>cat /proc/進(jìn)程ID/oom_adj</p><p><img src=以上就是如何對(duì)Android中的進(jìn)程進(jìn)行保活,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI