← Назад к вопросам

Как работать с разрешениями в Android 6.0+?

1.7 Middle🔥 212 комментариев
#Android компоненты

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Работа с разрешениями в Android 6.0+

Начиная с Android 6.0 (API 23), Google ввела модель Runtime Permissions (разрешения во время выполнения). Это фундаментальное изменение, призванное повысить безопасность и прозрачность — пользователь предоставляет доступ к чувствительным данным (контакты, местоположение, камера и т.д.) не при установке приложения, а непосредственно в момент необходимости, прямо во время работы приложения.

Основные принципы новой модели

Все опасные разрешения (определяемые как dangerous в манифесте) теперь делятся на группы разрешений. Предоставление одного разрешения из группы автоматически даёт доступ ко всем остальным в этой группе (хронить на это не стоит, логика может измениться).

Весь процесс работы строится на использовании методов Activity Result API, который пришёл на смену устаревшему подходу с переопределением onRequestPermissionsResult.


Пошаговая реализация

1. Объявление разрешений в AndroidManifest.xml

Даже в новой модели разрешения необходимо декларировать в манифесте. Это информирует систему и магазины приложений о потребностях вашего приложения.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <!-- Запрашиваем разрешение на доступ к камере -->
    <uses-permission android:name="android.permission.CAMERA" />
    <!-- Запрашиваем разрешение на доступ к точному местоположению -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <application ...>
        ...
    </application>
</manifest>

2. Проверка статуса разрешения

Перед выполнением операции, требующей разрешения, необходимо проверить его текущий статус.

import android.content.pm.PackageManager

// ...

private fun checkPermission(permission: String): Boolean {
    return ContextCompat.checkSelfPermission(
        this, // Context (например, Activity)
        permission
    ) == PackageManager.PERMISSION_GRANTED
}

// Пример использования
val isCameraGranted = checkPermission(Manifest.permission.CAMERA)

3. Запрос разрешения у пользователя

Если разрешение не предоставлено, его нужно запросить. Используйте registerForActivityResult с контрактом ActivityResultContracts.RequestPermission() (для одного разрешения) или RequestMultiplePermissions() (для нескольких).

Пример запроса одного разрешения:

import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : AppCompatActivity() {
    // 1. Регистрируем контракт на получение результата запроса
    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted: Boolean ->
        // 2. Колбэк, вызываемый после ответа пользователя
        if (isGranted) {
            // Разрешение предоставлено. Запускаем операцию.
            openCamera()
        } else {
            // Разрешение отклонено. Объясняем пользователю последствия.
            showPermissionDeniedDialog()
        }
    }

    fun onCameraButtonClicked() {
        when {
            // 3. Проверяем, есть ли уже разрешение
            ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -> {
                openCamera()
            }
            // 4. Проверяем, нужно ли показать объяснение (rationale)
            shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
                // Пользователь ранее отклонял запрос. Нужно объяснить, зачем нужно разрешение.
                showRationaleDialogForCamera()
            }
            else -> {
                // 5. Запрашиваем разрешение. Система отобразит стандартное диалоговое окно.
                requestPermissionLauncher.launch(Manifest.permission.CAMERA)
            }
        }
    }

    private fun openCamera() {
        // Логика работы с камерой
    }
}

Пример запроса нескольких разрешений:

private val requestMultiplePermissionsLauncher = registerForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) { permissionsMap: Map<String, Boolean> ->
    permissionsMap.entries.forEach { entry ->
        val permissionName = entry.key
        val isGranted = entry.value
        // Обрабатываем результат для каждого разрешения
        if (isGranted) {
            when (permissionName) {
                Manifest.permission.CAMERA -> openCamera()
                Manifest.permission.RECORD_AUDIO -> startRecording()
            }
        } else {
            // Можно проверить shouldShowRequestPermissionRationale для каждого
        }
    }
}

fun requestLocationAndCamera() {
    requestMultiplePermissionsLauncher.launch(
        arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.CAMERA
        )
    )
}

4. Обработка сценария "Больше не спрашивать"

Если пользователь отклонил запрос и поставил галочку "Больше не спрашивать" (Don't ask again), метод shouldShowRequestPermissionRationale() вернёт false. В этом случае стандартное системное диалоговое окно больше не появится. Вам необходимо:

  • Вежливо объяснить пользователю, что функция недоступна без разрешения.
  • Предоставить кнопку-ссылку для перехода в настройки приложения, где разрешение можно включить вручную.
private fun showPermissionDeniedDialog() {
    AlertDialog.Builder(this)
        .setTitle("Требуется разрешение")
        .setMessage("Для работы этой функции необходим доступ к камере. Вы можете предоставить его в настройках приложения.")
        .setPositiveButton("Открыть настройки") { _, _ ->
            // Интент для открытия экрана настроек конкретного приложения
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
            intent.data = Uri.fromParts("package", packageName, null)
            startActivity(intent)
        }
        .setNegativeButton("Отмена", null)
        .show()
}

Важные рекомендации и лучшие практики

  • Запрашивайте разрешения контекстно. Не спрашивайте все разрешения при старте приложения. Просите доступ в тот момент, когда пользователь инициировал действие, требующее этого разрешения (например, нажал кнопку "Сделать фото").
  • Всегда проверяйте наличие разрешения перед использованием API. Даже если вы его уже запрашивали, пользователь может отозвать его в настройках в любой момент.
  • Объясняйте пользу (Rationale). Если shouldShowRequestPermissionRationale возвращает true, покажите пользователю простое объяснение, зачем вашему приложению нужен этот доступ. Это повышает вероятность одобрения.
  • Уважайте отказ. Если пользователь окончательно запретил доступ, не заставляйте его — дайте возможность использовать остальной функционал приложения.
  • Для фонового доступа к местоположению (Android 10+) и доступа ко всем файлам (Android 11+) существуют специальные, более строгие разрешения, требующие дополнительных действий в манифесте и, иногда, ручного перехода в настройки.

Использование Activity Result API делает код более модульным, тестируемым и избавляет от запутанной логики в onRequestPermissionsResult, что является современным и рекомендованным Google подходом к работе с разрешениями.