Как проверить, если " android.разрешение.Статистика использования пакета " разрешение дано?

фон

Я пытаюсь получить статистику запуска приложений, а на Lollipop это возможно с помощью UsageStatsManager класс, как таковой (исходное сообщение здесь):

манифест:

<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.разрешение.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;

это сработало, но это все еще обходной путь.

вопрос

почему я не получаю правильный результат проверки разрешения?

что нужно сделать, чтобы проверить это лучше?

3 ответов


по нашему исследованию: если режим по умолчанию (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);
}

специальные разрешения, которые предоставляются Пользователем в Системных настройках (доступ к статистике использования, доступ к уведомлениям, ...) обрабатываются AppOpsManager, который был добавлен в Android 4.4.

обратите внимание, что помимо предоставления вам доступа в Системных настройках вам обычно требуется разрешение в манифесте Android (или каком-либо компоненте), без которого ваше приложение даже не отображается в Системных настройках. Для статистики использования вам нужно android.permission.PACKAGE_USAGE_STATS разрешение.

существует не так много документации об этом, но вы всегда можете проверить источники Android для его. Решение может показаться немного избитым, потому что некоторые константы были добавлены позже к 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".

Я проверил этот чек на леденец (включая 5.1.1), и он работает так, как ожидалось. Он говорит мне, дал ли пользователь явное разрешение без какого-либо сбоя. Существует также метод appOps.checkOp() что может бросить SecurityException.


второй аргумент checkOpNoThrow is 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;