作者: 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操作会引起耗时
方法七

使用 ProcessLifecycleOwner 监听应用程序的生命周期

使用Jetpack组件

方法一:通过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打上勾

方法五:通过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中打印的信息

原理

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

方法七:使用 ProcessLifecycleOwner 监听应用程序的生命周期

具有生命周期的组件除了 Activity、Fragment 和 Service 外,还有 Application。ProcessLifecycleOwner 就是用来监听整个应用程序的生命周期情况。

具体使用方法:

第一步:添加依赖项:

implementation "androidx.lifecycle:lifecycle-process:2.2.0"

第二步:定义一个 ApplicationObserver,实现 LifecycleObserver 接口。

public class ApplicationObserver implements LifecycleObserver {private String TAG = this.getClass().getName();/*** 在应用程序的整个生命周期中只会被调用一次*/@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)public void onCreate() {Log.d(TAG,"Lifecycle.Event.ON_CREATE");}@OnLifecycleEvent(Lifecycle.Event.ON_START)public void onStart() {Log.d(TAG,"Lifecycle.Event.ON_START");}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)public void onResume() {Log.d(TAG,"Lifecycle.Event.ON_RESUME");}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)public void onPause() {Log.d(TAG,"Lifecycle.Event.ON_PAUSE");}@OnLifecycleEvent(Lifecycle.Event.ON_STOP)public void onStop() {Log.d(TAG,"Lifecycle.Event.ON_STOP");}/*** 永远不会被调用,系统不会分发调用 ON_DESTROY 事件*/@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)public void onDestroy() {Log.d(TAG,"Lifecycle.Event.ON_DESTROY");}
}

第三步:在 Application 中关联 ApplicationObserver。

public class App extends Application {@Overridepublic void onCreate() {super.onCreate();ProcessLifecycleOwner.get().getLifecycle().addObserver(new ApplicationObserver());}
}

注意事项:

  1. ProcessLifecycleOwner 是针对整个应用程序的监听,与 Activity 的数量无关。
  2. Lifecycle.Event.ON_CREATE 只会被调用一次,而 Lifecycle.Event.ON_DESTROY 永远不会被调用。
  3. Lifecycle.Event.ON_PAUSE 和 Lifecycle.Event.ON_STOP 的调用会有一定的延后,因为系统需要为“屏幕旋转,由于配置发生变化而导致的 Activity 重新创建” 的情况预留一些时间。

判断App位于前台或者后台的6种方法相关推荐

  1. 如何判断app在前台还是后台

    项目遇到一个轮训,有通知就toast.但是toast是可以不受actvity控制的,当我按home键让app常驻后台后,我要他不吐司,这时候我们需要判断app在前台还是后台. 发挥谷歌搜索的威力 Ch ...

  2. php前台调用后台方法,JavaScript_JavaScript调用后台的三种方法实例,方法一:直接使用%=%调 - phpStudy...

    JavaScript调用后台的三种方法实例 方法一:直接使用调用 前台JS: var methodStr = ""; alert(methodStr); 后头方法: public ...

  3. oppo手机android系统进程,OPPO手机应用软件怎么在后台运行?OPPO软件后台运行两种方法...

    明明按了Home键让APP在后台运行,结果再进来时,却回不了原先的界面,相当于重新启动了APP!相信不少小伙伴都遇到过这种情况,对于杀怪杀到一半的孩纸,更是痛彻心扉-- 要解决问题很简单,这里有两种方 ...

  4. python脚本判断一个数是否为素数的几种方法

    质数又称素数.指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数.素数在数论中有着很重要的地位.比1大但不是素数的数称为合数.1和0既非素数也非合数.质数是与合数相对立的两个概念 ...

  5. python判断字符串出现的次数_【如何判断python字符串出现次数?这几种方法你一定要学会】- 环球网校...

    [摘要]python应用阶段是实际的工作经验,现在如何判断python字符串出现次数?这几种方法你一定要学会,小编建议大家可以试着理解这些内容,也许对您的python学习有帮助,毕竟实践出真知,所以你 ...

  6. python中判断一个数是否为素数_【转载】Python脚本判断一个数是否为素数的几种方法...

    质数又称素数.指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数.素数在数论中有着很重要的地位.比1大但不是素数的数称为合数.1和0既非素数也非合数.质数是与合数相对立的两个概念 ...

  7. php判断数组的值是否为空,PHP判断数组是否为空的常用方法(五种方法)

    本文介绍了PHP开发中遇到的数组问题,小编在这里给大家总结了5中方法关于php判断数组是否为空问题,需要的朋友参考下 本文介绍了PHP开发中遇到的数组问题,这里介绍了判断PHP数组为空的5种方法,有需 ...

  8. Linux下判断磁盘是SSD还是HDD的几种方法

    文章目录 1.使用Linux相关命令 2.linux查看磁盘所在槽位 1.使用Linux相关命令 方法1: 如果是直通盘,即JBOD模式,方法则正确 如果返回1则表示磁盘可旋转,那么就是HDD了:反之 ...

  9. js中判断文本框是否为空的两种方法

    js中判断文本框是否为空的两种方法 //用户名非空验证 function checkUserName(){ var name = document.myform.txtUser; //在这里我认为: ...

  10. jQuery判断复选框是否选中的三种方法

    jQuery判断复选框是否选中的三种方法. PS:下面的代码为通过循环找到在多个复选框中被选中的复选框,并对其删除 //判断复选框是否选中的第一种方法: $.each(buttons,function ...

最新文章

  1. 北漂经历 | 我在北京这几年
  2. PXE实现Linux的自动安装
  3. MySQL分库分表环境下全局ID生成方案
  4. Zenoss学习杂记(十)
  5. 微服务API模拟框架frock介绍
  6. 《Effective C#》Item 21:用委托实现回调
  7. GUID和INT两种数据类型做主键的比较
  8. python抢红包random实现_python写红包的原理流程包含random,lambda其中的使用和见简单介绍...
  9. 8s 配置session保持_分布式session共享解决方案
  10. 3dm下载的都是linux游戏,3DM的游戏怎么下载和安装(没智商的小白用户)
  11. python与数据挖掘 上机实验_python数据挖掘实验报告1
  12. map取固定key_Map获取key值
  13. 用c语言编写文曲星小游戏,这是文曲星里的小游戏,本人用c语言将其编出并添加破纪录功能。...
  14. 联想H61主板升级BIOS,支持nvme硬盘
  15. 数据结构循环队列C++实现
  16. 1920x1080平板 android,高清是王道!1080P分辨率屏幕平板大搜罗
  17. ABP——切换MySQL数据库
  18. linux将php停了,Linux停PHP环境的搭建
  19. 更换电脑机械硬盘之后,无需重新安装程序技巧(系统盘为固态),解决D盘程序快捷方式图标白色方块
  20. html3d粒子球,Canvas粒子系统:3D球体

热门文章

  1. 返利网拼团小程序,10人拼团7人返利
  2. 2017公共DNS服务器评估报告——公共DNS推荐(摘录)
  3. 【清华大学】深入理解操作系统(陈渝) 第二章
  4. 你觉得最好用的地图导航软件是哪一个?这3款App供你选择
  5. linux系统下安装wrk和使用
  6. 强大的 Fresco(加载网络和本地图片)简单使用
  7. 电脑桌面有计算机和回收站怎么办,电脑回收站不见了怎么办 电脑回收站找回的4种方法...
  8. UE4编辑器界面语言切换
  9. 【QT】找茬外挂制作
  10. 南京:全面启用商品房买卖电子合同