Android后臺焙耍活實踐總結(jié):即時通訊應(yīng)用無法根治的“頑疾”

前言

Android進程和Service的彼亲觯活,是困擾Android開發(fā)人員的一大頑疾遏弱。因涉及到省電和內(nèi)存管理策略盆均,各廠商基于自家的理解,在自已ROOM發(fā)布于都對標準Android發(fā)行版作為或多或少的改動漱逸,使得應(yīng)用層程序在處理進程和Service崩嵋蹋活問題上變的異常復(fù)雜,且很難兼容饰抒,因為說不定哪款手機或者哪個版本的省電策略發(fā)生改變肮砾,那么隨之而來的就是進程和Service保活的差異袋坑。

在應(yīng)用場景上仗处,由于即時通訊應(yīng)用(包括IM聊天應(yīng)用、消息推送服務(wù)等)為了保證消息的全時、實時送達能力婆誓,必須要實現(xiàn)進程或Service的背曰罚活。而就這一看似不起眼的問題旷档,實際處理起來模叙,因為眾多Android手機和Android系統(tǒng)版本的差異,讓問題的處理充滿了不確定性鞋屈。

本文基于作者的實踐以及相關(guān)資料的整理范咨,總結(jié)了自已對Android進程和Service保活的理解厂庇,希望能為你的應(yīng)用開發(fā)帶來啟發(fā)渠啊。

概述

近期做了一個Android項目,涉及到了后臺進程和Service比酰活的問題替蛉,網(wǎng)上找了很多資料,基本的敝袈龋活方法都測試了躲查。結(jié)果是:不同的手機,不同的Android版本币氚兀活效果各有差異镣煮。最難繞過的是個廠商對“后臺程序保活”管理鄙麦。

本文主要把相應(yīng)的實踐結(jié)果和钡浯剑活方法進行總結(jié)。然而胯府,因筆者可用的測試真機有限嘉竟,可能存有不完整的地方薯演,還請及時提出指正并補充贪绘,大家共同進步绍哎。

手機QQ、微信這樣的大型IM是如何解決甭虑活問題的塘装?

以小米手機為例,MIUI的神隱模式讓很多IM和推送開發(fā)同行糾結(jié)不已:在MIUI深度休眠之后,默認會徹底斷開后臺應(yīng)用的socket影所。但微信蹦肴、QQ這樣的應(yīng)用,MIUI官方的帖子說了:給這2個應(yīng)用特殊照顧猴娩。好吧阴幌,特殊照顧勺阐,普通的APP只能繼續(xù)折騰了。(關(guān)于MIUI的神隱模式的討論矛双,見此貼的回復(fù):
http://www.52im.net/thread-354-1-1.html

本文實踐涉及到的真機型號和版本

手機:三星9100-4.1.2渊抽,三星9300-4.3,華為G730-4.1.2议忽,華為TL00H-EMUI3.1(android 5.1.1)懒闷,魅族MX4-Flyme4.2.8.2c(android 4.4.2)。

手頭能用的測試機就這些了栈幸。主要測試的service是一個最基本的service愤估,在相應(yīng)的生命周期的觸發(fā)函數(shù)上做了輸出。測試時都沒有添加到后臺保護中速址,注:三星的機子沒找到有后臺保護設(shè)置的地方玩焰。

為什么我們的后臺進程/Service會被結(jié)束掉?

我想到的是有三個方面:

  1. Android系統(tǒng)內(nèi)存回收機制芍锚;
  2. 各廠商對后臺程序的一個管理制度(就是允許程序后臺運行那個)昔园;
  3. 第三方軟件的清理(360什么的)。

其中有的后臺程序保護把程序結(jié)束的同時會把程序弄成停止狀態(tài)并炮,導(dǎo)致無法接收廣播默刚!

我們的保活方案有哪些逃魄?

1.控制onStartCommand函數(shù)的返回值:

我對這個函數(shù)的理解是:當服務(wù)被異常終止時羡棵,是否重啟服務(wù)?有些文章里面在用這個做保活時嗅钻,修改的是flag,在我實際測試中是無效店展。有效的做法是直接返回參數(shù)养篓。另外默認的flags值為0,是START_STICKY_COMPATIBILITY赂蕴。

具體代碼如下:
@Override
publicintonStartCommand(Intent intent,intflags,intstartId) {
    // TODO Auto-generated method stub
    return START_STICKY;
    //return super.onStartCommand(intent, flags, startId);
}
測試結(jié)果:

魅族的機子無效柳弄,不管默認還是修改參數(shù),在DDMS里面直接結(jié)束進程后都不會重啟服務(wù)概说。其它三臺機子(9100沒測):默認參數(shù)的情況下就會重啟服務(wù)碧注,return START_STICKY 會重啟,return START_NOT_STICKY 不會重啟糖赔。

另外:用360一鍵清理萍丐,或者360超級ROOT的手機優(yōu)化,會殺死進程放典,過會兒還是會重啟逝变,只是會慢很多基茵,大概是在排隊重啟服務(wù)。

2.在service 的onDestory里面重啟服務(wù):

這個在所有能觸發(fā)onDestory的情況下都是有效的壳影。4臺測試機都測試過拱层。直接startService 或者發(fā)送廣播重啟都可以 。

但能觸發(fā)onDestory的情況宴咧,我不知道內(nèi)存回收會不會觸發(fā)根灯。另外兩種情況(2,3)是不觸發(fā)的掺栅。我的測試方法是在“設(shè)置”-> 應(yīng)用管理-> 正在運行-> 停止服務(wù)烙肺。(這個是正常停止服務(wù),會觸發(fā)onDestory柿冲,所以上面的onStartCommand效果不會觸發(fā)茬高。)

3.提高服務(wù)的優(yōu)先級:

這個主要是針對第一種kill服務(wù)的情況,內(nèi)存回收機制假抄。由于這個測試比較難搭建怎栽。360清理什么把后臺的進程都殺的,體現(xiàn)不出優(yōu)先級這樣的概念宿饱。我的建議是能提高就提高熏瞄,下面幾個實驗。

[1] 前臺service:

創(chuàng)建一個通知使自己成為前臺service
測試結(jié)果:
360一鍵清理和手機優(yōu)化谬以,不會把該service結(jié)束掉强饮。

[2] 對于后臺保護:

華為G730不結(jié)束service,魅族和華為TL00H都會結(jié)束service为黎。通知欄的庇史幔活效果還是可以的,一般的應(yīng)用要求基本能滿足了铭乾。

[3] 若有root權(quán)限:

android:persistent="true",并放入system/app中
測試結(jié)果:
效果一般剪廉,三星9100上用360等清理工具殺不掉進程,在華為G730上沒什么效果.(這個測試跟onStartCommand有點干擾)炕檩。

4.守護進程:

雙服務(wù):360會同時殺掉兩個服務(wù)斗蒋,分兩個apk也一樣。native守護進程:360不會殺掉native的守護進程笛质,但在魅族和華為TL00H中待機一段時間后還是會被殺掉泉沾。

結(jié)論和待續(xù):

  1. 一般的應(yīng)用添加到后臺保護進程后,改個onStartCommand返回值妇押,再加個通知跷究。基本上大部分都能庇咚保活了揭朝。
  2. 雙服務(wù)我覺得沒有native守護進程來的好队贱,雖然360,微信什么的都有幾個進程服務(wù)潭袱,但如果不添加到后臺敝樱活的話,效果一樣不能蓖突唬活编丘,也會進入停止狀態(tài)。
  3. 但是.360手機助手會創(chuàng)建雙natice守護進程做相互的看守彤悔。存活的效果會高一點點嘉抓。“沒添加到后臺痹我ぃ活”一般只會殺一次抑片,(魅族是屏幕關(guān)閉后5分鐘,華為TL00H是屏幕關(guān)閉時)杨赤。

附個native守護進程:利用socket來判斷服務(wù)是否存在敞斋,需要在被保活的服務(wù)里創(chuàng)建一個監(jiān)聽socket疾牲。調(diào)試信息會在SD卡目錄下創(chuàng)建一個daemon.log植捎。使用方法:NDKFork port包名/.服務(wù)名。具體下載鏈接:http://download.csdn.net/detail/pvlking/9412815

Android應(yīng)用實現(xiàn)毖羧幔活的基本原理總結(jié)

都是通過雙進程互拉以及設(shè)置進程的重要性焰枢,除非你root后,把自己的進程設(shè)置成系統(tǒng)進程舌剂。

互拉的方式有很多種:

  1. 可以通過監(jiān)聽系統(tǒng)廣播來把自己拉起來
  2. 可以多個app相互拉
  3. 可以把自己的服務(wù)搞成前臺服務(wù)
  4. 在service的onstart方法里返回 STATR_STICK
  5. 添加Manifest文件屬性值為android:persistent=“true”
  6. 覆寫Service的onDestroy方法
  7. 服務(wù)互相綁定
  8. 設(shè)置鬧鐘济锄,定時喚醒
  9. 自己的app在native層fork一個子進程來與主進程互拉。

綜上所述霍转,總結(jié)下來就是拟淮,目前實現(xiàn)Android后臺保活沒有完美實現(xiàn)谴忧,只能針對不同的機型綜合使用上面列舉的方法,同時祈禱自已APP的用戶不要遇到奇葩機型的苯浅妫活問題沾谓。

推薦一個開源的解決方案

源碼托管地址
源碼托管地址是:https://github.com/52im/MarsDaemon

實現(xiàn)原理
**原理:
**使用Jni,在 c端 fork進程戳鹅,檢測Service是否存活均驶,若Service已被殺死,則進行重啟Service. 至于檢測方式枫虏,可以輪詢獲取子進程Pid,若為1, 則說明子進程被Init進程所領(lǐng)養(yǎng),已經(jīng)成為了孤兒進程. 但是這種方式比較消耗電量妇穴,并且由于不同手機系統(tǒng)定制的改變爬虱,當應(yīng)用被強制停止時,父進程并不一定被真正殺死腾它,因此在一些特定機型上是無法通過此方式進行判斷. 這里推薦使用liunx socket的方式進行類似心跳包的檢測跑筝,并且當觸發(fā)檢測Service是否被殺死之前,需要判斷應(yīng)用是否已經(jīng)被卸載瞒滴,如果應(yīng)用已經(jīng)被卸載曲梗,則不再進行檢測Service行為,直接調(diào)用exit(0)退出子進程妓忍,避免浪費系統(tǒng)資源和消耗電量.

**注意:
** 目前在Android 5.0系統(tǒng)上會把fork出來的進程放到一個進程組里虏两, 當程序主進程掛掉后,也會把整個進程組殺掉,因此用fork的方式也無法在Android5.0及以上系統(tǒng)實現(xiàn)守護進程. 這個是系統(tǒng)層面的限制世剖,當然也是為了優(yōu)化整個的系統(tǒng)環(huán)境,守護進程給手機帶來的體驗并不好

**具體見源碼:
**http://androidxref.com/5.0.0_r2/ ... /ProcessRecord.java

好消息:
Android5.0 以上目前已在 https://github.com/52im/MarsDaemon 中被黑科技攻克定罢,部分機型可能無法起到作用,但思路很值得借鑒旁瘫,代碼結(jié)構(gòu)也不錯, 具體方案請見源碼哦祖凫。

原文:http://www.52im.net/thread-429-1-1.html
因為原文已經(jīng)無法打開,所以將內(nèi)容復(fù)制到了這里


在android5.0及以上,谷歌出了一個JobService,經(jīng)測試可以在原生系統(tǒng)里定時執(zhí)行任務(wù),所以在三星這種機器上,可以用JobService拉起自己的Service

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市境蜕,隨后出現(xiàn)的幾起案子蝙场,更是在濱河造成了極大的恐慌,老刑警劉巖粱年,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件售滤,死亡現(xiàn)場離奇詭異,居然都是意外死亡台诗,警方通過查閱死者的電腦和手機完箩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拉队,“玉大人弊知,你說我怎么就攤上這事×豢欤” “怎么了秩彤?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長事哭。 經(jīng)常有香客問我漫雷,道長,這世上最難降的妖魔是什么鳍咱? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任降盹,我火速辦了婚禮,結(jié)果婚禮上谤辜,老公的妹妹穿的比我還像新娘蓄坏。我一直安慰自己价捧,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布涡戳。 她就那樣靜靜地躺著结蟋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妹蔽。 梳的紋絲不亂的頭發(fā)上椎眯,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音胳岂,去河邊找鬼编整。 笑死,一個胖子當著我的面吹牛乳丰,可吹牛的內(nèi)容都是我干的掌测。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼产园,長吁一口氣:“原來是場噩夢啊……” “哼汞斧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起什燕,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤粘勒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后屎即,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庙睡,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年技俐,在試婚紗的時候發(fā)現(xiàn)自己被綠了乘陪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡雕擂,死狀恐怖啡邑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情井赌,我是刑警寧澤谤逼,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站仇穗,受9級特大地震影響森缠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仪缸,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望列肢。 院中可真熱鬧恰画,春花似錦宾茂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至片林,卻和暖如春端盆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背费封。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工焕妙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弓摘。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓焚鹊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親韧献。 傳聞我的和親對象是個殘疾皇子末患,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,163評論 25 707
  • 本篇文章是后臺殺死系列的最后一篇,主要探討一下進程的彼涑活走搁,Android本身設(shè)計的時候是非常善良的,它希望進程在不...
    看書的小蝸牛閱讀 11,670評論 10 66
  • 追逐夢想迈窟,會很辛酸私植,會很累,會有無數(shù)的委屈车酣,會讓你無數(shù)次痛哭……但曲稼,你的人生會很充實,內(nèi)心會很快樂湖员!會有無數(shù)的難忘...
    林義平閱讀 176評論 0 0
  • 白玉玲瓏巧贫悄,夜水浮蓮苞。 內(nèi)中秉燭苗娘摔,純清新光照窄坦。 淚溢瓣霖干,文火煮心燒。 諳明人非蠟鸭津,悠緩訴今宵彤侍。
    正旦閱讀 358評論 0 0
  • 這是KK的讀書筆記 第十一篇 《刻意練習》是學習領(lǐng)域的一本經(jīng)典著作。 當所有人都以為能力出眾源于“天賦”時逆趋,作者通...
    張三川閱讀 645評論 0 1