Android初級第八講之應用如何保活

 

 本文來自http://blog.csdn.net/liuxian13183/ ,引用必須註明出處!

 

一般情況下應用保活的場景在於:後臺要不斷定位描述一條清晰軌跡、IM通信需要及時收到消息提醒等。

 

所謂保活就是避免被應用殺死,前臺應用自然不用說,主要是後臺應用。我們知道Android的應用優先級是-16到15,系統進程一般擁有-16到-1的優先級,而普通應用只擁有0-15的優先級;級別越小優先級越高。

首先進入後臺的應用不能是流氓進程,比如頻率的定位、發送網絡請求、不允許屏幕關閉等;如果做心跳,需要選擇合適的週期比如2分鐘一次,進行socket長連;可以設計一個前臺進程一個後臺進程,互相監測重啓對方;保持至少有1像素位於前臺。

其次如果強制保活,那麼90%的可能會殺死進程;4.4以前可以用AlarmManager的setRepeating方法可定時保活,之後可以使用setAndAllWhileIdle方法在保持在一段時間內集體喚醒;

再者可以通過註冊通知,比如開機啓動、時間變動、鎖屏解屏、網絡開關、收到短信、打入電話等;5.0以後可以使用JobSchedule的Api進行輪循操作,通過主動註冊網絡切換廣播來監聽(配置文件註冊方式已被禁止)

如果是Service還可以通過startForeGround的方式來讓服務處於前臺,避免殺死,關閉時使用stopForeGround來去掉。另外在重寫onStartCommand,返回START_STICKY,使service被殺死後自動重啓

public int onStartCommand(Intent intent, int flags, int startId) {        

return START_STICKY;    

}

還有通過WakeLock,需要申請到權限

 獲取鎖:

  1. WakeLock mWakeLock=null;  
  2. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);  
  3. /** 
  4.  * PowerManager.PARTIAL_WAKE_LOCK:保持CPU運轉,屏幕和鍵盤燈可能是關閉的 
  5.  * PowerManager.SCREEN_DIM_WAKE_LOCK:保持CPU運轉,運行屏幕顯示但是屏幕有可能是灰的,允許關閉鍵盤燈 
  6.  * PowerManager.SCREEN_BRIGHT_WAKE_LOCK:保持CPU運轉,屏幕高亮顯示,允許關閉鍵盤燈 
  7.  * PowerManager.FULL_WAKE_LOCK:保持CPU運轉,屏幕高亮顯示,鍵盤燈高亮顯示 
  8.  * PowerManager.ON_AFTER_RELEASE:當鎖被釋放時,保持屏幕亮起一段時間 
  9.  * PowerManager.ACQUIRE_CAUSES_WAKEUP:強制屏幕亮起 
  10.  */  
  11. mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SoundRecorder");  
  12. mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);  
  13. mWakeLock.acquire();  

 

          釋放鎖   

  1. if (mWakeLock.isHeld()) {  
  2.       mWakeLock.release();  
  3.   } 

如果是Root手機,可以設置應用的persistent標籤爲true。

 

終歸這樣的方式很流氓,就像張小龍對微信的期許一下:希望它是個人們有需要用一下,用完就放開的工具。

 

給Activity設置如下標籤,當用戶點擊最近任務時,App不會顯示在內,達到隱藏的目的

android:excludeFromRecents="true"

tips:另外針對線程做雙重UncaughtExceptionHandler,有助於防止App直接掛掉。

附斑馬行車對用戶權限的要求(主要設置白名單)

恭喜你,看到最後發現新天地!無論如何,在保活的時候要考慮下用戶的感受,理性保活!

其他如啓動1像素的activity,Native進程保活,通知拉起保存Service、監聽第三方和系統的公開廣播

 

Android進程保活招數大全

 

作者:騰訊——張興華

目前市面上的應用,貌似除了微信和手Q都會比較擔心被用戶或者系統(廠商)殺死問題。本文對 Android 進程拉活進行一個總結。

Android 進程拉活包括兩個層面:

A. 提供進程優先級,降低進程被殺死的概率

B. 在進程被殺死後,進行拉活

本文下面就從這兩個方面做一下總結。

1. 進程的優先級

Android 系統將盡量長時間地保持應用進程,但爲了新建進程或運行更重要的進程,最終需要清除舊進程來回收內存。

爲了確定保留或終止哪些進程,系統會根據進程中正在運行的組件以及這些組件的狀態,將每個進程放入“重要性層次結構”中。

必要時,系統會首先消除重要性最低的進程,然後是清除重要性稍低一級的進程,依此類推,以回收系統資源。

進程的重要性,劃分5級:

  1. 前臺進程(Foreground process)

  2. 可見進程(Visible process)

  3. 服務進程(Service process)

  4. 後臺進程(Background process)

  5. 空進程(Empty process)

前臺進程的重要性最高,依次遞減,空進程的重要性最低,下面分別來闡述每種級別的進程

1.1. 前臺進程 —— Foreground process

用戶當前操作所必需的進程。通常在任意給定時間前臺進程都爲數不多。

只有在內存不足以支持它們同時繼續運行這一萬不得已的情況下,系統纔會終止它們。

A. 擁有用戶正在交互的 Activity(已調用 onResume()

B. 擁有某個 Service,後者綁定到用戶正在交互的 Activity

C. 擁有正在“前臺”運行的 Service(服務已調用 startForeground()

D. 擁有正執行一個生命週期回調的 Service(onCreate()onStart() 或 onDestroy()

E. 擁有正執行其 onReceive() 方法的 BroadcastReceiver

1.2. 可見進程 —— Visible process

沒有任何前臺組件、但仍會影響用戶在屏幕上所見內容的進程。

可見進程被視爲是極其重要的進程,除非爲了維持所有前臺進程同時運行而必須終止,否則系統不會終止這些進程。

A. 擁有不在前臺、但仍對用戶可見的 Activity(已調用 onPause())。

B. 擁有綁定到可見(或前臺)Activity 的 Service

1.3. 服務進程 —— Service process

儘管服務進程與用戶所見內容沒有直接關聯,但是它們通常在執行一些用戶關心的操作(例如,在後臺播放音樂或從網絡下載數據)。

因此,除非內存不足以維持所有前臺進程和可見進程同時運行,否則系統會讓服務進程保持運行狀態。

A. 正在運行 startService() 方法啓動的服務,且不屬於上述兩個更高類別進程的進程。

1.4. 後臺進程 —— Background process

後臺進程對用戶體驗沒有直接影響,系統可能隨時終止它們,以回收內存供前臺進程、可見進程或服務進程使用。 

通常會有很多後臺進程在運行,因此它們會保存在 LRU 列表中,以確保包含用戶最近查看的 Activity 的進程最後一個被終止。

如果某個 Activity 正確實現了生命週期方法,並保存了其當前狀態,則終止其進程不會對用戶體驗產生明顯影響,

因爲當用戶導航回該 Activity 時,Activity 會恢復其所有可見狀態。

A. 對用戶不可見的 Activity 的進程(已調用 Activity的onStop() 方法)

1.5. 空進程 —— Empty process

保留這種進程的的唯一目的是用作緩存,以縮短下次在其中運行組件所需的啓動時間。 

爲使總體系統資源在進程緩存和底層內核緩存之間保持平衡,系統往往會終止這些進程。

A. 不含任何活動應用組件的進程

詳情參見:http://developer.android.com/intl/zh-cn/guide/components/processes-and-threads.html

2. Android 進程回收策略

Android 中對於內存的回收,主要依靠 Lowmemorykiller 來完成,是一種根據 OOM_ADJ 閾值級別觸發相應力度的內存回收的機制。

關於 OOM_ADJ 的說明如下:

其中

紅色部分代表比較容易被殺死的 Android 進程(OOM_ADJ>=4),

綠色部分表示不容易被殺死的 Android 進程,

其他表示非 Android 進程(純 Linux 進程)。

在 Lowmemorykiller 回收內存時會根據進程的級別優先殺死 OOM_ADJ 比較大的進程,

對於優先級相同的進程則進一步受到進程所佔內存和進程存活時間的影響。

Android 手機中進程被殺死可能有如下情況:

綜上,可以得出減少進程被殺死概率無非就是想辦法提高進程優先級,減少進程在內存不足等情況下被殺死的概率。

3. 提升進程優先級的方案

3.1. 利用 Activity 提升權限

3.1.1. 方案設計思想

監控手機鎖屏解鎖事件,在屏幕鎖屏時啓動1個像素的 Activity,在用戶解鎖時將 Activity 銷燬掉。

注意該 Activity 需設計成用戶無感知。

通過該方案,可以使進程的優先級在屏幕鎖屏時間由4提升爲最高優先級1。

3.1.2. 方案適用範圍

適用場景: 

本方案主要解決第三方應用及系統管理工具在檢測到鎖屏事件後一段時間(一般爲5分鐘以內)內會殺死後臺進程,已達到省電的目的問題。

適用版本: 適用於所有的 Android 版本。

3.1.3. 方案具體實現

首先定義 Activity,並設置 Activity 的大小爲1像素:

其次,從 AndroidManifest 中通過如下屬性,排除 Activity 在 RecentTask 中的顯示:

最後,控制 Activity 爲透明:

Activity 啓動與銷燬時機的控制:

3.2. 利用 Notification 提升權限

3.2.1. 方案設計思想

Android 中 Service 的優先級爲4,通過 setForeground 接口可以將後臺 Service 設置爲前臺 Service,使進程的優先級由4提升爲2,

從而使進程的優先級僅僅低於用戶當前正在交互的進程,與可見進程優先級一致,使進程被殺死的概率大大降低。

3.2.2. 方案實現挑戰

從 Android2.3 開始調用 setForeground 將後臺 Service 設置爲前臺 Service 時,

必須在系統的通知欄發送一條通知,也就是前臺 Service 與一條可見的通知時綁定在一起的。

對於不需要常駐通知欄的應用來說,該方案雖好,但卻是用戶感知的,無法直接使用。

3.2.3. 方案挑戰應對措施

通過實現一個內部 Service,在 LiveService 和其內部 Service 中同時發送具有相同 ID 的 Notification,然後將內部 Service 結束掉。

隨着內部 Service 的結束,Notification 將會消失,但系統優先級依然保持爲2。

3.2.4. 方案適用範圍

適用於目前已知所有版本。

3.2.5. 方案具體實現

4. 進程死後拉活的方案

4.1. 利用系統廣播拉活

#####4.1.1. 方案設計思想

在發生特定系統事件時,系統會發出響應的廣播,通過在 AndroidManifest 中“靜態”註冊對應的廣播監聽器,即可在發生響應事件時拉活。

常用的用於拉活的廣播事件包括:

4.1.2. 方案適用範圍

適用於全部 Android 平臺。但存在如下幾個缺點:

1) 廣播接收器被管理軟件、系統軟件通過“自啓管理”等功能禁用的場景無法接收到廣播,從而無法自啓。

2) 系統廣播事件不可控,只能保證發生事件時拉活進程,但無法保證進程掛掉後立即拉活。

因此,該方案主要作爲備用手段。

4.2. 利用第三方應用廣播拉活

4.2.1. 方案設計思想

該方案總的設計思想與接收系統廣播類似,不同的是該方案爲接收第三方 Top 應用廣播。

通過反編譯第三方 Top 應用,如:手機QQ、微信、支付寶、UC瀏覽器等,以及友盟、信鴿、個推等 SDK,找出它們外發的廣播,

在應用中進行監聽,這樣當這些應用發出廣播時,就會將我們的應用拉活。

4.2.2. 方案適用範圍

該方案的有效程度除與系統廣播一樣的因素外,主要受如下因素限制:

1) 反編譯分析過的第三方應用的多少

2) 第三方應用的廣播屬於應用私有,當前版本中有效的廣播,在後續版本隨時就可能被移除或被改爲不外發。

這些因素都影響了拉活的效果。

4.3. 利用系統Service機制拉活

4.3.1. 方案設計思想

將 Service 設置爲 START_STICKY,利用系統機制在 Service 掛掉後自動拉活:

4.3.2. 方案適用範圍

如下兩種情況無法拉活:

  1. Service 第一次被異常殺死後會在5秒內重啓,第二次被殺死會在10秒內重啓,第三次會在20秒內重啓,

  2. 一旦在短時間內 Service 被殺死達到5次,則系統不再拉起。

  3. 進程被取得 Root 權限的管理工具或系統工具通過 forestop 停止掉,無法重啓。

4.4. 利用Native進程拉活

#####4.4.1. 方案設計思想

**主要思想:**利用 Linux 中的 fork 機制創建 Native 進程,在 Native 進程中監控主進程的存活,

當主進程掛掉後,在 Native 進程中立即對主進程進行拉活。

**主要原理:**在 Android 中所有進程和系統組件的生命週期受 ActivityManagerService 的統一管理。

而且,通過 Linux 的 fork 機制創建的進程爲純 Linux 進程,其生命週期不受 Android 的管理。

#####4.4.2. 方案實現挑戰

挑戰一:在 Native 進程中如何感知主進程死亡。

要在 Native 進程中感知主進程是否存活有兩種實現方式:

  1. 在 Native 進程中通過死循環或定時器,輪訓判斷主進程是否存活,檔主進程不存活時進行拉活。

  2. 該方案的很大缺點是不停的輪詢執行判斷邏輯,非常耗電。

  3. 在主進程中創建一個監控文件,並且在主進程中持有文件鎖。

  4. 在拉活進程啓動後申請文件鎖將會被堵塞,一旦可以成功獲取到鎖,說明主進程掛掉,即可進行拉活。

  5. 由於 Android 中的應用都運行於虛擬機之上,Java 層的文件鎖與 Linux 層的文件鎖是不同的,

  6. 要實現該功能需要封裝 Linux 層的文件鎖供上層調用。

封裝 Linux 文件鎖的代碼如下:

Native 層中堵塞申請文件鎖的部分代碼:

挑戰二:在 Native 進程中如何拉活主進程。

通過 Native 進程拉活主進程的部分代碼如下,即通過 am 命令進行拉活

通過指定“–include-stopped-packages”參數來拉活主進程處於 forestop 狀態的情況。

挑戰三:如何保證 Native 進程的唯一。

從可擴展性和進程唯一等多方面考慮,將 Native 進程設計層 C/S 結構模式,主進程與 Native 進程通過 Localsocket 進行通信。

在Native進程中利用 Localsocket 保證 Native 進程的唯一性,不至於出現創建多個 Native 進程以及 Native 進程變成殭屍進程等問題。

4.4.3. 方案適用範圍

該方案主要適用於 Android5.0 以下版本手機。

該方案不受 forcestop 影響,被強制停止的應用依然可以被拉活,在 Android5.0 以下版本拉活效果非常好。

對於 Android5.0 以上手機,系統雖然會將native進程內的所有進程都殺死,

這裏其實就是系統“依次”殺死進程時間與拉活邏輯執行時間賽跑的問題,

如果可以跑的比系統邏輯快,依然可以有效拉起。

記得網上有人做過實驗,該結論是成立的,在某些 Android 5.0 以上機型有效。

4.5. 利用 JobScheduler 機制拉活

4.5.1. 方案設計思想

Android5.0 以後系統對 Native 進程等加強了管理,Native 拉活方式失效。

系統在 Android5.0 以上版本提供了 JobScheduler 接口,系統會定時調用該進程以使應用進行一些邏輯操作。

在本項目中,我對 JobScheduler 進行了進一步封裝,兼容 Android5.0 以下版本。

封裝後 JobScheduler 接口的使用如下:

4.5.2. 方案適用範圍

該方案主要適用於 Android5.0 以上版本手機。

該方案在 Android5.0 以上版本中不受 forcestop 影響,被強制停止的應用依然可以被拉活,在 Android5.0 以上版本拉活效果非常好。

僅在小米手機可能會出現有時無法拉活的問題。

4.6. 利用賬號同步機制拉活

#####4.6.1. 方案設計思想

Android 系統的賬號同步機制會定期同步賬號進行,該方案目的在於利用同步機制進行進程的拉活。添加賬號和設置同步週期的代碼如下:

該方案需要在 AndroidManifest 中定義賬號授權與同步服務。

####4.6.2. 方案適用範圍

該方案適用於所有的 Android 版本,包括被 forestop 掉的進程也可以進行拉活。

最新 Android 版本(Android N)中系統好像對賬戶同步這裏做了變動,該方法不再有效。

5. 其他有效拉活方案

經研究發現還有其他一些系統拉活措施可以使用,但在使用時需要用戶授權,用戶感知比較強烈。

這些方案包括:

  1. 利用系統通知管理權限進行拉活

  2. 利用輔助功能拉活,將應用加入廠商或管理軟件白名單。

這些方案需要結合具體產品特性來搞。

上面所有解釋這些方案都是考慮的無 Root 的情況。

其他還有一些技術之外的措施,比如說應用內 Push 通道的選擇:

  1. 國外版應用:接入 Google 的 GCM。

  2. 國內版應用:根據終端不同,在小米手機(包括 MIUI)接入小米推送、華爲手機接入華爲推送;其他手機可以考慮接入騰訊信鴿或極光推送與小米推送做 A/B Test。

  3. 原文地址:http://dev.qq.com/topic/57ac4a0ea374c75371c08ce8

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章