注意,测试场景应该包含back键退出、home键退出、锁屏、亮屏、通知栏跳入其他app、通知栏进入当前app等情况。
ActivityLifecycleCallbacks
该接口提供了一系列回调方法,用于让开发者对Activity的生命周期事件进行集中处理。在该方法出现前,我们往往需要将所有Activity都继承自统一的BaseActivity,再进行onStart/onStop等的监听计数等来实现同样的目的。
public interface ActivityLifecycleCallbacks {
void onActivityCreated(Activity activity, Bundle savedInstanceState);
void onActivityStarted(Activity activity);
void onActivityResumed(Activity activity);
void onActivityPaused(Activity activity);
void onActivityStopped(Activity activity);
void onActivitySaveInstanceState(Activity activity, Bundle outState);
void onActivityDestroyed(Activity activity);
}
ActivityLifecycleCallbacks使用要求API 14+ (Android 4.0+)。初始化的时候需要注册 application.registerActivityLifecycleCallbacks(this);
可以分别在onActivityStarted和onActivityStoped两个方法中进行++、--的计数,来判断当前应用在前台还是后台。
为什么要在onStop中检测,而不是onPause?这是由于A启动B时,生命周期的执行顺序如下:A.onPause->B.onCreate->B.onStart->B.onResume->A.onStop,也就是说,在A的onPause方法中,B的生命周期还没有执行,进程没有进入前台,当然是检测不到的。
其他方案可参考 http://www.jianshu.com/p/e7f64e6bc2cc
RunningTaskInfo
ActivityManager.getRunningTasks方法返回当前运行的task列表,使用该接口需要 android.permission.GET_TASKS权限。最近使用的task排在第一位,按使用顺序依次排序。该方法的本意是调试和展示ui的任务蛮力,不应该用于应用的核心逻辑,例如根据获取的信息来展现不同的行为。谷歌官方处于安全的考虑,该方法在5.0(Build.VERSION_CODES_LOLLIPOP)及以后deprecated,第三方应用不能再访问。注释如下
* @deprecated As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method
* is no longer available to third party
* applications: the introduction of document-centric recents means
* it can leak person information to the caller. For backwards compatibility,
* it will still retu rn a small subset of its data: at least the caller's
* own tasks, and possibly some other tasks
* such as home that are known to not be sensitive.
在小米手机MIUI8系统运行,可看出该函数只能返回一个home的task。
在5.0以下获取当前top应用的代码如下:
/**
*判断当前应用程序处于前台还是后台
*/
public static boolean isApplicationBroughtToBackground(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
getRunningAppProcesses
5.0之后可以通过ActivityManager的getRunningAppProcesses()方法获取正在运行的应用程序。
public static boolean isBackground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List appProcesses = activityManager.getRunningAppProcesses();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.processName.equals(context.getPackageName())) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
Log.i("后台", appProcess.processName);
return true;
}else{
Log.i("前台", appProcess.processName);
return false;
}
}
}
return false;
}
实际测试中,该方法对大部分的场景可行,但是部分场景不可行。如通知栏点击进入其他应用,需要进行兼容性测试。
参考:
http://blog.csdn.net/zhuangyalei/article/details/50554862
http://blog.csdn.net/goodlixueyong/article/details/50543627