19

I am trying to determine the currently visible application for the user. To do so, I use the activityManager.getRunningAppProcesses() method.

I know that the method is not supported as off Android 5.1.1 - this is ok.

In the beginning it worked like charm, I am iterating through the list of RunningAppProcessInfos and check for the importance.

tl;dr What is the correct method to get current foreground process and prevent false postives? How is the order of the list done - the API says it is not specified. Is there a way to order them correctly?

What I have done:

Unfortunately the list returned by the ActivityManager is different on every device. Some devices return multiple infos with the importance 100 (which is FOREGROUND), even if the process is currently not visible.

This caused the problem that I had a lot of false positives. For example, I tested it with facebook and created a toast, every time facebook is in foreground. I switched to Home, so my launcher should have been the foreground process. It was for like 10 seconds, after that, facebook appeared with importance FOREGROUND in the list again (it was not open nor visible) and I got a false positive.

I recognized that some devices order the list by the recent process on top. So I decided to try the following approach:

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
        }

With appProcesses.get(0); I only examine the first element and the bug was gone. No false positives anymore.

But, now on some devices I do not get the foreground process at all anymore. Because they do not order the list in any way. For example some 4.2 Sony smartphones are some of the candidates. I get the list, but the really currently visible process is at index 11 or so.

I have no clue what to do, to get the current foreground process, without false positives.

What is the correct method to get current foreground process and prevent false postives? How is the order of the list done - the API says it is not specified. Is there a way to order them correctly?

Thanks!

JacksOnF1re
  • 3,336
  • 24
  • 55
  • This looks like a dupe of http://stackoverflow.com/questions/2166961/determining-the-current-foreground-application-from-a-background-task-or-service – alzee Dec 13 '15 at 21:44
  • I haven't tested, but this looks like it will help you: http://stackoverflow.com/a/33886313/4973904 – Álisson Morais Dec 13 '15 at 21:58
  • @ÁlissonMorais Well, thanks first for the response, but did you read the complete question? I can't use the first item of the returned list only, because on like 30% of devices, the list is not sorted. – JacksOnF1re Dec 13 '15 at 22:35
  • @user3137702 Thanks, but this isn't a duplicate, I do not want to use the usageStats manager, since on Samsung devices it won't work, they decided to not support it and the getTasks method is deprecated since api 21 and needs the permission get tasks. – JacksOnF1re Dec 13 '15 at 22:36
  • @JacksOnF1re Which lower API your application will support? You could do a check for API level and use both methods: ActivityManager and UsageStatsManager. In which case you are encountering problems? Higher or lower than API 21? – Álisson Morais Dec 13 '15 at 22:46
  • It will support every API level from 16 to current available. But as said, Usage Stats manager is no answer, since Samsung devices to not all support it. Unfortunately. – JacksOnF1re Dec 13 '15 at 22:57
  • Have you tried this way : http://stackoverflow.com/a/32366476/3061903 – Vishal Maral Sep 04 '16 at 14:07

1 Answers1

3

What is the correct method to get current foreground process and prevent false positives?

UsageStatsManager is the only official API to get the current running app (see #50).

Using getRunningTasks(int maxNum), getRunningAppProcesses() or AccessibilityService to get the foreground app has never been reliable. The documentation for the first two methods has the following warning: Note: this method is only intended for debugging


Below is an example for getting the top app using 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));

I know this isn't the answer you are hoping for. Apps like CM Security and AppLock use UsageStatsManager on Android 5.1.1+. Due to SeLinux, it is impossible to get the foreground app using getRunningTasks(int maxNum) or getRunningAppProcesses().

Community
  • 1
  • 1
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
  • Thanks for the answer! Unfortunately the StatsManager won't work for most of the Samsumg devices and not below API 21 (as you also stated out). :/ – JacksOnF1re Dec 16 '15 at 01:14