Как работать с разрешениями в 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 требует ручного включения в настройках.
Как корректно запрашивать и проверять разрешения (практика)
- Добавьте разрешение в AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
- Перед вызовом защищённого API проверьте статус:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQ)
} else {
// доступ есть
}
- Обработайте результат:
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"
- Манифест: указан ли <uses-permission ...>?
- Runtime: вызываете ли checkSelfPermission() и requestPermissions() перед использованием API?
- Target SDK: если targetSdkVersion < 23, поведение отличается — учитывайте при тестах.
- Scoped Storage: для доступа к файлам на Android 10+ используйте MediaStore/SАF; WRITE_EXTERNAL_STORAGE уже не даёт прямой доступ на новых версиях.
- Очистите данные и переустановите: adb shell pm clear com.example.app; затем проверьте снова.
- Если после pm grant проблема остаётся: смотрите логи SELinux (dmesg | grep denied) — возможно политика блокирует доступ.
- Для 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 только для отладки.