如何检查是否给出了"android.permission.PACKAGE_USAGE_STATS"权限?

and*_*per 40 permissions android usage-statistics android-recents usagestatsmanager

背景

我正在尝试获取应用程序启动的统计信息,并且在Lollipop上可以通过使用UsageStatsManager类来实现(原始帖子在这里):

表现:

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

打开活动,让用户确认给您这个权限:

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

获取统计数据,汇总:

 private static final String USAGE_STATS_SERVICE ="usagestats"; // Context.USAGE_STATS_SERVICE);
 ...
 final UsageStatsManager usageStatsManager=(UsageStatsManager)context.getSystemService(USAGE_STATS_SERVICE);
 final Map<String,UsageStats> queryUsageStats=usageStatsManager.queryAndAggregateUsageStats(fromTime,toTime);
Run Code Online (Sandbox Code Playgroud)

问题

我似乎无法检查是否授予您所需的权限("android.permission.PACKAGE_USAGE_STATS").到目前为止我所做的一切总是会让人感到被拒绝.

代码有效,但权限检查不起作用.

我试过的

您可以使用以下任一方法检查是否授予了权限:

String permission = "android.permission.PACKAGE_USAGE_STATS";
boolean granted=getContext().checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;   
Run Code Online (Sandbox Code Playgroud)

或这个:

String permission = "android.permission.PACKAGE_USAGE_STATS";
boolean granted=getPackageManager().checkPermission(permission,getPackageName())== PackageManager.PERMISSION_GRANTED;   
Run Code Online (Sandbox Code Playgroud)

两者总是返回它被拒绝(即使我已经授予用户权限).

看看UsageStatsManager的代码,我试图想出这个解决方法:

      UsageStatsManager usm=(UsageStatsManager)getSystemService("usagestats");
      Calendar calendar=Calendar.getInstance();
      long toTime=calendar.getTimeInMillis();
      calendar.add(Calendar.YEAR,-1);
      long fromTime=calendar.getTimeInMillis();
      final List<UsageStats> queryUsageStats=usm.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,fromTime,toTime);
      boolean granted=queryUsageStats!=null&&queryUsageStats!=Collections.EMPTY_LIST;
Run Code Online (Sandbox Code Playgroud)

它工作,但它仍然是一个解决方法.

这个问题

为什么我没有得到权限检查的正确结果?

应该怎么做才能更好地检查?

Tom*_*mik 27

用户在系统设置中授予的特殊权限(使用情况统计信息访问,通知访问权限等)由AppOpsManager处理,AppOpsManager已在Android 4.4中添加.

请注意,除了在系统设置中授予您访问权限的用户之外,您通常还需要Android清单(或某些组件)中的权限,而您的应用甚至不会在系统设置中显示.对于使用统计,您需要android.permission.PACKAGE_USAGE_STATS获得许可.

关于此的文档不​​多,但您可以随时查看Android源代码.解决方案可能看起来有点hacky,因为稍后会添加一些常量AppOpsManager,并且某些常量(例如,用于检查不同的权限)仍然隐藏在私有API中.

AppOpsManager appOps = (AppOpsManager) context
        .getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow("android:get_usage_stats", 
        android.os.Process.myUid(), context.getPackageName());
boolean granted = mode == AppOpsManager.MODE_ALLOWED;
Run Code Online (Sandbox Code Playgroud)

这会告诉您用户是否授予了权限.请注意,由于API级别21存在常量AppOpsManager.OPSTR_GET_USAGE_STATS = "android:get_usage_stats".

我在Lollipop(包括5.1.1)上测试了这个检查,它按预期工作.它告诉我用户是否给出了明确的权限而没有任何崩溃.还有一种方法appOps.checkOp()可能会抛出一个SecurityException.


Chr*_* Li 16

通过我们的调查:如果MODE是默认值(MODE_DEFAULT),则需要额外的权限检查.感谢Weien的考试工作.

boolean granted = false;
AppOpsManager appOps = (AppOpsManager) context
        .getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, 
        android.os.Process.myUid(), context.getPackageName());

if (mode == AppOpsManager.MODE_DEFAULT) {
    granted = (context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) == PackageManager.PERMISSION_GRANTED);
} else {
    granted = (mode == AppOpsManager.MODE_ALLOWED);
}
Run Code Online (Sandbox Code Playgroud)