使用activityManager.getRunningAppProcesses()获取真实的前台进程

19

我试图确定用户当前正在使用的应用程序。为此,我使用activityManager.getRunningAppProcesses()方法。

我知道该方法自Android 5.1.1以来不再支持 - 这没关系。

起初它像魔法一样工作,我正在迭代运行中的应用程序进程信息列表并检查其重要性。

简而言之,有什么正确的方法可以获取当前前台进程并防止误报?列表的排序方式是如何完成的- API表示未指定。有没有一种方法可以正确地排序它们?

我所做的:

很遗憾,ActivityManager返回的列表在每个设备上都不同。一些设备即使进程当前不可见也会返回多个重要性为100(即FOREGROUND)的信息。

这导致了我有很多误报的问题。例如,我用Facebook测试它,并创建了一个toast,每次Facebook在前台运行时就会出现。我切换到主屏幕,因此我的启动器应该是前台进程。它是在十秒钟内,之后,Facebook又以FOREGROUND的重要性再次出现在列表中(它既没有打开也不可见),我得到了一个误报。

我发现一些设备按照最近的进程排列列表。因此,我决定尝试以下方法:

ActivityManager.RunningAppProcessInfo appProcess = appProcesses.get(0);
        final String processName = appProcess.processName;
        final String packageName = removeProcessSuffix(processName);
        if (appProcess.importance == FOREGROUND || appProcess.importance == VISIBLE){
            //do something, like the toast
        }

使用appProcesses.get(0);,我只检查第一个元素,这个错误就消失了。不再有误报。

但是,现在在一些设备上,我根本就无法获取前台进程。因为它们没有以任何方式排序列表。 例如,一些4.2的索尼智能手机是其中的一些候选对象。我可以获取列表,但目前真正可见的进程位于索引11左右。

我不知道该怎么做,才能获取当前的前台进程,而不会出现误报。

获取当前前台进程并防止误报的正确方法是什么?列表的顺序是如何确定的——API表示未指定顺序。是否有一种方法可以正确排序它们?

谢谢!


这看起来像是 https://dev59.com/LnI95IYBdhLWcg3www2Y 的重复。 - alzee
我没有测试过,但这看起来会对你有所帮助:https://dev59.com/CF4d5IYBdhLWcg3wLf_P#33886313 - Álisson Morais
@ÁlissonMorais 首先感谢您的回复,但是您是否完整阅读了问题?我不能仅使用返回列表的第一项,因为在大约30%的设备上,该列表未排序。 - JacksOnF1re
@user3137702 谢谢,但这并不是重复的问题,我不想使用usageStats管理器,因为在三星设备上它无法工作,他们决定不支持它,并且getTasks方法已经被弃用自API 21以来需要获取任务权限。 - JacksOnF1re
@JacksOnF1re 你的应用程序将支持哪个较低的API?您可以检查API级别并使用ActivityManager和UsageStatsManager两种方法。在哪种情况下会遇到问题?高于还是低于API 21? - Álisson Morais
显示剩余2条评论
1个回答

3

什么是获取当前前台进程并防止误报的正确方法?

UsageStatsManager 是唯一的官方API,用于获取当前正在运行的应用程序(请参见#50)。

使用 getRunningTasks(int maxNum)getRunningAppProcesses()AccessibilityService 获取前台应用程序从未可靠。前两种方法的文档具有以下警告:注意:此方法仅用于调试


以下是使用UsageStatsManager获取顶部应用程序的示例:
Calendar endCal = Calendar.getInstance();
Calendar beginCal = Calendar.getInstance();
beginCal.add(Calendar.MINUTE, -30);
UsageStatsManager manager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
List<UsageStats> stats =  manager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,  
    beginCal.getTimeInMillis(), endCal.getTimeInMillis());
Collections.sort(stats, new Comparator<UsageStats>() {

  @Override public int compare(UsageStats lhs, UsageStats rhs) {
    long time1 = lhs.getLastTimeUsed();
    long time2 = rhs.getLastTimeUsed();
    if (time1 > time2) {
      return -1;
    } else if (time1 < time2) {
      return 1;
    }
    return 0;
  }
});
// The first "UsageStats" in the list will be the top application.
// If the list is empty you will need to ask for permissions to use UsageStatsManager
// To request permission:
// startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));

我知道这不是你所希望的答案。像CM SecurityAppLock这样的应用程序使用Android 5.1.1+上的UsageStatsManager。由于SeLinux,无法使用getRunningTasks(int maxNum)getRunningAppProcesses()获取前台应用程序。

谢谢你的回答!不幸的是,StatsManager 对大多数三星设备都不起作用,而且不支持 API 21 以下的版本(正如你所说的)。 :/ - JacksOnF1re

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接