Android中如何判断本app是否在前台运行
2016-05-08 12:43
429 查看
缘由:
在做App升级时,遇到的需求。在发现升级信息后,如果当前App在前台运行,则弹窗提示有升级信息; 如果App此正在后台运行,则在通知栏发送通知。那么问题的关键点在于:如何判断本App正在前台运行?
解决方法:
1、调用系统API
这是很多应用锁所采用的方法。获取当前正在前台运行的App包名,判断是否是自己。不过这个方法存在缺陷,依赖于系统对API的开放程度,必须增加权限。而且此功能过于强大,没有必要使用。代码参考如下:
private 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(getPackageName()))
{
return true ;
}
return false ;
}
此外,并不是所有的系统都可用此代码,例如:
Android L开始,Google开始对getRunningTasks接口进行限制使用。
默认情况下,普通的三方应用(非系统应用)不能使用该接口。这种方式以及废弃。应用要使用该接口必须声明权限 android.permission.REAL_GET_TASKS。而这个权限是不对三方应用开放的。(在Manifest里申请了也没有作用)系统应用(有系统签名)可以调用该权限。Google这样做的原因还是出于安全考虑,对普通应用开发该接口可能会造成用户的隐私泄露。
2、在BaseActivity中监控Activity的生命周期
另一种就是自己监控自己所有Activity的运行状态。整个系统维护一个运行在前台的Activity计数,当任意activity进入onResue()时,增加计数;当退出前台时进入onPause()时,减少计数。为达到此目的,需要为所有应用中的Activiy增加一个基类BaseActivity,BaseActivity再继承自系统中的Activity。BaseActivity中添加如下代码。这也说明了自定义一个Activity的便利性。
为什么是onPause()而不是onStop()?
通过观察Activity的生命周期状态图,可以看到,App可能会在onPause()或onStop()调用后被杀死,而onPause()先于onStop()运行,所以,为了保证计数的准确,必须在onPause()处理Activity的计数递减;否则就可能出现Activity在onPause()调用后,立即被杀死,而Activity计数没有递减的状态。
判断当前App是否在前台运行的方法?
只要检查计数是否>0。
public static boolean isAppRunningFront() {
return activityVisiableCount > 0;
}
public static void setIsAppRunningFront(boolean isAppRunningFront) {
if (isAppRunningFront) {
activityVisiableCount++;
} else if (activityVisiableCount > 0){
activityVisiableCount--;
}
}
如何判断在前台的是哪个Activty?
首先判断前当前App是否在前台运行,然后获取topActivity即可。
3、在Application中注册Activity状态切换的监控回调
此方式同第2种方式原理是一样的,只不过使用Application注册相应接口。
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
回调的接口如下:
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);
}
同样的,在onActivityResumed和onActivityPaused中增加同第2种方式相同的代码即可。
总结
这个问题回答了回为什么有必要了解Activity的生命周期,否则难以想到第2、3种方式的原理,以及注意Activity回收时机而将计数递减代码放在onPause而不是onStop的原因。
在做App升级时,遇到的需求。在发现升级信息后,如果当前App在前台运行,则弹窗提示有升级信息; 如果App此正在后台运行,则在通知栏发送通知。那么问题的关键点在于:如何判断本App正在前台运行?
解决方法:
1、调用系统API
这是很多应用锁所采用的方法。获取当前正在前台运行的App包名,判断是否是自己。不过这个方法存在缺陷,依赖于系统对API的开放程度,必须增加权限。而且此功能过于强大,没有必要使用。代码参考如下:
private 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(getPackageName()))
{
return true ;
}
return false ;
}
此外,并不是所有的系统都可用此代码,例如:
Android L开始,Google开始对getRunningTasks接口进行限制使用。
默认情况下,普通的三方应用(非系统应用)不能使用该接口。这种方式以及废弃。应用要使用该接口必须声明权限 android.permission.REAL_GET_TASKS。而这个权限是不对三方应用开放的。(在Manifest里申请了也没有作用)系统应用(有系统签名)可以调用该权限。Google这样做的原因还是出于安全考虑,对普通应用开发该接口可能会造成用户的隐私泄露。
2、在BaseActivity中监控Activity的生命周期
另一种就是自己监控自己所有Activity的运行状态。整个系统维护一个运行在前台的Activity计数,当任意activity进入onResue()时,增加计数;当退出前台时进入onPause()时,减少计数。为达到此目的,需要为所有应用中的Activiy增加一个基类BaseActivity,BaseActivity再继承自系统中的Activity。BaseActivity中添加如下代码。这也说明了自定义一个Activity的便利性。
@Override protected void onResume() { super.onResume(); topActivity = this; BuluApplication.setIsAppRunningFront(true); MobclickAgent.onResume(this); } @Override protected void onPause() { super.onPause(); BuluApplication.setIsAppRunningFront(false); MobclickAgent.onPause(this); }
为什么是onPause()而不是onStop()?
通过观察Activity的生命周期状态图,可以看到,App可能会在onPause()或onStop()调用后被杀死,而onPause()先于onStop()运行,所以,为了保证计数的准确,必须在onPause()处理Activity的计数递减;否则就可能出现Activity在onPause()调用后,立即被杀死,而Activity计数没有递减的状态。
判断当前App是否在前台运行的方法?
只要检查计数是否>0。
public static boolean isAppRunningFront() {
return activityVisiableCount > 0;
}
public static void setIsAppRunningFront(boolean isAppRunningFront) {
if (isAppRunningFront) {
activityVisiableCount++;
} else if (activityVisiableCount > 0){
activityVisiableCount--;
}
}
如何判断在前台的是哪个Activty?
首先判断前当前App是否在前台运行,然后获取topActivity即可。
3、在Application中注册Activity状态切换的监控回调
此方式同第2种方式原理是一样的,只不过使用Application注册相应接口。
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
回调的接口如下:
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);
}
同样的,在onActivityResumed和onActivityPaused中增加同第2种方式相同的代码即可。
总结
这个问题回答了回为什么有必要了解Activity的生命周期,否则难以想到第2、3种方式的原理,以及注意Activity回收时机而将计数递减代码放在onPause而不是onStop的原因。
相关文章推荐
- 解决Gradle DSL method not found: ‘android()’
- 对照Java学习Swift--自动引用计数(Automatic Reference Counting)
- Lucene highlighter高亮显示
- android studio 学习笔记之 生成签名APK
- ApplicationId 与 PackageName
- android contentprovider
- Android开发艺术探索首观
- Android Studio导入ZXING
- Android ViewPager之实现轮播广告效果
- android packagemanager
- cocos环境配置和打包apk
- android 系统给应用的jar
- Android工作总结
- android studio 学习笔记之 注释规范化
- Android利用Fragment实现新闻客户端界面切换(addBackStack,popBackStack)
- iOS开发中常用的几个插件
- Android Studio解决导入开源项目出现的相关问题
- Object-c------NSDate的简单介绍
- virtualenvwrapper 的安装和使用
- ios基础知识--03