在我们开发的过程中,经常会遇到需要我们判断app进入后台,或者切换到前台的情况。比如我们想判断app切换到前台时,显示一个解锁界面,要求用户输入解锁密码才能继续进行操作;我们想判断app切换到后台,记录一下log;或者当用户切换回前台时,我们想刷新一下页面的数据等等......

android里面监听app前后台的方案很多(这还是得归根于安卓提供了丰富的api和强大的架构支撑,呵呵~),比如可以通过ActivityManager提供的getRunningAppProcesses()获取系统当前运行的app,从而判断app是否处于前台。或者通过监听点击Home键,判断app是否回到了后台。下面将针对笔者已知的几种方案,进行对比分析。

方案一:利用ActivityManager的RunningAppProcessInfo类
ActivityManager在整个系统里面起着非常重要的作用,主要为系统中运行着的activity交互提供接口,其中RunningAppProcessInfo类则封装了正在运行着的进程信息,当然也包含了正在运行的app的包名,因此我们可以activitymanager.getRunningAppProcesses()获取当前运行的app列表,对比自身的包名,来判断本身app是否处于前台运行。

这打断一下,ActivityManager框架是Android系统十分重要的一部分,在以后有时间,笔者会好好学习整理ActivityManager框架的分析。

回到这里,下面给出部分关键代码。

 /**
* 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掉了....(心中万马奔腾...)

方案二:监听Home键点击

说起home键的监听,也算是android里面的一个梗。这看上去简单的功能,实际上实现起来却十分的曲折,这跟android系统的设计有很大的关系。当home键被点击的时候,会发出一个系统广播,在系统收到这个广播以后,会在framework层做一系列操作将当前的app退到后台,然后把事件消费掉不传给应用层,所以这时候 onKeyDown事件也接收不到了..用官方的解释就是——“Home key. This key is handled by the framework and is never delivered to applications.”。实际上这也是为了安全性的考虑,不然每家的app都监听home键,然后禁掉响应,不都成了流氓软件了。

官方不支持,可是这难不到我们万能的攻城狮们的,毕竟有很多想我们正规的开发者,还是需要监听home键来做一些如写日志之类的操作的。网上谷歌百度会有很多类似的解决方案,在这里就不展开了。(不过这里可以推荐一下)

小结:我们能监听到home键点击,当然就知道app处于前台还是后台了。但毕竟这个方案是基于官方不支持的前提下的,而且home键的监听在很多设备都会有兼容性的问题,因此我们不大推荐这样做。

方案三:利用ActivityLifecycleCallbacks监听所有activity的生命周期

通过监听所有activity的onStart、onStop调用,然后统计当前是不是所有的activity都调用了onStop,确实可以判断app处于了后台,不过让我们重写每一个activity的onStop,并加这段奇怪的代码,实在不大优雅,即使在activity基类里面统一写,那天如果忘了或者不需要继承基类的activity,就不大好了。

因此,这里推荐一个新的接口ActivityLifecycleCallbacks,说新也不新,其实早在API 14 (android 4.0)就已经推出了。ActivityLifecycleCallbacks接口在Application类里面,因此需要我们自己继承Application,自定义一个MyApplication,然后注册接口。ActivityLifecycleCallbacks为application提供了对所有activity生命周期的监听,因此我们通过重写ActivityLifecycleCallbacks的onActivityStarted和onActivityStopped方法,定义一个变量,来统计当前有几个activity处于前台。

  /**
* 当前Acitity个数
*/
private int activityAount = ; @Override
public void onCreate() {
......
registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
......
} /**
* Activity 生命周期监听,用于监控app前后台状态切换
*/
ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
} @Override
public void onActivityStarted(Activity activity) {
// if (activityAount == 0) {
// //app回到前台
// isForeground = true;
// }
activityAount++;
} @Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
} @Override
public void onActivityStopped(Activity activity) {
activityAount--;
if (activityAount == ) {
isForeground = false;
}
} @Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
};

以上代码写在MyApplication里面。怎么样,是不是很简单快捷!而且准确无误。

总结:
1、利用ActivityManager的RunningAppProcessInfo类,直接粗暴,官方摒弃,不推荐;
2、监听Home键点击,官方不支持,兼容性差,不稳定,不推荐;
3、利用ActivityLifecycleCallbacks监听所有activity的生命周期,官方指定饮品,哦,不对,官方指定接口,大力推荐!我们举一反三,利用ActivityLifecycleCallbacks监听,我们还能控制我们的activity堆栈,甚至还可以在里面做日志统计...想想还是很强大的。

PS:虽则利用ActivityLifecycleCallbacks接口监听的方案最优,但这毕竟是4.0以后的产品,因此对于4.0以下的,可以考虑增加方案一判断。

Android 监听APP进入后台或切换到前台方案对比的更多相关文章

  1. android 监听app进入后台以及从后台进入前台

    package com.pinshang.base; import com.pinshang.common.CommonValue; import com.pinshang.investapp.Ent ...

  2. ios 监听app从后台恢复到前台

    正常情况下,在AppDelegate中实现下面两个方法,能够监听从后台恢复到前台 [cpp] - (void)applicationDidEnterBackground:(UIApplication ...

  3. Cocos Creater 监听程序到后台和重新到前台

    cocos creator前后台切换当玩家在玩游戏时,突然接了一个电话,此时游戏会被切到后台待机,所有的声音播放都会停止,等打完电话,回到游戏,游戏又会被切回前台来,需要手动播放声音.可使用如下代码 ...

  4. Android监听来电和去电

    要监听android打电话和接电话,只需下面2步骤1.第一步,写一个Receiver继承自BroadcastReceiver import android.app.Service; import an ...

  5. Android监听ScrollView滑动到顶端和底部

    Android监听ScrollView滑动到顶端和底部     package cn.testscrollview; import android.os.Bundle; import android. ...

  6. Android 监听 WiFi 开关状态

    Android 监听 WiFi 开关状态 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/70854309 本文出自[赵彦军的博客] ...

  7. Android监听系统短信数据库变化-提取短信内容

    由于监听系统短信广播受到权限的限制,所以很多手机可能使用这种方式没法监听广播,从而没办法获取到系统短信,所以又重新开辟一条路. Android监听系统短信数据库内容变化使用场景: 1.监听短信数据库的 ...

  8. Android监听返回键、Home键+再按一次返回键退出应用

    Android监听返回键需重写onKeyDown()方法 Home键keyCode==KeyEvent.KEYCODE_HOME @Override public boolean onKeyDown( ...

  9. Android监听应用程序安装和卸载

    Android监听应用程序安装和卸载 第一. 新建监听类:BootReceiver继承BroadcastReceiver package com.rongfzh.yc; import android. ...

随机推荐

  1. linux文件系统总结

    apue中:其中进程表项内部的数组又称为 进程打开文件表    另外一个角度: 从linux内核角度开: task_struct是进程描述符对应上面的进程表项,在task_struct描述符中有str ...

  2. Gym - 101845D 计算几何

    Ignacio is a famous mathematician, some time ago he was married with Dolly, a famous scientific, at ...

  3. shell控制流程

    #!/bin/bash #存储为a.sh == ] then #参数正确,返回0 else #参数错误,返回1 fi #!/bin/bash #存储为b.sh echo $? $ . ./a.sh $ ...

  4. POJ1051 P,MTHBGWB

    题目来源:http://poj.org/problem?id=1051 题目大意: Morse密码里每个字母用长度不定的点和线来表示,一条信息中字母的编码之间用空隙隔开.下表为Morse密码的编码表: ...

  5. CF D. Fair(思维+DFS)

    http://codeforces.com/contest/987/problem/D 题目大概: 给出一个n个城镇m条边的图,给出每个城镇拥有的特产(可能多个城镇有相同特产).有k种不同特产. 要求 ...

  6. 阿里Java开发规约(2)

    本文是对阿里插件中规约的详细解释二,关于插件使用,请参考这里 及时清理不再使用的代码段或配置信息. 说明:对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余 Positive examp ...

  7. Mysql 查看表数据以及索引大小

    如果想查看 Mysql 数据库的总的数据量或者某个表的数据或者索引大小,可以使用系统库 information_schema 来查询,这个系统库中有一个 TABLES 表,这个表是用来记录数据库中表的 ...

  8. oracle db 产品路线图

    Release Schedule of Current Database Releases (文档 ID 742060.1)

  9. ES6使用常量做为函数名

    重点是 要给常量加一个中括号 就是这么任性~ [SET_INFO](state) { state.userInfo = { name: cookie.getCookie('name'), token: ...

  10. 多线程编程_读写锁ReadWriteLock

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...