需求
最近接到一个新的需求:用户把app切换到后台,再次切回到app界面的时候会被要求重新输入登陆密码,这一需求的设计主要是出于安全性考虑。
这里就需要监听app的状态,从而判断app当前处于前台还是后台,再对其做不同的逻辑处理即可。
方案一:利用ActivityLifecycleCallbacks监听所有activity的生命周期
解释下registerActivityLifecycleCallbacks这个方法,只要app中有一个activity的生命周期改变了就会调用registerActivityLifecycleCallbacks的相应方法.
比如说splashActivity走了onCreate方法,registerActivityLifecycleCallbacks的onActivityCreated也会被调用,括号中的参数activity就是splashActivity本身
1.在application中注册监听方法,一般写在onCreate方法中
private int countActivity = 0;
//是否进入后台
private boolean isBackground = false;
@Override
public void onCreate() {
super.onCreate();
//监听应用进入后台回到前台
initBackgroundCallBack();
}
2.实现监听方法:具体实现onActivityStarted,onActivityStopped方法
private void initBackgroundCallBack() {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
@Override
public void onActivityStarted(Activity activity) {
countActivity++;
if (countActivity == 1 && isBackground) {
Log.e("MyApplication", "onActivityStarted: 应用进入前台");
isBackground = false;
//说明应用重新进入了前台
Toast.makeText(MyApplication.this, "应用进入前台", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
countActivity--;
if (countActivity <= 0 && !isBackground) {
Log.e("MyApplication", "onActivityStarted: 应用进入后台");
isBackground = true;
//说明应用进入了后台
Toast.makeText(MyApplication.this, "应用进入后台", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
countActivity 是为了判断应用是否进入后台,当一个activity的调用onStart方法时countActivity就会+1,调用onStop方法时countActivity就会-1
当所有activity的countActivity都=0时,说明所有的activity都在后台,即整个应用都处于后台
isBackground 是为了判断应用是否在后台,如果应用在后台又被调用了onActivityStarted方法,说明应用从后台回到前台
方案二:利用ActivityManager的RunningAppProcessInfo类
ActivityManager在整个系统里面起着非常重要的作用,主要为系统中运行着的activity交互提供接口,其中RunningAppProcessInfo类则封装了正在运行着的进程信息,当然也包含了正在运行的app的包名,因此我们可以activitymanager.getRunningAppProcesses()获取当前运行的app列表,对比自身的包名,来判断本身app是否处于前台运行。
/**
* 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掉了
参考文献