天天看點

Android背景保活實踐總結:即時通訊應用無法根治的“頑疾”前言 學習交流概述手機QQ、微信這樣的大型IM是如何解決保活問題的?本文實踐涉及到的真機型号和版本為什麼我們的背景程序/Service會被結束掉?我們的保活方案有哪些?Android應用實作保活的基本原理總結推薦一個開源的解決方案

前言

Android程序和Service的保活,是困擾Android開發人員的一大頑疾。因涉及到省電和記憶體管理政策,各廠商基于自家的了解,在自已ROOM釋出時都會對标準Android發行版作或多或少的改動,使得應用層程式在處理程序和Service保活問題上變的異常複雜,且很難相容,因為說不定哪款手機或者哪個版本的省電政策發生改變,那麼随之而來的就是程序和Service保活的差異。

在應用場景上,由于即時通訊應用(包括IM聊天應用、消息推送服務等)為了保證消息的全時、實時送達能力,必須要實作程序或Service的保活。而就這一看似不起眼的問題,實際處理起來,因為衆多Android手機和Android系統版本的差異,讓問題的處理充滿了不确定性。

本文基于作者的實踐以及相關資料的整理,總結了自已對Android程序和Service保活的了解,希望能為你的應用開發帶來啟發。

學習交流

- 更多即時通訊技術資料:

http://www.52im.net/forum.php?mod=collection&op=all

- 即時通訊開發交流群:

215891622

 [推薦]

概述

近期做了一個Android項目,涉及到了背景程序和Service保活的問題,網上找了很多資料,基本的保活方法都測試了。結果是:不同的手機,不同的Android版本保活效果各有差異。最難繞過的是個廠商對“背景程式保活”管理。

本文主要把相應的實踐結果和保活方法進行總結。然而,因筆者可用的測試真機有限,可能存有不完整的地方,還請及時提出指正并補充,大家共同進步。

手機QQ、微信這樣的大型IM是如何解決保活問題的?

以小米手機為例,MIUI的神隐模式讓很多IM和推送開發同行糾結不已:在MIUI深度休眠之後,預設會徹底斷開背景應用的socket。但微信、QQ這樣的應用,MIUI官方的文章說了:給這2個應用特殊照顧。好吧,特殊照顧,普通的APP隻能繼續折騰了。

(關于MIUI的神隐模式的讨論,見此貼的回複:

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,在相應的生命周期的觸發函數上做了輸出。測試時都沒有添加到背景保護中,注:三星的機子沒找到有背景保護設定的地方。

為什麼我們的背景程序/Service會被結束掉?

我想到的是有三個方面:

1)Android系統記憶體回收機制;

2)各廠商對背景程式的一個管理制度(就是允許程式背景運作那個);

3)第三方軟體的清理(360什麼的)。

其中有的背景程式保護把程式結束的同時會把程式弄成停止狀态,導緻無法接收廣播!

我們的保活方案有哪些?

1)控制onStartCommand函數的傳回值:

我對這個函數的了解是:當服務被異常終止時,是否重新開機服務?有些文章裡面在用這個做保活時,修改的是flag,在我實際測試中是無效。有效的做法是直接傳回參數。另外預設的flags值為0,是START_STICKY_COMPATIBILITY。

具體代碼如下

@Override

publicintonStartCommand(Intent intent,intflags,intstartId) {

    // TODO Auto-generated method stub

    returnSTART_STICKY;

    //return super.onStartCommand(intent, flags, startId);

}

測試結果

魅族的機子無效,不管預設還是修改參數,在DDMS裡面直接結束程序後都不會重新開機服務。其它三台機子(9100沒測):預設參數的情況下就會重新開機服務,return START_STICKY 會重新開機,return START_NOT_STICKY 不會重新開機。

另外

:用360一鍵清理,或者360超級ROOT的手機優化,會殺死程序,過會兒還是會重新開機,隻是會慢很多,大概是在排隊重新開機服務。

2)在service 的onDestory裡面重新開機服務:

這個在所有能觸發onDestory的情況下都是有效的。4台測試機都測試過。直接startService 或者發送廣播重新開機都可以 。

但能觸發onDestory的情況,我不知道記憶體回收會不會觸發。另外兩種情況(2,3)是不觸發的。我的測試方法是在“設定”-> 應用管理-> 正在運作-> 停止服務。(這個是正常停止服務,會觸發onDestory,是以上面的onStartCommand效果不會觸發。)

3)提高服務的優先級:

這個主要是針對第一種kill服務的情況,記憶體回收機制。由于這個測試比較難搭建。360清理什麼把背景的程序都殺的,展現不出優先級這樣的概念。我的建議是能提高就提高,下面幾個實驗。

[

1

] 前台service:

建立一個通知使自己成為前台service

測試結果:

360一鍵清理和手機優化,不會把該service結束掉。

2

] 對于背景保護:

華為G730不結束service,魅族和華為TL00H都會結束service。通知欄的保活效果還是可以的,一般的應用要求基本能滿足了。

3

] 若有root權限:

android:persistent="true",并放入system/app中

效果一般,三星9100上用360等清理工具殺不掉程序,在華為G730上沒什麼效果.(這個測試跟onStartCommand有點幹擾)。

4)守護程序:

雙服務:360會同時殺掉兩個服務,分兩個apk也一樣。

native守護程序:360不會殺掉native的守護程序,但在魅族和華為TL00H中待機一段時間後還是會被殺掉。

結論和待續:

1)一般的應用添加到背景保護程序後,改個onStartCommand傳回值,再加個通知。基本上大部分都能保活了。

2)雙服務我覺得沒有native守護程序來的好,雖然360,微信什麼的都有幾個程序服務,但如果不添加到背景保活的話,效果一樣不能保活,也會進入停止狀态。

3)但是.360手機助手會建立雙natice守護程序做互相的看守。存活的效果會高一點點。“沒添加到背景保活”一般隻會殺一次,(魅族是螢幕關閉後5分鐘,華為TL00H是螢幕關閉時)。

附個native守護程序:利用socket來判斷服務是否存在,需要在被保活的服務裡建立一個監聽socket。調試資訊會在SD卡目錄下建立一個daemon.log。使用方法:NDKFork port包名/.服務名。具體下載下傳連結:

http://download.csdn.net/detail/pvlking/9412815

Android應用實作保活的基本原理總結

都是通過雙程序互拉以及設定程序的重要性,除非你root後,把自己的程序設定成系統程序。

互拉的方式有很多種:

1)可以通過監聽系統廣播來把自己拉起來

2)可以多個app互相拉

3)可以把自己的服務搞成前台服務

4)在service的onstart方法裡傳回 STATR_STICK

5)添加Manifest檔案屬性值為android:persistent=“true”

6)覆寫Service的onDestroy方法

7)服務互相綁定

8)設定鬧鐘,定時喚醒

9)自己的app在native層fork一個子程序來與主程序互拉。

綜上所述,總結下來就是,目前實作Android背景保活沒有完美實作,隻能針對不同的機型綜合使用上面列舉的方法,同時祈禱自已APP的使用者不要遇到奇葩機型的保活問題。

推薦一個開源的解決方案

1)源碼托管位址

源碼托管位址是:

https://github.com/52im/MarsDaemon

2)實作原理 原理

]:使用Jni,在 c端 fork程序,檢測Service是否存活,若Service已被殺死,則進行重新開機Service.  至于檢測方式,可以輪詢擷取子程序Pid,若為1, 則說明子程序被Init程序所領養,已經成為了孤兒程序.    但是這種方式比較消耗電量,并且由于不同手機系統定制的改變,當應用被強制停止時,父程序并不一定被真正殺死,是以在一些特定機型上是無法通過此方式進行判斷. 這裡推薦使用liunx socket的方式進行類似心跳包的檢測,并且當觸發檢測Service是否被殺死之前,需要判斷應用是否已經被解除安裝,如果應用已經被解除安裝,則不再進行檢測Service行為,直接調用exit(0)退出子程序,避免浪費系統資源和消耗電量.

注意

]: 目前在Android 5.0系統上會把fork出來的程序放到一個程序組裡, 當程式主程序挂掉後,也會把整個程序組殺掉,是以用fork的方式也無法在Android5.0及以上系統實作守護程序. 這個是系統層面的限制,當然也是為了優化整個的系統環境,守護程序給手機帶來的體驗并不好

具體見源碼

]:

http://androidxref.com/5.0.0_r2/ ... /ProcessRecord.java
Android背景保活實踐總結:即時通訊應用無法根治的“頑疾”前言 學習交流概述手機QQ、微信這樣的大型IM是如何解決保活問題的?本文實踐涉及到的真機型号和版本為什麼我們的背景程式/Service會被結束掉?我們的保活方案有哪些?Android應用實作保活的基本原理總結推薦一個開源的解決方案
好消息

Android5.0 以上目前已在

中被黑科技攻克,部分機型可能無法起到作用,但思路很值得借鑒,代碼結構也不錯, 具體方案請見源碼哦。

(本文同步釋出于:

http://www.52im.net/thread-429-1-1.html
作者: Jack Jiang (點選作者姓名進入Github) 出處: http://www.52im.net/space-uid-1.html 交流: �歡迎加入即時通訊開發交流群 讨論: http://www.52im.net/ Jack Jiang同時是 【原創Java Swing外觀工程BeautyEye】 【輕量級移動端即時通訊架構MobileIMSDK】

的作者,可前往下載下傳交流。

本文 歡迎轉載,轉載請注明出處(也可前往

我的52im.net 找到我)。

繼續閱讀