Как работать с разрешениями в Android и исправлять Permission denied

В первых 200 символах: чтобы исправить Permission denied — проверь манифест, убедись в runtime‑проверке через checkSelfPermission(), запроси разрешение пользователю (ActivityCompat.requestPermissions) или на время отладки выдай через adb shell pm grant; далее следуй чек‑листу в статье.

Зачем нужны разрешения и какие они бывают

Разрешения защищают пользовательские данные. С Android 6.0 добавлены runtime‑permissions: опасные (dangerous) нужно запрашивать при работе приложения; normal выдаются автоматически; signature/system — только для системных/подписанных приложений; special — отдельные настройки (MANAGE_EXTERNAL_STORAGE, POST_NOTIFICATIONS и т.п.). При обращении к API без нужного разрешения вы получите SecurityException ("Permission denied").

Для storage в Android 11+ и выше рассматривайте SAF или MediaStore вместо прямого доступа; MANAGE_EXTERNAL_STORAGE требует ручного включения в настройках.

Как корректно запрашивать и проверять разрешения (практика)

  1. Добавьте разрешение в AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
  1. Перед вызовом защищённого API проверьте статус:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQ)
} else {
    // доступ есть
}
  1. Обработайте результат:
override fun onRequestPermissionsResult(req: Int, perms: Array<String>, res: IntArray) {
  if (req == REQ && res.isNotEmpty() && res[0] == PackageManager.PERMISSION_GRANTED) {
    // OK
  } else {
    if (shouldShowRequestPermissionRationale(perms[0])) showRationale()
    else openAppSettings() // если "Не спрашивать"
  }
}
  • Для Jetpack Compose используйте библиотеки permission‑helpers (Accompanist/Compose APIs).
  • Группируйте связанные разрешения, но объясняйте пользователю, зачем они нужны.

Покажите объяснение (rationale) перед повторным запросом: это повышает конверсию согласий.

pm grant / ADB: когда и как использовать

Для отладки и автоматизации вы можете выдавать/отзывать разрешения через ADB (USB‑отладка включена):

Выдать:

adb shell pm grant com.example.app android.permission.CAMERA

Отозвать:

adb shell pm revoke com.example.app android.permission.CAMERA

Проверить:

adb shell dumpsys package com.example.app | grep permission

pm grant не даёт системных привилегий: некоторые разрешения требуются только для системных/подписанных приложений. Не используйте это в продакшене — для тестов и CI.

Пошаговый план исправления "Permission denied"

  1. Манифест: указан ли <uses-permission ...>?
  2. Runtime: вызываете ли checkSelfPermission() и requestPermissions() перед использованием API?
  3. Target SDK: если targetSdkVersion < 23, поведение отличается — учитывайте при тестах.
  4. Scoped Storage: для доступа к файлам на Android 10+ используйте MediaStore/SАF; WRITE_EXTERNAL_STORAGE уже не даёт прямой доступ на новых версиях.
  5. Очистите данные и переустановите: adb shell pm clear com.example.app; затем проверьте снова.
  6. Если после pm grant проблема остаётся: смотрите логи SELinux (dmesg | grep denied) — возможно политика блокирует доступ.
  7. Для foreground services и уведомлений: не забудьте соответствующие разрешения (например, FOREGROUND_SERVICE, POST_NOTIFICATIONS для новых Android).

Пример типичного исключения: java.lang.SecurityException: Permission denied (missing INTERNET permission?)

Частые ошибки

  • Забыт манифест .
  • Не проверяют разрешение перед вызовом API.
  • Пользователь навсегда запретил — продолжают вызывать requestPermissions вместо редиректа в настройки.
  • Ожидание прямого доступа к файлам на Android 11+ без использования SAF/MediaStore.
  • Ожидание, что pm grant решит системные/SELinux проблемы.

FAQ

  • Что делать, если пользователь выбрал "Не спрашивать"?
    Откройте настройки приложения через ACTION_APPLICATION_DETAILS_SETTINGS и объясните, зачем нужен доступ.
  • Можно ли автоматизировать выдачу разрешений на CI?
    Да — через adb (pm grant) в эмуляторах или тестовых девайсах с включённой отладкой.
  • Почему разрешение есть на эмуляторе, но нет на реальном устройстве?
    Возможны дополнительные политики производителя, SELinux или отличие targetSdk/OS версии; проверьте логи.

Итог: всегда проверяйте манифест и runtime‑чек, минимизируйте список разрешений, тестируйте на нескольких версиях Android и используйте adb pm grant только для отладки.