Android 監聽APP進入后台或切換到前台方案對比


在我們開發的過程中,經常會遇到需要我們判斷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鍵來做一些如寫日志之類的操作的。網上谷歌百度會有很多類似的解決方案,在這里就不展開了。(不過這里可以推薦一下)

小結:我們能監聽到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以下的,可以考慮增加方案一判斷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM