如何使用UsageStatsManager?

背景

Google已弃用“ActivityManager”类的函数“ getRecentTasks ”。 现在只需要获取当前应用程序打开的应用程序列表。

我甚至在StackOverflow上写了一篇文章,但是我注意到这是不可能的。

问题

我已经做了一个关于它的文章( 在这里 ,另一个是由别人创build的类似文章),并请求重新考虑它,Google决定创build一个新的类,它似乎提供了类似的function(更像是统计,但也可能是有用的),但我不知道如何使用它。

该类被称为“UsageStatsManager”,我的猜测是函数“ queryUsageStats ”做这个工作。

此外,它似乎有一个新的权限(“android.permission.PACKAGE_USAGE_STATS”),这是一个系统权限,但它写道:

声明权限意味着使用API​​的意图,并且设备的用户可以通过设置应用程序授予权限。

这是关于这个新function另一个链接。

我发现了什么

我已经看了Android的代码,并注意到“Context”有USAGE_STATS_SERVICE,在JavaDocs中说下一件事:

/** * Use with {@link #getSystemService} to retrieve a {@link * android.app.UsageStatsManager} for interacting with the status bar. * * @see #getSystemService * @see android.app.UsageStatsManager * @hide */ public static final String USAGE_STATS_SERVICE = "usagestats"; 

奇怪的是,它不仅说“状态栏”,而且packageName不匹配(而应该是“android.app.usage.UsageStatsManager”)。

我也添加了正确的权限:

 <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" /> 

这里是我使用的代码:

  final UsageStatsManager usageStatsManager=(UsageStatsManager)context.getSystemService("usagestats");// Context.USAGE_STATS_SERVICE); final int currentYear=Calendar.getInstance().get(Calendar.YEAR); final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,currentYear-2,currentYear); 

在模拟器本身,我去“设置” – >“安全” – >“使用访问的应用程序”,并启用我的应用程序。

但是,运行代码时,我得到的是一个空列表…

这个问题

你如何使用UsageStatsManager?

另外,您如何让用户以最简单的方式授予权限? 还是自动完成,只要应用程序试图获得所需的信息?

尝试使用这个类时会发生什么,但用户还没有确认呢?

我怎样才能让代码返回一个真正的应用程序列表?

我认为文档只是日历的东西。 我不认为这只是2014年的实际工作。 但是我可能是错的。

为了访问UsageStats的实际列表,您需要使用正确的月份,date和年份创build一个Calendar对象。 MRK在另一个答案中是如何说的。 我复制并纠正了MRK代码中的错误,所以任何在将来看到它的人都可以看到它。

 Calendar beginCal = Calendar.getInstance(); beginCal.set(Calendar.DATE, 1); beginCal.set(Calendar.MONTH, 0); beginCal.set(Calendar.YEAR, 2012); Calendar endCal = Calendar.getInstance(); endCal.set(Calendar.DATE, 1); endCal.set(Calendar.MONTH, 0); endCal.set(Calendar.YEAR, 2014); final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, beginCal.getTimeInMillis(), endCal.getTimeInMillis()); 

– 信用卡; 由我纠正(他不小心只是把cal而不是beginCal和endCal)

下面是使用访问设置的代码。 🙂

 Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); startActivity(intent); 

我已经创build了一个如何在我的Github上使用UsageStats的示例。 希望对某人有所帮助

https://github.com/ColeMurray/UsageStatsSample

回答你最后的问题“我怎样才能让代码返回给我一个真正的应用程序列表?”。 queryUsageStats以毫秒为单位开始时间和结束时间,而不是int中年份的值。

 Calendar beginCal = Calendar.getInstance(); beginCal.set(Calendar.DATE, 1); beginCal.set(Calendar.MONTH, 0); beginCal.set(Calendar.YEAR, 2012); Calendar endCal = Calendar.getInstance(); endCal.set(Calendar.DATE, 1); endCal.set(Calendar.MONTH, 0); endCal.set(Calendar.YEAR, 2014); final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, beginCal.getTimeInMillis(), endCal.getTimeInMillis()); 

这应该返回2012年和2013年的UsageStats列表(请记住,结束时间不包括最终结果时间范围)。

当用户打开通知抽屉或locking屏幕时,使用UsageStats将得到错误的信息。 您必须使用UsageStatsManager.queryEvents()并使用MOVE_TO_FOREGROUND事件types查找最新的事件。

实际上AOSP示例代码中包含一个示例应用程序 : developers/samples/android/system/AppUsageStatistics/

它包含在应用程序中使用UsageStats所需的所有位:

  1. AndroidManifest.xml声明权限

    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>

  2. 显示设置以授予访问UsageStatsManager权限

    startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));

  3. 查询UsageStatsManager进行统计。

     Calendar cal = Calendar.getInstance(); cal.add(Calendar.YEAR, -1); List<UsageStats> queryUsageStats = mUsageStatsManager .queryUsageStats(intervalType, cal.getTimeInMillis(), System.currentTimeMillis()); 
  4. 根据UsageStats创build一个应用程序列表

总结并应用于您的示例:

  • 您似乎正确地要求并授予访问使用统计信息的权限。
  • 您正确获取UsageStats系统服务。
  • 然而,您查询的时间段是简短的:参数beginTimeendTime是从纪元开始测量的毫秒数。 Calendar实例可以通过getTimeinMillis()给你这个值。 你错误地做的是只给出年份数字(如果你今天运行该程序, 20152017 )。 这些值被解释为自纪元起的毫秒数,因此间隔仅为2毫秒,并且在1970年的某个时间。

而不是你发布的以下代码片段,你应该复制下面发布的示例:

错误:

 final int currentYear=Calendar.getInstance().get(Calendar.YEAR); final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,currentYear-2,currentYear); 

正确:

 final long currentTime = System.currentTimeMillis(); // Get current time in milliseconds final Calendar cal = Calendar.getInstance(); cal.add(Calendar.YEAR, -2); // Set year to beginning of desired period. final long beginTime = cal.getTimeInMillis(); // Get begin time in milliseconds final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, beginTime, currentTime); 

你可以这样做

 //noinspection ResourceType final UsageStatsManager usageStatsManager=(UsageStatsManager)context.getSystemService("usagestats");// Context.USAGE_STATS_SERVICE); final int currentYear=Calendar.getInstance().get(Calendar.YEAR); final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,currentYear-2,currentYear);