如何使用UsageStatsManager?

and*_*per 52 android usage-statistics activity-manager android-recents usagestatsmanager

背景

谷歌已弃用getRecentTasks"ActivityManager"类的功能" ".现在它所做的只是获取当前应用程序已打开的应用程序列表.

我甚至在StackOverflow上写了一篇关于它的帖子,但我发现这是不可能的.

问题

我发了一篇关于它的帖子(在这里,另一个,类似的由其他人创建,在这里),并要求重新考虑它,谷歌决定创建一个新类,似乎提供类似的功能(更像是统计,但也可能有用),但我无法找到如何使用它.

该类称为" UsageStatsManager",我的猜测是函数" queryUsageStats"完成工作.

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

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

这是关于这个新功能另一个链接.

我发现了什么

我查看了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";
Run Code Online (Sandbox Code Playgroud)

奇怪的是,不仅它说" status bar",而且packageName也不匹配(应该是" android.app.usage.UsageStatsManager").

我还添加了正确的权限:

<uses-permission
    android:name="android.permission.PACKAGE_USAGE_STATS"
    tools:ignore="ProtectedPermissions" />
Run Code Online (Sandbox Code Playgroud)

这是我使用的代码:

  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);
Run Code Online (Sandbox Code Playgroud)

在模拟器本身,我去了" Settings"->"security"->"apps with usage access",并启用了我的应用程序.

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

这个问题

你怎么用的UsageStatsManager

另外,您如何让用户以最简单的方式授予权限?或者,只要应用程序尝试获取所需信息,它是否会自动完成?

尝试使用此类但用户尚未确认时会发生什么?

如何让代码返回真正的应用程序列表?

Ati*_*ish 31

我认为文档只是日历内容的简写.我不认为它实际上只适用于2014年; 但是我错了.

要访问UsageStats的实际列表,您需要创建具有正确月,日和年的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());
Run Code Online (Sandbox Code Playgroud)

-Credit MRK; 由我纠正(他偶然只是把cal而不是beginCal和endCal)

使用访问设置的代码如下.:)

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)


Col*_*ray 23

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

https://github.com/ColeMurray/UsageStatsSample


MRK*_*MRK 9

回答你的上一个问题"如何让代码返回真实的应用程序列表?".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());
Run Code Online (Sandbox Code Playgroud)

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


Sam*_* Lu 7

当用户打开通知抽屉或在锁定的屏幕上时,使用 UsageStats 会得到错误的信息。您必须使用 UsageStatsManager.queryEvents() 并查找具有 MOVE_TO_FOREGROUND 事件类型的最新事件。


jus*_*rec 7

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());
    
    Run Code Online (Sandbox Code Playgroud)
  4. 创建基于应用程序的列表 UsageStats

总结并应用于您的示例:

  • 您似乎正确地请求并授予访问使用情况统计信息的权限。
  • 您正确获得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);
Run Code Online (Sandbox Code Playgroud)

正确的:

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);
Run Code Online (Sandbox Code Playgroud)