前言
什么?面試官又問(wèn)了進(jìn)程?;??你又是一臉尷尬地說(shuō)不知道?然后又讓你回去等消息?
好吧,不能老這樣,學(xué)而時(shí)習(xí)之,習(xí)而記筆記,今天整理一下進(jìn)程?;钅切┕?,下次面試不再懵逼。
概念
一些必須的基礎(chǔ)概念QA。
Q: ?;睿渴裁匆馑??
A:意思是:讓app進(jìn)程沒(méi)有那么容易被系統(tǒng)殺死.
Q:系統(tǒng)為什么要?dú)⑦M(jìn)程?
A:Android有LMK(low memory killer)機(jī)制---------當(dāng)系統(tǒng)的可用內(nèi)存剩余太少的時(shí)候,系統(tǒng)就會(huì)根據(jù) 進(jìn)程回收機(jī)制來(lái) 殺掉一些進(jìn)程,來(lái)騰出內(nèi)存空間給需要內(nèi)存的app。
Q:系統(tǒng)什么時(shí)候殺進(jìn)程?
A: 不同的手機(jī),存在不同的內(nèi)存閾值,比如我打開(kāi)SDK自帶的模擬器,輸入命令(并不是所有手機(jī)上都能使用此命令,因?yàn)榇蟛糠终鏅C(jī)不開(kāi)放su權(quán)限):
image.png
就會(huì)得到 上面的5個(gè)數(shù)字,這幾個(gè)數(shù)字的意思就是 當(dāng)系統(tǒng)的可用內(nèi)存下降到 其中一個(gè)值乘以 4KB的大小的時(shí)候,就會(huì)殺掉一批進(jìn)程。貼一張
進(jìn)程優(yōu)先級(jí)的官方圖:
image.png
上面5個(gè)數(shù)字,從左到右對(duì)應(yīng)了前臺(tái)進(jìn)程,可見(jiàn)進(jìn)程,服務(wù)進(jìn)程,后臺(tái)進(jìn)程,空進(jìn)程
當(dāng)可用內(nèi)存低于18432*4KB=72M的時(shí)候,就會(huì)去殺死前臺(tái)進(jìn)程,以保證系統(tǒng)正常運(yùn)行, 而 低于80640*4KB= 315M的時(shí)候,就會(huì)殺死空進(jìn)程.
Q:怎么查看進(jìn)程的被殺優(yōu)先級(jí)?
A: Android系統(tǒng)中的進(jìn)程都有一個(gè)adj值,它代表進(jìn)程的被殺優(yōu)先級(jí),這個(gè)值數(shù)字越高,越容易被系統(tǒng)殺掉!查看這個(gè)值的方法為(也不用到真機(jī)上試驗(yàn)了,大部分真機(jī)都不開(kāi)放該目錄的訪(fǎng)問(wèn)權(quán)限,要試驗(yàn)就用模擬器吧,雖然模擬器也不一定行):
image.png
Android系統(tǒng)中的進(jìn)程adj值,是AMS(ActivityManagerService)去計(jì)算的,AMS通過(guò)一系列參數(shù)(比如應(yīng)用的當(dāng)前狀態(tài)等)的計(jì)算,最終得出adj值,并決定要不要kill掉這個(gè)進(jìn)程.
ps:作為應(yīng)用層面的開(kāi)發(fā)工程師,我們不去做ROM,對(duì)這一塊,知其然就行了,就算想去深究,也用不到實(shí)處。
Q: ?;钣心膸追N常用方式??jī)?yōu)缺點(diǎn)都是啥?
A:上面說(shuō)了,要想讓進(jìn)程沒(méi)那么容易被殺,就要想辦法提高進(jìn)程優(yōu)先級(jí),比如 .
常見(jiàn)?;罘绞絻深?lèi):
第一類(lèi):欺騙系統(tǒng),在我們的app退到后臺(tái)之后,讓系統(tǒng)以為 app還在前臺(tái)
1像素?;?/strong>/前臺(tái)服務(wù)?;?/strong>
第二類(lèi): 如果還是app進(jìn)程還是不幸被殺,那就想辦法再啟動(dòng)它,整個(gè)可稱(chēng)之為拉活,然后你的應(yīng)用就變成了僵尸病毒,殺一次復(fù)活一次,囧 !
粘性廣播拉活/賬戶(hù)同步拉活/JobScheduler拉活
Q:說(shuō)句公道話(huà)
A:所謂?;?,就是 利用安卓系統(tǒng)的bug,欺騙系統(tǒng),讓系統(tǒng)以為我們的app優(yōu)先級(jí)處于安全范圍內(nèi),不去殺,或者讓系統(tǒng)以為我們的app已經(jīng)死了,但是其實(shí)還沒(méi)死。說(shuō)到底,都是流氓手段,試想,如果你的手機(jī)上全都是 無(wú)限保活的app,你的手機(jī)應(yīng)該會(huì)報(bào)廢吧。但是大家知道,國(guó)人都是很精明的,國(guó)內(nèi)手機(jī)廠(chǎng)商也是,你要app開(kāi)發(fā)商要?;睿俏沂謾C(jī)廠(chǎng)商就堵死你?;畹囊磺型緩剑ㄈA為,小米,oppo,vivo)。
但是盡管如此有些面試官(我們就不糾結(jié)是哪些人了)還是會(huì)去問(wèn)這些問(wèn)題,既然有市場(chǎng)需求,我們還是不能免俗,學(xué)一學(xué)總歸沒(méi)有壞處。
如何?;?/h1>
?;罘绞?:1像素?;?/h5>
在屏幕熄滅的時(shí)候,偷偷創(chuàng)建一個(gè)Activity,它是全透明的,內(nèi)容只是左上角有一個(gè)像素,這樣,我們的app就會(huì)在屏幕熄滅時(shí),被系統(tǒng)認(rèn)為是前臺(tái)進(jìn)程,處于最安全的級(jí)別。然后在 屏幕亮起的時(shí)候,偷偷關(guān)閉這個(gè)1像素Activity,假裝無(wú)事發(fā)生....
?;罘绞?:前臺(tái)服務(wù)?;?/h5>
同樣是欺騙系統(tǒng)的手段,它偷偷地開(kāi)啟一個(gè)ForegroundService(不知道這是個(gè)啥玩意?玩過(guò)網(wǎng)易云音樂(lè)吧?你把a(bǔ)pp退到后臺(tái),音樂(lè)依然在播放,在通知欄你可以看到它的前臺(tái)服務(wù),對(duì)就是那玩意)。但是并不是所有app都想讓人看到它在通知欄里面有這么一個(gè)消息,所以, 讓這個(gè)消息消失吧。
4.3以下,沒(méi)有這個(gè)通知欄的消息,4.3到7.0,會(huì)看到整個(gè)消息,但是谷歌寫(xiě)了一個(gè)bug,我們可以開(kāi)啟兩個(gè)serviceId一樣的前臺(tái)進(jìn)程,然后關(guān)閉其中一個(gè),然后通知欄里面的消息就消失了。而7.0以后,也就是8.0開(kāi)始,谷歌把bug修復(fù)了,所以說(shuō),前臺(tái)服務(wù)?;钤?.0以上的手機(jī)上,永遠(yuǎn)會(huì)有這么一個(gè)通知欄的消息,如果你覺(jué)得無(wú)所謂,那就可以不在意,如果你是偷偷摸摸的?;睿幌胱屓税l(fā)現(xiàn),還是不要使用這個(gè)方法的好 。
如果實(shí)在是保不住呢?那就拉活吧
拉活方式1: 粘性廣播拉活
放棄吧,谷歌對(duì)于廣播的控制越來(lái)越嚴(yán)格,基本上GG,不用想了
拉活方式2: 賬戶(hù)同步拉活
這是谷歌自己的賬戶(hù)同步機(jī)制,利用這個(gè)機(jī)制,可以很穩(wěn)定地實(shí)現(xiàn)進(jìn)程拉活,但是 既然是利用系統(tǒng)的機(jī)制來(lái)拉活,控制權(quán)就不在我們自己手上,什么時(shí)候活,不知道。而且,國(guó)內(nèi)對(duì)于原生系統(tǒng)的改造力度很大,有些手機(jī)上注定就是不能賬戶(hù)拉活,沒(méi)辦法。
拉活方式3: JobService拉活
類(lèi)似定時(shí)器,開(kāi)啟一個(gè)Service,它是一個(gè)由系統(tǒng)調(diào)用完成的定時(shí)器,定期檢測(cè)進(jìn)程是不是活的,不是活的就嘗試?yán)睢?/p>
參考代碼:https://github.com/18598925736/MyKeep
就寫(xiě)到這里吧
從上面的文字中,大家應(yīng)該可以看出,在國(guó)內(nèi)環(huán)境,要做?;睿瑢?shí)在是惡心,各種改系統(tǒng)的手機(jī)廠(chǎng)家,要求我們做很多兼容設(shè)定,其實(shí)心里話(huà),不是很想做保活的需求。但是,拉活?;畹母拍?,我們還是要有的。
上面的github地址,是上面5個(gè) ?;罾罘绞降氖纠a,我不保證能夠運(yùn)行(因?yàn)槭謾C(jī)系統(tǒng)兼容性),但是有興趣的可以拿去參考看一看。最后,聽(tīng)說(shuō),jetpack上有?;畹膸?kù)可以使用,還沒(méi)去看過(guò),以后有空再說(shuō)吧 。歐了!


