判断App位于前台或者后台的6种方法

作者: wenmingvs
Github: https://github.com/wenmingvs/AndroidProcess

用法

传入Context参数与想要判断是否位于前台的App的包名,会返回ture或者false表示App是否位于前台


//六种方法任选其一

//使用方法一
Boolean isForeground = BackgroundUtil.getRunningTask(context, packageName);
//使用方法二
Boolean isForeground = BackgroundUtil.getRunningAppProcesses(context, packageName);
//使用方法三
Boolean isForeground = BackgroundUtil.getApplicationValue(context);
//使用方法四
Boolean isForeground = BackgroundUtil.queryUsageStats(context, packageName);
//使用方法五
Boolean isForeground = BackgroundUtil.getFromAccessibilityService(context, packageName);
//使用方法六
Boolean isForeground = BackgroundUtil.getLinuxCoreInfo(context, packageName);

六种方法的区别

方法 判断原理 需要权限 可以判断其他应用位于前台 特点
方法一 RunningTask Android4.0系列可以,5.0以上机器不行 5.0此方法被废弃
方法二 RunningProcess 当App存在后台常驻的Service时失效
方法三 ActivityLifecycleCallbacks 简单有效,代码最少
方法四 UsageStatsManager 需要用户手动授权
方法五 通过Android无障碍功能实现 需要用户手动授权
方法六 读取/proc目录下的信息 当proc目录下文件夹过多时,过多的IO操作会引起耗时

方法一:通过RunningTask

原理

当一个App处于前台的时候,会处于RunningTask的这个栈的栈顶,所以我们可以取出RunningTask的栈顶的任务进程,看他与我们的想要判断的App的包名是否相同,来达到效果

缺点

getRunningTask方法在Android5.0以上已经被废弃,只会返回自己和系统的一些不敏感的task,不再返回其他应用的task,用此方法来判断自身App是否处于后台,仍然是有效的,但是无法判断其他应用是否位于前台,因为不再能获取信息

方法二:通过RunningProcess

原理

通过runningProcess获取到一个当前正在运行的进程的List,我们遍历这个List中的每一个进程,判断这个进程的一个importance 属性是否是前台进程,并且包名是否与我们判断的APP的包名一样,如果这两个条件都符合,那么这个App就处于前台

缺点

在聊天类型的App中,常常需要常驻后台来不间断的获取服务器的消息,这就需要我们把Service设置成START_STICKY,kill 后会被重启(等待5秒左右)来保证Service常驻后台。如果Service设置了这个属性,这个App的进程就会被判断是前台,代码上的表现就是appProcess.importance的值永远是 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,这样就永远无法判断出到底哪个是前台了。

方法三:通过ActivityLifecycleCallbacks

原理
AndroidSDK14在Application类里增加了ActivityLifecycleCallbacks,我们可以通过这个Callback拿到App所有Activity的生命周期回调。

 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);
    }

知道这些信息,我们就可以用更官方的办法来解决问题,当然还是利用方案二里的Activity生命周期的特性,我们只需要在Application的onCreate()里去注册上述接口,然后由Activity回调回来运行状态即可。

可能还有人在纠结,我用back键切到后台和用Home键切到后台,一样吗?以上方法适用吗?在Android应用开发中一般认为back键是可以捕获的,而Home键是不能捕获的(除非修改framework),但是上述方法从Activity生命周期着手解决问题,虽然这两种方式的Activity生命周期并不相同,但是二者都会执行onStop();所以并不关心到底是触发了哪个键切入后台的。另外,Application是否被销毁,都不会影响判断的正确性

方法四:通过使用UsageStatsManager获取

原理

通过使用UsageStatsManager获取,此方法是Android5.0之后提供的新API,可以获取一个时间段内的应用统计信息,但是必须满足一下要求

使用前提
1.此方法只在android5.0以上有效
2.AndroidManifest中加入此权限

<uses-permission xmlns:tools="http://schemas.android.com/tools"    
 android:name="android.permission.PACKAGE_USAGE_STATS"   
  tools:ignore="ProtectedPermissions" />

3.打开手机设置,点击安全-高级,在有权查看使用情况的应用中,为这个App打上勾

enter image description here
enter image description here

方法五:通过Android自带的无障碍功能

非常感谢@EffectiveMatrix大神带来的新的判断前后台的方法

此方法属于他原创,具体的博文参照这里http://effmx.com/articles/tong-guo-android-fu-zhu-gong-neng-accessibility-service-jian-ce-ren-yi-qian-tai-jie-mian/

此方法无法直观的通过下拉通知视图来进行前后台的观察,请到LogCat中进行观察即可,以下是LogCat中打印的信息

enter image description here

原理

Android 辅助功能(AccessibilityService) 为我们提供了一系列的事件回调,帮助我们指示一些用户界面的状态变化。 我们可以派生辅助功能类,进而对不同的 AccessibilityEvent 进行处理。 同样的,这个服务就可以用来判断当前的前台应用

优势

  1. AccessibilityService 有非常广泛的 ROM 覆盖,特别是非国产手机,从 Android API Level 8(Android 2.2) 到 Android Api Level 23(Android 6.0)
  1. AccessibilityService 不再需要轮询的判断当前的应用是不是在前台,系统会在窗口状态发生变化的时候主动回调,耗时和资源消耗都极小
  2. 不需要权限请求
  3. 它是一个稳定的方法,与 “方法6”读取 /proc 目录不同,它并非利用 Android 一些设计上的漏洞,可以长期使用的可能很大
  4. 可以用来判断任意应用甚至 Activity, PopupWindow, Dialog 对象是否处于前台

劣势

  1. 需要要用户开启辅助功能
  1. 辅助功能会伴随应用被“强行停止”而剥夺

方法六:读取Linux系统内核保存在/proc目录下的process进程信息

此方法并非我原创,原作者是国外的大神,GitHub项目在这里,也一并加入到工程中,供大家做全面的参考选择

原理

无意中看到乌云上有人提的一个漏洞,Linux系统内核会把process进程信息保存在/proc目录下,Shell命令去获取的他,再根据进程的属性判断是否为前台

优点

  1. 不需要任何权限
  1. 可以判断任意一个应用是否在前台,而不局限在自身应用

缺点

  1. 当/proc下文件夹过多时,此方法是耗时操作

用法
获取一系列正在运行的App的进程

List<AndroidAppProcess> processes = ProcessManager.getRunningAppProcesses();

获取任一正在运行的App进程的详细信息

AndroidAppProcess process = processes.get(location);
String processName = process.name;

Stat stat = process.stat();
int pid = stat.getPid();
int parentProcessId = stat.ppid();
long startTime = stat.stime();
int policy = stat.policy();
char state = stat.state();

Statm statm = process.statm();
long totalSizeOfProcess = statm.getSize();
long residentSetSize = statm.getResidentSetSize();

PackageInfo packageInfo = process.getPackageInfo(context, 0);
String appName = packageInfo.applicationInfo.loadLabel(pm).toString();

判断是否在前台

if (ProcessManager.isMyProcessInTheForeground()) {
  // do stuff
}

获取一系列正在运行的App进程的详细信息

List<ActivityManager.RunningAppProcessInfo> processes = ProcessManager.getRunningAppProcessInfo(ctx);

更多文章请关注公众号

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容