Как проверить, разрешено ли разрешение «android.permission.PACKAGE_USAGE_STATS»?

Задний план

Я пытаюсь получить статистику, полученную приложением, и на 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.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; 

Это сработало, но это все еще обходное решение.

Вопрос

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

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

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

    Специальные разрешения, предоставленные пользователем в системных настройках (доступ к статистическим данным , доступ к уведомлениям и т. Д.), Обрабатываются 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" .

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

    Второй аргумент checkOpNoThrowuid , а не 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;