经常在一些场景中,需要判断App是否在后台运行,从而做一些相应的处理。比如切换到后台运行后显示解锁界面等。接下来记录下平常用到的几种方法。
方法一
利用ActivityManager,获取RuningAppProcessInfo或者RuningTaskInfo这两种方法,代码如下:
1、获取RuningAppProcessInfo
public 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;
}
2、获取RuningTaskInfo
public static boolean isAppForeground(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 ;
}
这两种方法有点类似于在使用windows的任务管理器,先抛开其性能方面的影响,这两种方法在,例如用户在进行应用间切换、按HOME键进入桌面、按开机键进入锁屏,都可能会影响到判断结果。而且获取RuningTaskInfo中getRunningTasks(1)方法在Android5.0中已经被废弃掉了,不推荐使用。
鉴于有一些问题的存在,这里推荐使用方法二。
方法二
先上代码:
public class MyApplication extends Application {
public int count = 0;
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityStopped(Activity activity) {
count--;
if (count == 0) {
Log.v("vergo", "**********切到后台**********");
}
}
@Override
public void onActivityStarted(Activity activity) {
if (count == 0) {
Log.v("vergo", "**********切到前台**********");
}
count++;
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
});
}
}
Android在SDK 14的时候提供了ActivityLifecycleCallbacks接口,可以通过这个它拿到App所有Activity的生命周期回调。
通过重写Application的onCreate()方法,或者在Application的无参构造方法内,调用registerActivityLifecycleCallbacks()方法,并实现ActivityLifecycleCallbacks接口。
分析:
首先简单回顾下Activity的生命周期,如果Activity调用了onResume(),那么这个Activity肯定是可见的,也就是运行在前台的。如果调用了onPause(),且没有Activity来调用onResume(),那么App就在后台运行。
根据这个原理,我们可以定义一个计数变量count初始为0,在ActivityLifecycleCallbacks回调的onActivityResumed()方法中加一,在onActivityPaused()方法中减一,如果count等于1,表示App在前台,如果count等于0,则表示在后台。
但是很快就会发现,如果在onActivityResumed()和onActivityPaused()中进行计数,会有个延时,导致判断不准确。
又回到Activity的生命周期中来,比如从Activity A跳转至Activity B,A和B的生命周期变化经历了如下的变化:
A onPause ——> B onCreate ——> B onStart ——> B onResume ——> A onStop
可以看出,在A onPause到B onResume之间,根据我们对count的判断,表示在此短暂的阶段应用处于后台运行状态,这样逻辑肯定是不正确的。
所以,正确的方式应该在ActivityLifecycleCallbacks回调的onActivityStarted()方法里面对count加一,在onActivityStopped()方法里减一。