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

Posted

技术标签:

【中文标题】如何在 Android "L" 上获取最近的任务?【英文标题】:How to get recent tasks on Android "L"? 【发布时间】:2014-08-26 18:02:06 【问题描述】:

背景

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

问题

android "L" 开始,函数 getRecentTasks 将只返回当前应用已启动的应用列表,如 documentation 中所述:

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

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

使用 ADT 显示该函数的文档时也是这样写的(目前在 Internet 上不可用):

此方法已弃用。自 L 起,此方法不再可用 到第三方应用程序:作为以文档为中心的引入 最近意味着它可以将个人信息泄露给来电者。为了 向后兼容性,它仍将返回其一小部分 数据:至少调用者自己的任务(尽管参见 getAppTasks() 检索该信息的正确支持方式),并且可能 其他一些已知不敏感的任务,例如家。

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

问题是,这是我添加的这个功能的一个很大的限制,所以我希望有办法克服这个问题。

我尝试过的

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

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

问题

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

也许有可能用root?还是 BusyBox?

【问题讨论】:

好吧,他们说原因:the ActivityManager.getRecentTasks() method is now deprecated to improve user privacy 我真的没有答案,但是对于“我不明白为什么要删除它”部分,我想通过 L 引入的新的“以文档为中心”的任务,你会'已经能够知道用户打开了哪些文档或单个网页。 @ianhanniballake 是的,我读过。我只是不同意它有助于隐私,因此我对此发表了一点评论。 @matiash 是的,我已经阅读了所有内容(或者至少我在这里发布的内容),并且还观看了视频,但我在这里要求另一种方法或解决方法,甚至如果需要 root/BusyBox。获取当前应用启动的内容并没有多大帮助... 主演this issue 并希望 Google 在 L 正式发布之前改变主意似乎是最好的选择。 【参考方案1】:

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

但请注意,用户必须在每个应用程序的设置中批准对使用数据的访问。 因此,您应该通过使用

启动设置操作来直接提示用户进行设置
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);

获取***包名:

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

【讨论】:

是的,我忘了更新问题或添加答案。对不起。这是一个类似的问题,在我注意到这是使用它的方法之后:***.com/q/26431795/878126。不过有点奇怪。你能保证获得***应用吗?我的意思是,如果它在 10 多秒前被打开怎么办? 是的,你说得对,如果顶部打开超过 10 秒,则统计信息将返回空列表...大时间会增加列表的大小,因此有时间对其进行排序..所以它会加深您的实现以及您希望如何使用***包的知识。对我来说 10 秒就足够了。 也许,至少它可以获取最近的,从上次打开设备开始?我认为如果查询时间过长,需要相当长的时间才能得到结果。 @user3742392 适用于大多数应用程序,但不适用于某些系统应用程序(Google Now 启动器、下载等)。当其中一个应用程序运行时,它总是返回“com.google.android.googlequicksearchbox” 你会如何在 Android Wear 上做到这一点?它没有用户可以启用此功能的 ACTION_USAGE_ACCESS_SETTINGS 设置屏幕。提前致谢。【参考方案2】:

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

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

【讨论】:

这个答案只是省了我很多麻烦,应该是公认的答案。 是不是也可以知道里面有哪些app有生存过程?【参考方案3】:

@user3742392 的回答很好,但是使用 TreeMap 查找上次使用的时间有点矫枉过正(尤其是如果您想定期检查运行最频繁的应用程序)。

这是编辑后的答案,没有使用简单循环的 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();
            
        
    

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

是的,很抱歉没有更新这个问题。我也找到了,现在不知道怎么用。能否请您检查一下:***.com/q/26431795 看看您是否成功使用它?如果是这样,我可以标记两个答案。

以上是关于如何在 Android "L" 上获取最近的任务?的主要内容,如果未能解决你的问题,请参考以下文章

android 如何将swiperefreshlayout刷新动画能定制吗

如何在 Android XML 中为文本添加下划线?

如何修改 Android 状态栏高度

android 读取xml

如何在 android:updatePeriodMillis="0" 时从 Flutter 更新 Android 小部件?

android获取系统应用大小的方法