如何在Android“L”上获取最近的任务?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24590533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:27:41  来源:igfitidea点击:

How to get recent tasks on Android "L"?

androidprocessandroid-5.0-lollipopandroid-task

提问by android developer

Background

背景

My appallows to sort an apps list by the time they were recently launched .

我的应用程序允许按最近启动的时间对应用程序列表进行排序。

The problem

问题

As of Android "L" , the function getRecentTaskswill just return the list of apps that the current app has launched, as written in the documentation:

从 Android "L" 开始,函数getRecentTasks将只返回当前应用程序已启动的应用程序列表,如文档中所述:

If your app uses ActivityManager.getRecentTasks()...

With the introduction of the new concurrent documents and activities tasks feature in the upcoming release (see Concurrent documents and activities in Recents screen below), the ActivityManager.getRecentTasks() method is now deprecated to improve user privacy. For backward compatibility, this method still returns a small subset of its data, including the calling application's own tasks and possibly some other non-sensitive tasks (such as Home). If your app is using this method to retrieve its own tasks, use android.app.ActivityManager.getAppTasks() instead to retrieve that information.

如果您的应用程序使用 ActivityManager.getRecentTasks()...

随着在即将发布的版本中引入新的并发文档和活动任务功能(请参阅下面最近屏幕中的并发文档和活动),现在不推荐使用 ActivityManager.getRecentTasks() 方法以提高用户隐私。为了向后兼容,此方法仍返回其数据的一小部分,包括调用应用程序自己的任务和可能的其他一些非敏感任务(例如 Home)。如果您的应用使用此方法来检索自己的任务,请改用 android.app.ActivityManager.getAppTasks() 来检索该信息。

Same is written when using ADT to show the documentation of this function (not currently available on the Internet) :

使用 ADT 显示此函数的文档时也是如此(当前在 Internet 上不可用):

This method is deprecated. As of L, this method is no longer available to third party applications: as the introduction of document-centric recents means it can leak personal information to the caller. For backwards compatibility, it will still return a small subset of its data: at least the caller's own tasks (though see getAppTasks() for the correct supported way to retrieve that information), and possibly some other tasks such as home that are known to not be sensitive.

此方法已弃用。从 L 开始,此方法不再适用于第三方应用程序:由于引入了以文档为中心的最近记录,这意味着它可能会将个人信息泄露给调用者。为了向后兼容,它仍将返回其数据的一小部分:至少是调用者自己的任务(尽管请参阅 getAppTasks() 以获取检索该信息的正确支持方式),并且可能还有一些其他任务,例如已知的 home不要敏感。

I don't get why this act was taken, as it's easy to see which apps the user has, and even without any permission.

我不明白为什么要采取这一行动,因为很容易看到用户拥有哪些应用程序,即使没有任何许可。

Thing is, this is a big restriction for this feature that I've added, so I hope there is a way to overcome this.

事实是,这是我添加的此功能的一个很大限制,所以我希望有一种方法可以克服这个限制。

What I've tried

我试过的

For now, I only used a heuristic way about which apps were recently launched - I get the list of running processes instead.

目前,我只使用启发式方法来了解最近启动了哪些应用程序——而是获取正在运行的进程列表。

I could also use the importance value of the processes and maybe the "importanceReasonComponent" , but this is just all heuristics and guesses ...

我也可以使用流程的重要性值,也许是 "importanceReasonComponent" ,但这只是启发式和猜测......

The question

问题

Is there a way to overcome this restriction? Any workaround I haven't thought of?

有没有办法克服这个限制?我没有想到的任何解决方法?

Maybe it's possible with root? Or BusyBox ?

也许root可以?还是 BusyBox ?

回答by user3742392

To get the top (Foreground) package name currently running you need to use the Usage Stats API in Android Lollipop.

要获取当前运行的顶级(前台)包名称,您需要使用 Android Lollipop 中的 Usage Stats API。

But notice user has to approve the access to usage data in the settings for each Application. So you should prompt the user directly to the setting by launching setting action with

但请注意,用户必须在每个应用程序的设置中批准对使用数据的访问。因此,您应该通过启动设置操作来直接提示用户进行设置

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);

To get top packagename:

获取顶级包名:

String topPackageName ;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService("usagestats");                       
    long time = System.currentTimeMillis(); 
    // We get usage stats for the last 10 seconds
    List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*10, time);                                    
    // Sort the stats by the last time used
    if(stats != null) {
        SortedMap<Long,UsageStats> mySortedMap = new TreeMap<Long,UsageStats>();
        for (UsageStats usageStats : stats) {
            mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
        }                    
        if(!mySortedMap.isEmpty()) {
            topPackageName =  mySortedMap.get(mySortedMap.lastKey()).getPackageName();                                   
        }                                       
    }
}

回答by Sam Lu

If you Use UsageStats to get the current foreground package, you will get the wrong information when user opens the notification drawer or on a locked screen. (tested on both Android Lollipop and Marshmallow)

如果使用 UsageStats 获取当前前台包,当用户打开通知抽屉或在锁定屏幕上时,您将获得错误的信息。(在 Android Lollipop 和 Marshmallow 上测试)

You have to use UsageStatsManager.queryEvents() and look for the latest event with MOVE_TO_FOREGROUND event type for deciding the current foreground package.

您必须使用 UsageStatsManager.queryEvents() 并查找具有 MOVE_TO_FOREGROUND 事件类型的最新事件来决定当前的前台包。

回答by Atish

Lollipop deprecated the method; however there is a new API that allows you to view app usage. The method was deprecated because of security issues. :\

Lollipop 弃用了该方法;但是有一个新的 API 可以让您查看应用程序的使用情况。由于安全问题,该方法已被弃用。:\

UsageStatsManager has some useful methods to see activity between an interval of time. Hope this is sufficient for your needs!

UsageStatsManager 有一些有用的方法来查看时间间隔之间的活动。希望这足以满足您的需求!

https://developer.android.com/reference/android/app/usage/package-summary.html

https://developer.android.com/reference/android/app/usage/package-summary.html

回答by stevo.mit

@user3742392 answer is good, however using a TreeMap to find last used time is a bit overkill (especially if you want to check top running app periodically).

@user3742392 答案很好,但是使用 TreeMap 来查找上次使用时间有点矫枉过正(特别是如果您想定期检查正在运行的应用程序)。

Here is the edited answer without the TreeMap with simple loop instead:

这是没有使用简单循环的 TreeMap 的编辑答案:

String topPackageName;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService("usagestats");
    long currentTime = System.currentTimeMillis();
    // get usage stats for the last 10 seconds
    List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, currentTime - 1000 * 10, currentTime);
    // search for app with most recent last used time
    if (stats != null) {
        long lastUsedAppTime = 0;
        for (UsageStats usageStats : stats) {
            if (usageStats.getLastTimeUsed() > lastUsedAppTime) {
                topPackageName = usageStats.getPackageName();
                lastUsedAppTime = usageStats.getLastTimeUsed();
            }
        }
    }
}