Android对App前后台运行状态的判断

作者: 亦枫 | 来源:发表于2016-07-04 23:23 被阅读7490次

在某些特定场景下,我们需要判断App是否处于后台运行状态,常见如:推送或聊天消息是否需要显示到通知栏中、设置手势密码状态下应用是否显示解锁界面等。

Android系统中判断App的前后台运行状态,大家常用的就是ActivityManager这个类,获取RunningAppProcessInfo或者RunningTaskInfo这两种方式,代码如下:

    /**
     * 判断app是否处于前台
     * @param context
     * @return
     */
    public static boolean isAppForeground(Context context){
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Service.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfoList = activityManager.getRunningAppProcesses();
        if (runningAppProcessInfoList==null){
            return false;
        }
        for (ActivityManager.RunningAppProcessInfo processInfo : runningAppProcessInfoList) {
            if (processInfo.processName.equals(context.getPackageName()) &&
                    processInfo.importance==ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
                return true;
            }
        }
        return false;
    }

    /**
     * 判断app是否处于前台
     * @param context
     * @return
     */
    public static boolean isRunningForeground (Context context) {
        ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
        String currentPackageName = cn.getPackageName();
        if(!TextUtils.isEmpty(currentPackageName) && currentPackageName.equals(context.getPackageName())) {
            return true ;
        }
        return false ;
    }

抛开性能问题不谈,这两种方式看上去貌似没有问题。但是请注意我用了“貌似”这个词呢,说明还是有问题的。

通常,我们会在Activity的onStop生命周期方法中判断应用是否进入后台。而用户在进行应用间切换、按HOME键进入桌面、按开机键进入锁屏状态会影响到应用的前后台运行状态。通过Debug可以看到,切换到其他应用(按HOME键也是切换到其他应用)时,这两种方法返回false,表明应用进入后台运行状态,但按关机键进入锁屏状态时,返回true,也就是说App依然处于前台运行状态。拿手势密码案例来说,如果用户按开机键进入锁屏状态,当再次按开机键回到应用时,当然希望应用之前也算进入后台状态而显示解锁界面,显然,上面两种方法已经不满足我们的需求了。

那么有没有一种更好的方式也能监听到用户使用开机键进入手机锁屏状态下呢?答案当然是有!通过Activity的生命周期方法我们可以实现这样的功能。

我们知道,如果应用处于前台,当前Activity一定调用了onResume方法,而应用进入后台,当前Activity一定调用了onStop方法。根据这个原理,如果我们使用一个计数变量activityCount,初始化为0,在我们自定义的所有Activity基类BaseActivity对应的生命周期方法中做加减计数处理,那么,当activityCount为1时,则表示应用处于前台运行状态,反之,为0时表示应用处于后台运行状态。

利用Activity生命周期来判断应用的前后台运行状态,很轻松的获取了各种情境下应用的前后台状态变换。但是有个细节需要注意,activityCount的加减处理应该加在Activity的哪个生命周期方法里面。

很多朋友会不假思索的选择在onPause方法里面减一,在onResume方法里面加一。这种情况下,会出现一个短暂的间隔问题。

比如从Activity A跳转至Activity B,A和B的生命周期变化经历了如下一个过程:

A onPause ——> B onCreate ——> B onStart ——> B onResume ——> A onStop

可以看出,在A onPause到 B onResume之间,根据我们对activityCount的判断,表示在此短暂的阶段应用处于后台运行状态,而实际情况是前台运行状态,显然是有问题的。

所以,正确的方式应该是在onStart里面对activityCount加一,在onStop里面对Activity减一,而这个阶段的时间小到可以忽略不计。

上述这种间隔问题主要考虑到诸如消息推送这场景下的一个应用前后台状态的判断,而在手势密码这种使用场景下,无需考虑,也可以在其他生命周期方法中处理,只需要在onResume方法中判断是否需要展示解锁解界面。

补充:应用进入后台再回到前台时,当前Activity生命周期的变化过程如下,通常往往容易忽视在onRestart之后的onStart方法:

onPause ——> onStop ——> onRestart ——> onStart ——> onResume

相关文章

网友评论

  • 相互交流:如果我们在基类BaseActivity里面的是在onStart里面对activityCount加一,在onStop里面对Activity减一,如果我的需求是要从后台切换到前台,需要弹出界面锁屏,。。比如应用在后台了,在进入前台,也会调用onStart()方法进行加一,此时在那个生命周期做判断都是有问题的...楼主说的这种方法判断应用是在前台还是在后台,,是针对什么场景的。。还望解答,不太明白...
    亦枫:@相互交流 嗯,有点绕,在你说的这种情况下,count为1,所以应用在前台,并且是后台转入前台,所以需要展示解锁界面。按照我的写法,如果从A界面进去B界面,B的onresume中判断时,count为2,所以不需要展示解锁界面。对于解锁这个例子,文章中我可能漏了判断展示解锁的条件:count是否为1,多谢提醒:smile:
    相互交流:@亦枫 onResume方法中判断是否需要展示解锁解界面。但是从后台进入前台,先调用onStart(),,在调用onResume(),此时获取到activityCount是处于前台,而事实上他是从后台到前台...
    亦枫:@相互交流 生命周期这部分主要是针对特殊场景,比如推送。如果是解锁,就有多种选择了,文章中有提到哈
  • 相互交流:正确的方式应该是在onStart里面对activityCount加一,在onStop里面对Activity减一,楼主在那个生命周期里面判断是否显示界面锁更好了???
    亦枫:@相互交流 也分使用场景的
  • Alex_Cin:楼主你好,我的简书有利用Application来监听app处于前台还是后台,目前我们的app就是这么干的。代码是外国友人的方案,可惜我只是搬砖的。
    亦枫:@Alex_Cin 好的,我看看,欢迎交流:smile:
    亦枫:@Alex_Cin 怎么监听的,用ActivityLifecycleCallbacks的吗
    Alex_Cin:@Alex_Cin 这是链接 http://www.jianshu.com/p/e6f2759d3f27
  • forevan:am.getRunningTasks在L上已经被标示为deprecated
    亦枫:@ministorm 嗯,是的
  • 于晓飞93:API-21以上这个方法就不能用了
    亦枫:@泰_然 嗯,废弃掉了
    泰_然:@亦枫 利用ActivityManager 来获取 ActivityTask 最前端进程的方法,Android 5.0之后 系统不再提供这个的接口
    亦枫:@于晓飞93 哪个方法:scream:
  • ccc48ba4d41c:如果我要监听其他应用程序的前后台运行状态,你这个方案就不行吧。
    亦枫:@跘廿誓唁 嗯,这里主要监听自己应用的前后台运行状态。
  • openGL小白:在14以后,系统已经这样帮我们做好了回调Activity的相关工作,在回调中做这个就行了。
    Application.ActivityLifecycleCallbacks,你可以看看这个类的使用。就可以用来判断前后台,
    也是计数方式
    塘泥:@coolstar1204 应该是这个回调加application的onTrimMemory结合
    亦枫:@coolstar1204 这个类还没了解过,有时间查查资料

本文标题:Android对App前后台运行状态的判断

本文链接:https://www.haomeiwen.com/subject/kclhjttx.html