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

时间:2014-07-05 21:01:45

标签: android process android-5.0-lollipop android-task

背景

My app允许在最近推出时对应用列表进行排序。

问题

从Android“L”开始,函数getRecentTasks将返回当前应用已启动的应用列表,如documentation中所述:

  

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

     

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

使用ADT显示此功能的文档(目前在Internet上不可用)时写的相同:

  

不推荐使用此方法。截至L,此方法不再可用   到第三方应用程序:作为以文档为中心的引入   最近意味着它可以将个人信息泄露给呼叫者。对于   向后兼容性,它仍然会返回它的一小部分   data:至少是调用者自己的任务(尽管请参阅getAppTasks())   检索该信息的正确支持方式),并且可能   其他一些任务,如家庭,已知不敏感。

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

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

我尝试了什么

目前,我只使用了一种关于最近推出了哪些应用的启发式方法 - 我得到了正在运行的进程列表。

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

问题

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

也许root可以吗?还是BusyBox?

4 个答案:

答案 0 :(得分:34)

要获取当前正在运行的top(Foreground)包名称,您需要使用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();                                   
        }                                       
    }
}

答案 1 :(得分:6)

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

您必须使用UsageStatsManager.queryEvents()并使用MOVE_TO_FOREGROUND事件类型查找最新事件,以确定当前前台程序包。

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

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