標籤:日誌統計 str 自身 run 作用 對比分析 rac 消費 資料
在我們開發的過程中,經常會遇到需要我們判斷app進入後台,或者切換到前台的情況。比如我們想判斷app切換到前台時,顯示一個解鎖介面,要求使用者輸入解鎖密碼才能繼續進行操作;我們想判斷app切換到後台,記錄一下log;或者當使用者切換回前台時,我們想重新整理一下頁面的資料等等......
android裡面監聽app前背景方案很多(這還是得歸根於安卓提供了豐富的api和強大的架構支撐,呵呵~),比如可以通過ActivityManager提供的getRunningAppProcesses()擷取系統當前啟動並執行app,從而判斷app是否處於前台。或者通過監聽點擊Home鍵,判斷app是否回到了後台。下面將針對筆者已知的幾種方案,進行對比分析。
方案一:利用ActivityManager的RunningAppProcessInfo類
ActivityManager在整個系統裡面起著非常重要的作用,主要為系統中運行著的activity互動提供介面,其中RunningAppProcessInfo類則封裝了正在運行著的進程資訊,當然也包含了正在啟動並執行app的包名,因此我們可以activitymanager.getRunningAppProcesses()擷取當前啟動並執行app列表,對比自身的包名,來判斷本身app是否處於前台運行。
這打斷一下,ActivityManager架構是Android系統十分重要的一部分,在以後有時間,筆者會好好學習整理ActivityManager架構的分析。
回到這裡,下面給出部分關鍵代碼。
/** * App前後台狀態 */ public boolean isForeground = false; @Override protected void onResume() { ...... if (isForeground == false) { //由後台切換到前台 isForeground = true; } } @Override protected void onPause() { ...... if (!isAppOnForeground()) { //由前台切換到後台 isForeground = false; } } /** * 判斷app是否處於前台 * * @return */ public boolean isAppOnForeground() { ActivityManager activityManager = (ActivityManager) getApplicationContext() .getSystemService(Context.ACTIVITY_SERVICE); String packageName = getApplicationContext().getPackageName(); /** * 擷取Android裝置中所有正在啟動並執行App */ List<RunningAppProcessInfo> appProcesses = activityManager .getRunningAppProcesses(); if (appProcesses == null) return false; for (RunningAppProcessInfo appProcess : appProcesses) { // The name of the process that this object is associated with. if (appProcess.processName.equals(packageName) && appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true; } } return false; }
小結:通過ActivityManager來擷取當前啟動並執行app列表,然後判斷我們的app是否處於前台,能基本達到我們的預期需求。但如果將上面代碼放到每一個activity,或者activity基類裡面,這消耗還是挺大的。而且而且,ActivityManager通過.getRunningAppProcesses()擷取當前運行列表這個方法,在5.0以後已經被deprecated掉了....(心中萬馬奔騰...)
方案二:監聽Home鍵點擊
說起home鍵的監聽,也算是android裡面的一個梗。這看上去簡單的功能,實際上實現起來卻十分的曲折,這跟android系統的設計有很大的關係。當home鍵被點擊的時候,會發出一個系統廣播,在系統收到這個廣播以後,會在framework層做一系列操作將當前的app退到後台,然後把事件消費掉不傳給應用程式層,所以這時候 onKeyDown事件也接收不到了..用官方的解釋就是——“Home key. This key is handled by the framework and is never delivered to applications.”。實際上這也是為了安全性的考慮,不然每家的app都監聽home鍵,然後禁掉響應,不都成了流氓軟體了。
官方不支援,可是這難不到我們萬能的攻城獅們的,畢竟有很多想我們正規的開發人員,還是需要監聽home鍵來做一些如寫日誌之類的操作的。網上Google百度會有很多類似的解決方案,在這裡就不展開了。(不過這裡可以推薦一下)
小結:我們能監聽到home鍵點擊,當然就知道app處於前台還是後台了。但畢竟這個方案是基於官方不支援的前提下的,而且home鍵的監聽在很多裝置都會有相容性的問題,因此我們不大推薦這樣做。
方案三:利用ActivityLifecycleCallbacks監聽所有activity的生命週期
通過監聽所有activity的onStart、onStop調用,然後統計當前是不是所有的activity都調用了onStop,確實可以判斷app處於了後台,不過讓我們重寫每一個activity的onStop,並加這段奇怪的代碼,實在不大優雅,即使在activity基類裡面統一寫,那天如果忘了或者不需要繼承基類的activity,就不大好了。
因此,這裡推薦一個新的介面ActivityLifecycleCallbacks,說新也不新,其實早在API 14 (android 4.0)就已經推出了。ActivityLifecycleCallbacks介面在Application類裡面,因此需要我們自己繼承Application,自訂一個MyApplication,然後註冊介面。ActivityLifecycleCallbacks為application提供了對所有activity生命週期的監聽,因此我們通過重寫ActivityLifecycleCallbacks的onActivityStarted和onActivityStopped方法,定義一個變數,來統計當前有幾個activity處於前台。
/** * 當前Acitity個數 */ private int activityAount = 0; @Override public void onCreate() { ...... registerActivityLifecycleCallbacks(activityLifecycleCallbacks); ...... } /** * Activity 生命週期監聽,用於監控app前後台狀態切換 */ ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } @Override public void onActivityStarted(Activity activity) {// if (activityAount == 0) {// //app回到前台// isForeground = true;// } activityAount++; } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { activityAount--; if (activityAount == 0) { isForeground = false; } } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } };
以上代碼寫在MyApplication裡面。怎麼樣,是不是很簡單快捷!而且準確無誤。
總結:
1、利用ActivityManager的RunningAppProcessInfo類,直接粗暴,官方摒棄,不推薦;
2、監聽Home鍵點擊,官方不支援,相容性差,不穩定,不推薦;
3、利用ActivityLifecycleCallbacks監聽所有activity的生命週期,官方指定飲品,哦,不對,官方指定介面,大力推薦!我們舉一反三,利用ActivityLifecycleCallbacks監聽,我們還能控制我們的activity堆棧,甚至還可以在裡面做日誌統計...想想還是很強大的。
PS:雖則利用ActivityLifecycleCallbacks介面監聽的方案最優,但這畢竟是4.0以後的產品,因此對於4.0以下的,可以考慮增加方案一判斷。
Android 監聽APP進入後台或切換到前台方案對比