zoukankan      html  css  js  c++  java
  • 判断你的应用在前台还是在后台

    我的尝试

    /**
         * 判断应用是否是在后台
         */
        public static boolean isBackground(Context context) {
            ActivityManager activityManager = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
            KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(KEYGUARD_SERVICE);
    
            List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
                    .getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
                if (TextUtils.equals(appProcess.processName, context.getPackageName())) {
                    return appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
                }
            }
            return false;
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    一开始我用这个方法用来判断手机是否处于后台状态,如果应用处于后台的话,就停止应用程序中的音乐播放,但是却发现,点击 Home 键让应用退到后台并不会让音乐停止播放,后来发现如果应用正在播放音乐的话,此时点击 Home 键应用并不会进入后台状态( ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND ),而是进入了一个 ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE 的状态, 这个状态正是系统提供的应用后台播放应用的状态,好了,我们继续在原来的代码上进行完善:

    /**
         * 判断应用是否是在后台
         */
        public static boolean isBackground(Context context) {
            ActivityManager activityManager = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
            KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(KEYGUARD_SERVICE);
    
            List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
                    .getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
                if (TextUtils.equals(appProcess.processName, context.getPackageName())) {
                    return (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND || appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE);
                }
            }
            return false;
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    这样即使应用在播放应用的时候点击 Home 键也可以认为此时处于后台状态,但是此时依然会出现判断应用是否在后台不准确的情况,我们继续优化原来的代码。

    /**
         * 判断应用是否是在后台
         */
        public static boolean isBackground(Context context) {
            ActivityManager activityManager = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
            KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(KEYGUARD_SERVICE);
    
            List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
                    .getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
                if (TextUtils.equals(appProcess.processName, context.getPackageName())) {
                    boolean isBackground = (appProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE);
                    boolean isLockedState = keyguardManager.inKeyguardRestrictedInputMode();
                    return isBackground || isLockedState;
                }
            }
            return false;
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    上面这个方法通过监测应用进程是否处于前台状态,是否可见,手机是否锁屏来判断应用是否处于前台,如果这些情况有任一条达成的话就表明应用没有处于前台状态,这个方法在大部分测试机上都没有发现异常,但是我却在原生的 Nexus 5 手机上发现当当栈中的Activiy只有一个 Activity的时候,例如:应用启动,SplashActivity启动LoginActivity后,关闭SplashActivity,此时栈中就只生剩下了LoginActivity,此时,无论是点击返回键退出、点击 Home 键退到后台甚至点击右侧的多进程按键,此时的appProcess.importance 的都为 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,这样就彻底宣告了判断 appProcess.importance方法的失败。

    最终用法

    继承 Application.ActivityLifecycleCallbacks 写一个自己的 ActivityLifecycleCallbacks:

    public class MyLifecycleHandler implements Application.ActivityLifecycleCallbacks {
        private static int resumed;
        private static int paused;
        private static int started;
        private static int stopped;
    
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        }
    
        @Override
        public void onActivityStarted(Activity activity) {
            ++started;
        }
    
        @Override
        public void onActivityResumed(Activity activity) {
            ++resumed;
        }
    
        @Override
        public void onActivityPaused(Activity activity) {
            ++paused;
            android.util.Log.w("test", "application is in foreground: " + (resumed > paused));
        }
    
        @Override
        public void onActivityStopped(Activity activity) {
            ++stopped;
            android.util.Log.w("test", "application is visible: " + (started > stopped));
        }
    
        @Override
        public void onActivityDestroyed(Activity activity) {
        }
    
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }
    
        public static boolean isApplicationVisible() {
            return started > stopped;
        }
    
        public static boolean isApplicationInForeground() {
        // 当所有 Activity 的状态中处于 resumed 的大于 paused 状态的,即可认为有Activity处于前台状态中 
            return resumed > paused;
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    然后在自己定义的 Application 中的 onCreate() 方法中注册该 ActivityLifecycleCallbacks:

    registerActivityLifecycleCallbacks(new MyLifecycleHandler());
    • 1
    • 1

    这样的话我们就可以在自己定义的 ActivityLifecycleCallbacks 中监控自己应用中的所有的 Activity 的状态,通过 MyLifecycleHandler.isApplicationInForeground() 方法即可判断应用此时一定处于前台状态中,反之,则是处于”后台状态”。

    以上就是我对于当前应用是处于前台还是后台的判断,无论大家是发现BUG和改进,还是有其它更好的办法,欢迎前来讨论!

    需要注意:ActivityLifecycleCallbacks是在 API 14 即 Android 4.0加入的。

    参考链接

    http://stackoverflow.com/questions/3667022/checking-if-an-android-application-is-running-in-the-background/13809991#13809991 
    http://stackoverflow.com/questions/3667022/checking-if-an-android-application-is-running-in-the-background/5862048#5862048 
    https://segmentfault.com/q/1010000000687701 
    http://www.dewen.net.cn/q/10250/android%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B%E9%87%8D%E8%A6%81%E7%AD%89%E7%BA%A7%E4%B8%ADIMPORTANCE_BACKGROUND%E5%92%8CIMPORTANCE_PERCEPTIBLE%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%EF%BC%9F

     
     
  • 相关阅读:
    【2020】iOS证书(.p12)和描述文件(.mobileprovision)一键申请流程
    苹果开发者账号正在调查原因解答
    【2020最新】苹果iOS开发者到期续费流程
    【2020】联系苹果客服电话入口及步骤
    苹果电脑Transporter App及Windows上传ipa工具Appuploader
    一文学会苹果TestFlight上架详细流程
    iOS APP打包上线App Store七个步骤详解(2020版)
    技术分享 | mysql 表数据校验
    MySQL 自带的4个系统数据库的说明
    linux定时任务crontab怎样执行root命令
  • 原文地址:https://www.cnblogs.com/dongweiq/p/7027585.html
Copyright © 2011-2022 走看看