Android程序保活(三):利用定時器和系統廣播
前兩篇文章講的是怎麼保護程序不被殺,今天來說說程序被殺後該怎麼拉活。
在系統安全管家清理記憶體的時候,第三方應用很容易被幹掉。如果不想被殺怎麼辦?最有效的解決辦法是: 誘導使用者把你的應用加入白名單 。但是不是所有使用者都會乖乖聽你的話。這就需要我們採取其他手段,想方設法再次把程序啟動。
今天介紹兩種常用的方法,可以讓程序被殺後還有復活的希望。
一、定時器
說到定時器,我們最先想到的肯定是 AlarmManager,利用它可以完成定時任務。具體用法我在這裡就不細說了,只講講在程序拉活的時候怎麼用。在 Service 啟動的時候,我們開啟一個定時任務:每十分鐘檢查一次 Service 是否存活,如果未在執行,就啟動該 Service。
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); Intent alarmIntent = new Intent(getApplication(), DaemonService.class); PendingIntent pendingIntent = PendingIntent.getService(this, 1024, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); am.cancel(pendingIntent); am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 10 * 60 * 1000, pendingIntent);
但是 AlarmManager 有個硬傷,在系統 force stop 某程序的時候,會清除該程序註冊的鬧鐘事件。這樣,定時器就無法完成定時任務,我們的目的達不到了。
好在天無絕人之路!Android 5.0 及以上版本提供了 JobScheduler 的 API,它和 AlarmManager 類似,都是為了完成定時任務。但是 JobScheduler 的觸發條件比較靈活,比如網路連線時、充電時、空閒時。最關鍵的一點是它無視 force stop,被系統強行殺死的程序依然能在某一時間完成定時任務,這就給我們提供了無限可能!
首先開啟 JobScheduler 定時任務,它需要指定一個完成定時任務的 JobService,觸發條件設定為網路連線、週期為十分鐘,順便設定重啟後繼續生效 JobScheduler 任務。
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); jobScheduler.cancelAll();JobInfo.Builder builder = new JobInfo.Builder(1024, new ComponentName(getPackageName(), ScheduleService.class.getName())); builder.setPeriodic(10 * 60 * 1000); builder.setPersisted(true); builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); int schedule = jobScheduler.schedule(builder.build()); if (schedule <= 0) { Log.w(TAG, "schedule error!"); }
我們在 ScheduleService 裡啟動要拉活的程序,然後告訴 JobScheduler 我們幹完活了。
public class ScheduleService extends JobService { private static final String TAG = "ScheduleService"; @Override public boolean onStartJob(JobParameters params) { Log.d(TAG, "onStartJob(): params = [" + params + "]"); Intent intent = new Intent(this, DaemonService.class); startService(intent); jobFinished(params, false); return false; } @Override public boolean onStopJob(JobParameters params) { Log.d(TAG, "onStopJob(): params = [" + params + "]"); return false; } }
註冊 manifest 時,需要宣告一下許可權。
<service android:name="com.silence.keeplive.timer.ScheduleService" android:enabled="true" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE" />
二、系統廣播
在發生特定系統事件時,系統會發出響應的廣播,通過在 AndroidManifest 中靜態註冊對應的廣播監聽器,即可在發生響應事件時拉活。但是對於國內各種定製的 ROM 來說,此方案的效果並不好,因為安全管家會管理開機和後臺自啟,攔截髮送給第三方應用的廣播,所以該方案只能作為備選方案。

常用的系統廣播
除了上面列出的,還有
電源連線或斷開:ACTION_POWER_CONNECTED、ACTION_POWER_DISCONNECTED
在測試過程中發現,程序在被 force stop 後,一段時間內是收不到廣播的,該方案的侷限性太大,收效甚微。
【附錄】

資料圖
需要資料的朋友可以加入Android架構交流QQ群聊:513088520
點選連結加入群聊【Android移動架構總群】: 加入群聊
獲取免費學習視訊,學習大綱另外還有像高階UI、效能優化、架構師課程、NDK、混合式開發(ReactNative+Weex)等Android高階開發資料免費分享。