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

Как объявлять разрешения в манифесте?

1.0 Junior🔥 303 комментариев
#Жизненный цикл и навигация

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

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

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

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

Работа с разрешениями в Android — фундаментальный аспект разработки, требующий строгого соблюдения правил безопасности и конфиденциальности пользователей. Разрешения объявляются в файле AndroidManifest.xml, который является главным конфигурационным файлом приложения.

Основные типы разрешений

Android делит разрешения на несколько категорий:

  1. Обычные (Normal) разрешения — не представляют риска для приватности пользователя. Система предоставляет их автоматически при установке приложения. Например, android.permission.VIBRATE или android.permission.INTERNET.
  2. Опасные (Dangerous) разрешения — затрагивают приватность или могут повлиять на данные/операции пользователя. Требуют явного запроса и получения согласия пользователя во время выполнения (runtime). Например, android.permission.CAMERA, android.permission.READ_CONTACTS.
  3. Сигнатурные (Signature) разрешения — предоставляются автоматически, если запрашивающее приложение подписано тем же сертификатом, что и приложение, объявившее разрешение. Используются для безопасного взаимодействия между приложениями одного разработчика.
  4. Особые (Special) разрешения — например, SYSTEM_ALERT_WINDOW или WRITE_SETTINGS. Их запрос происходит по уникальным, нестандартным сценариям.

Синтаксис объявления в манифесте

Для объявления разрешения, которое ваше приложение будет использовать, используется элемент <uses-permission>. Он помещается на верхнем уровне манифеста, как дочерний для корневого элемента <manifest>.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">

    <!-- Запрос на использование разрешения -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
                     android:maxSdkVersion="28" /> <!-- Атрибут для обратной совместимости -->

    <application ...>
        ...
    </application>

</manifest>

Если вы создаете приложение-провайдер, которое предоставляет функциональность другим приложениям, и хотите защитить её, вы объявляете собственное разрешение с помощью элемента <permission>.

<manifest ...>
    <!-- Объявление собственного опасного разрешения -->
    <permission
        android:name="com.example.myapp.permission.ACCESS_PREMIUM_DATA"
        android:label="Доступ к премиум-данным"
        android:description="Разрешает доступ к закрытому премиум-контенту"
        android:protectionLevel="dangerous" />

    <application ...>
        ...
    </application>
</manifest>

Ключевые атрибуты элемента <permission>:

  • android:name — Уникальное имя разрешения (обычно с префиксом пакета).
  • android:protectionLevel — Уровень защиты: "normal", "dangerous", "signature" и др. Определяет, как система будет обрабатывать запрос.
  • android:label и android:description — Человекочитаемые строки, которые система показывает пользователю при запросе.

Запрос опасных разрешений во время выполнения (Runtime)

Объявления в манифесте недостаточно для опасных разрешений. Начиная с Android 6.0 (API 23), их необходимо запрашивать динамически в коде активности или фрагмента.

Базовый алгоритм:

  1. Проверить наличие разрешения с помощью ContextCompat.checkSelfPermission().
  2. Если разрешение не предоставлено, запросить его с помощью ActivityCompat.requestPermissions().
  3. Обработать результат запроса в переопределенном методе onRequestPermissionsResult().
// Пример в Activity или Fragment (Kotlin)
private val PERMISSION_REQUEST_CODE = 1001
private val REQUIRED_PERMISSION = Manifest.permission.ACCESS_FINE_LOCATION

fun checkOrRequestPermission() {
    // 1. Проверяем текущий статус
    when {
        ContextCompat.checkSelfPermission(this, REQUIRED_PERMISSION) == PackageManager.PERMISSION_GRANTED -> {
            // Разрешение уже есть, выполняем нужную операцию
            startLocationUpdates()
        }
        shouldShowRequestPermissionRationale(REQUIRED_PERMISSION) -> {
            // 2. Объясняем пользователю, зачем нужно разрешение (опционально)
            showRationaleDialog("Для отображения вашего местоположения на карте необходимо разрешение на доступ к геолокации.") {
                // После объяснения запрашиваем
                requestPermissions(arrayOf(REQUIRED_PERMISSION), PERMISSION_REQUEST_CODE)
            }
        }
        else -> {
            // 3. Запрашиваем разрешение напрямую
            requestPermissions(arrayOf(REQUIRED_PERMISSION), PERMISSION_REQUEST_CODE)
        }
    }
}

// 4. Обрабатываем ответ пользователя
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == PERMISSION_REQUEST_CODE) {
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            startLocationUpdates() // Разрешение получено
        } else {
            showMessage("Разрешение отклонено. Функционал локации недоступен.") // Разрешение отклонено
        }
    }
}

Современный подход с Activity Result API

В современных приложениях рекомендуется использовать Activity Result API (registerForActivityResult с контрактом ActivityResultContracts.RequestPermission), который является более декларативным и упрощает управление жизненным циклом.

// Объявление лаунчера для запроса разрешения
private val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
    if (isGranted) {
        startLocationUpdates()
    } else {
        showMessage("Разрешение необходимо для работы функции.")
    }
}

// Использование
fun requestPermission() {
    requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}

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

  • Запрашивайте разрешения контекстно, непосредственно перед выполнением операции, которая в них нуждается.
  • Всегда предоставляйте четкое объяснение (rationale), зачем приложению нужно разрешение. Используйте диалоги или другие UI-элементы.
  • Уважайте отказ пользователя. Ваше приложение должно корректно работать даже при отклонении разрешения, предлагая альтернативные функции или ограниченный режим.
  • Помните о группах разрешений. Запросив одно разрешение из группы (например, ACCESS_FINE_LOCATION), приложение получает доступ и к другим разрешениям в этой группе (например, ACCESS_COARSE_LOCATION), но для ясности кода их все равно лучше проверять отдельно.
  • Тестируйте сценарии как предоставления, так и отклонения разрешений, а также их отзыва в настройках системы.

Грамотная работа с разрешениями — это не только техническое требование, но и важная часть UX, напрямую влияющая на доверие пользователей и рейтинг приложения в магазине.

🛠️
aaaфывфывфвыф5 апр. 2026 г.

fff