如何检查是否给“android.permission.PACKAGE_USAGE_STATS”权限?

背景

我试图获取应用程序启动的统计信息,并且在棒棒糖上,可以通过使用UsageStatsManager类(如此处原始的post):

performance:

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

打开让用户确认给你这个权限的活动:

 startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); 

获取统计信息,汇总:

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

问题

我似乎无法检查是否授予您所需的权限(“android.permission.PACKAGE_USAGE_STATS”)。 到目前为止,我所尝试过的所有方式总是会被拒绝。

代码工作,但权限检查不能正常工作。

我试过了

您可以使用以下方法检查授予的权限:

 String permission = "android.permission.PACKAGE_USAGE_STATS"; boolean granted=getContext().checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED; 

或这个:

 String permission = "android.permission.PACKAGE_USAGE_STATS"; boolean granted=getPackageManager().checkPermission(permission,getPackageName())== PackageManager.PERMISSION_GRANTED; 

两者总是返回,它被拒绝(即使我已经授予作为用户的权限)。

查看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; 

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

这个问题

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

应该做什么来检查它更好?

Solutions Collecting From Web of "如何检查是否给“android.permission.PACKAGE_USAGE_STATS”权限?"

通过我们的调查:如果MODE是默认的(MODE_DEFAULT),则需要额外的权限检查。 感谢魏恩的考试。

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

用户在系统设置(使用状态访问,通知访问…)中授予的特殊权限由Android 4.4中添加的AppOpsManager处理。

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

没有太多的文档,但你可以随时检查Android的来源。 这个解决scheme可能看起来有些AppOpsManager ,因为有些常量稍后添加到了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; 

这告诉你,如果权限是由用户授予。 请注意,因为API级别21有不变的AppOpsManager.OPSTR_GET_USAGE_STATS = "android:get_usage_stats"

我testing了棒棒糖(包括5.1.1)这个检查,它按预期工作。 它告诉我用户是否给出了明确的许可而没有任何崩溃。 还有方法appOps.checkOp()可能会抛出SecurityException

checkOpNoThrow的第二个参数是uid ,而不是pid

更改代码以反映这似乎解决了其他人遇到的问题:

 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;