Как работать с permission в Android — кратко и по делу

Короткий ответ: запрашивайте dangerous permissions в рантайме (проверка через ContextCompat.checkSelfPermission → Activity Result API / ActivityCompat.requestPermissions), обрабатывайте отказ через shouldShowRequestPermissionRationale и при "Не спрашивать" предлагайте открыть настройки приложения. Ниже — рабочие примеры и алгоритмы.

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

  1. Всегда проверяйте текущее состояние перед запросом:
  • ContextCompat.checkSelfPermission() — есть ли разрешение.
  • Для группы разрешений проверяйте по каждому требуемому.
  1. Рекомендуемый современный способ — Activity Result API: kotlin
// В Activity или Fragment
private val requestCamera = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { granted ->
    if (granted) openCamera() else handleDenied()
}

// Запрос
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
    != PackageManager.PERMISSION_GRANTED) {
    requestCamera.launch(Manifest.permission.CAMERA)
} else {
    openCamera()
}
  1. Для множественных разрешений используйте RequestMultiplePermissions или Accompanist/Permissions в Compose: kotlin
val launcher = registerForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) { results -> /* results: Map<String, Boolean> */ }
launcher.launch(arrayOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO))
  1. Сохраняйте UX:
  • Запрашивайте только нужные разрешения, когда функция реально используется.
  • Для уведомлений в Android 13+ динамически запрашивайте POST_NOTIFICATIONS.
  • В Compose используйте библиотеки (Accompanist или официальные вспомогательные API) для декларативного диалога.

Проверяйте ContextCompat.checkSelfPermission() перед запросом, чтобы не показывать диалог повторно и не раздражать пользователя.

Короткая сводка по типам разрешений

ТипПримерКак обрабатывается
normalACCESS_NETWORK_STATEАвто при установке
dangerousCAMERA, LOCATIONRuntime‑запрос
specialSYSTEM_ALERT_WINDOWЗапрос через настройки
new (post-API)POST_NOTIFICATIONS, PHOTO_PICKERЗапрос/новые API поведения

Как пользователю выдавать и управлять разрешениями

  • Через Настройки > Приложения > [Ваше приложение] > Разрешения — включить/выключить по группам.
  • Для "Только один раз" — выбирайте опцию в диалоге запроса (Android 11+).
  • Если поставлен "Не спрашивать", нужно вручную открыть страницу приложения: kotlin
startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
    data = Uri.fromParts("package", packageName, null)
})
  • Система автоматически отзывает неиспользуемые разрешения (auto-revoke) для неактивных приложений (поведение с Android 11+).

Не выдавайте все разрешения подряд. Чем меньше запрашиваете — выше доверие и шанс на согласие.

Что делать при запрете доступа — рекомендации для разработчика

Алгоритм обработки отказа:

  1. Если пользователь отказал первый раз — покажите объяснение (rationale) перед повторным запросом.
  2. Если shouldShowRequestPermissionRationale() возвращает false (включая "Не спрашивать") — не спамьте диалогами, предложите открыть настройки.
  3. Деградируйте функциональность: отключите фичу с понятным сообщением и альтернативой (например, загрузить фото вместо камеры).
  4. Логируйте отказы для аналитики, но не используйте это для агрессивных повторных запросов.

Пример rationale: kotlin

if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
    AlertDialog.Builder(this)
      .setMessage("Камера нужна для сканирования QR-кодов")
      .setPositiveButton("Разрешить") { _,_ -> requestCamera.launch(Manifest.permission.CAMERA) }
      .setNegativeButton("Отмена", null)
      .show()
} else {
    // Открываем настройки — пользователь, возможно, выбрал "Не спрашивать"
    startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
        data = Uri.fromParts("package", packageName, null)
    })
}

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

  • Запрашивать все разрешения сразу при старте — ведёт к отказам.
  • Игнорировать shouldShowRequestPermissionRationale и повторно показывать диалоги.
  • Пытаться работать с API без проверки разрешения → краши.
  • Не учитывать авто-отзыв (auto-revoke) и новые приватные API (PHOTO_PICKER, APPROXIMATE_LOCATION).

FAQ

  • Нужно ли запрашивать разрешение при установке?
    Нельзя: dangerous permissions запрашиваются в рантайме с Android 6.0+.

  • Как понять, что пользователь выбрал "Только один раз"?
    В диалоге система даёт опцию; при следующем использовании нужно снова запросить.

  • Что с доступом к файлам (storage)?
    Используйте Scoped Storage и MediaStore; минимизируйте использование READ/WRITE_EXTERNAL_STORAGE, мигрируйте на Photo Picker и API доступа к медиа.

  • Как тестировать поведение на разных Android?
    Тестируйте на эмуляторах и реальных устройствах с разными версиями — поведение Permission API меняется между релизами.

Если нужно, могу подготовить готовые Kotlin‑фрагменты для вашего проекта (Activity/Fragment/Compose) с учетом Activity Result API и обработки всех веток отказа.