Запрос динамических разрешений

Каждое приложение Android работает в изолированной среде с ограниченным доступом. Если вашему приложению необходимо использовать ресурсы или информацию за пределами его собственной изолированной среды, вы можете объявить разрешение времени выполнения и настроить запрос разрешения, который предоставляет этот доступ. Эти шаги являются частью рабочего процесса использования разрешений .

Если вы объявляете какие-либо опасные разрешения и ваше приложение установлено на устройстве под управлением Android 6.0 (уровень API 23) или выше, вам необходимо запросить опасные разрешения во время выполнения, выполнив действия, описанные в этом руководстве.

Если вы не объявляете никаких опасных разрешений или если ваше приложение установлено на устройстве под управлением Android 5.1 (уровень API 22) или ниже, разрешения предоставляются автоматически, и вам не нужно выполнять какие-либо оставшиеся шаги на этой странице.

Основные принципы

Основные принципы запроса разрешений во время выполнения следующие:

  • Запрашивайте разрешение в контексте, когда пользователь начинает взаимодействовать с функцией, для которой оно требуется.
  • Не блокируйте пользователя. Всегда предоставляйте возможность отменить образовательный поток пользовательского интерфейса, например поток, который объясняет обоснование запроса разрешений.
  • Если пользователь отклоняет или отзывает разрешение, необходимое для работы функции, аккуратно снизьте функциональность приложения, чтобы пользователь мог продолжить его использование, возможно, отключив функцию, требующую разрешения.
  • Не предполагайте никакого поведения системы. Например, не предполагайте, что разрешения появляются в одной и той же группе разрешений . Группа разрешений просто помогает системе минимизировать количество системных диалогов, которые отображаются для пользователя, когда приложение запрашивает тесно связанные разрешения.

Рабочий процесс запроса разрешений

Прежде чем объявлять и запрашивать разрешения времени выполнения в своем приложении, оцените, нужно ли это вашему приложению . Вы можете реализовать множество вариантов использования в своем приложении, таких как съемка фотографий, приостановка воспроизведения мультимедиа и отображение релевантной рекламы, без необходимости объявлять какие-либо разрешения.

Если вы пришли к выводу, что вашему приложению необходимо объявлять и запрашивать разрешения во время выполнения, выполните следующие действия:

  1. В файле манифеста вашего приложения укажите разрешения , которые может потребоваться запросить вашему приложению.
  2. Разработайте UX вашего приложения так, чтобы определенные действия в вашем приложении были связаны с определенными разрешениями времени выполнения. Сообщите пользователям, какие действия могут потребовать от них предоставления разрешения вашему приложению на доступ к личным данным пользователя.
  3. Подождите, пока пользователь вызовет задачу или действие в вашем приложении, требующее доступа к определенным личным данным пользователя. В это время ваше приложение может запросить разрешение времени выполнения, необходимое для доступа к этим данным.
  4. Проверьте, предоставил ли пользователь разрешение на выполнение , которое требуется вашему приложению. Если да, ваше приложение может получить доступ к личным данным пользователя. Если нет, перейдите к следующему шагу.

    Вы должны проверять наличие у вас разрешения каждый раз, когда выполняете операцию, требующую этого разрешения.

  5. Проверьте, должно ли ваше приложение показывать пользователю обоснование , объясняющее, почему вашему приложению нужно, чтобы пользователь предоставил определенное разрешение времени выполнения. Если система определяет, что ваше приложение не должно показывать обоснование, перейдите непосредственно к следующему шагу, не показывая элемент пользовательского интерфейса.

    Однако, если система определяет, что ваше приложение должно показать обоснование, представьте обоснование пользователю в элементе пользовательского интерфейса. В этом обосновании четко объясните, к каким данным ваше приложение пытается получить доступ и какие преимущества приложение может предоставить пользователю, если он предоставит разрешение на выполнение. После того, как пользователь подтвердит обоснование, перейдите к следующему шагу.

  6. Запросите разрешение времени выполнения , которое требуется вашему приложению для доступа к личным данным пользователя. Система отобразит запрос разрешения времени выполнения, такой как показанный на странице обзора разрешений .

  7. Проверьте ответ пользователя — решил ли он предоставить или отклонить разрешение на выполнение.

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

На рисунке 1 показан рабочий процесс и набор решений, связанных с этим процессом:

Рисунок 1. Схема, показывающая рабочий процесс объявления и запроса разрешений времени выполнения на Android.

Определите, было ли уже предоставлено вашему приложению разрешение

Чтобы проверить, предоставил ли пользователь вашему приложению определенное разрешение, передайте это разрешение в метод ContextCompat.checkSelfPermission() . Этот метод возвращает либо PERMISSION_GRANTED , либо PERMISSION_DENIED в зависимости от того, имеет ли ваше приложение разрешение.

Объясните, почему вашему приложению необходимо разрешение

Диалоговое окно разрешений, отображаемое системой при вызове requestPermissions() сообщает, какие разрешения требуются вашему приложению, но не говорит, почему. В некоторых случаях пользователь может счесть это странным. Хорошая идея — объяснить пользователю, почему вашему приложению требуются разрешения, прежде чем вызывать requestPermissions() .

Исследования показывают, что пользователи гораздо более комфортно чувствуют себя с запросами разрешений, если знают, зачем они нужны приложению, например, нужно ли разрешение для поддержки основной функции приложения или для рекламы. В результате, если вы используете только часть вызовов API, которые попадают в группу разрешений, полезно явно перечислить, какие из этих разрешений вы используете и почему. Например, если вы используете только приблизительное местоположение, сообщите об этом пользователю в описании вашего приложения или в справочных статьях о вашем приложении.

При определенных условиях также полезно сообщать пользователям о доступе к конфиденциальным данным в режиме реального времени. Например, если вы получаете доступ к камере или микрофону, хорошей идеей будет сообщить об этом пользователю с помощью значка уведомления где-нибудь в вашем приложении или в области уведомлений (если приложение работает в фоновом режиме), чтобы не создавалось впечатления, что вы тайно собираете данные.

В конечном счете, если вам нужно запросить разрешение, чтобы что-то работало в вашем приложении, но причина этого не ясна пользователю, найдите способ сообщить пользователю, почему вам нужны самые конфиденциальные разрешения.

Если метод ContextCompat.checkSelfPermission() возвращает PERMISSION_DENIED , вызовите shouldShowRequestPermissionRationale() . Если этот метод возвращает true , покажите пользователю образовательный пользовательский интерфейс. В этом пользовательском интерфейсе опишите, почему функция, которую пользователь хочет включить, требует определенного разрешения.

Кроме того, если ваше приложение запрашивает разрешение, связанное с местоположением, микрофоном или камерой, подумайте о том, чтобы объяснить, зачем вашему приложению нужен доступ к этой информации.

Запросить разрешения

После того, как пользователь просматривает образовательный UI или возвращаемое значение shouldShowRequestPermissionRationale() указывает, что вам не нужно показывать образовательный UI, запросите разрешение. Пользователи видят системный диалог разрешений, где они могут выбрать, предоставлять ли определенное разрешение вашему приложению.

Для этого используйте контракт RequestPermission , включенный в библиотеку AndroidX, где вы позволяете системе управлять кодом запроса разрешения для вас. Поскольку использование контракта RequestPermission упрощает вашу логику, это рекомендуемое решение, когда это возможно. Однако при необходимости вы также можете управлять кодом запроса самостоятельно как частью запроса разрешения и включать этот код запроса в вашу логику обратного вызова разрешения.

Разрешить системе управлять кодом запроса разрешения

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

Затем вы можете использовать один из следующих классов:

  • Чтобы запросить отдельное разрешение, используйте RequestPermission .
  • Чтобы запросить несколько разрешений одновременно, используйте RequestMultiplePermissions .

Следующие шаги показывают, как использовать контракт RequestPermission . Процесс почти такой же для контракта RequestMultiplePermissions .

  1. В логике инициализации вашей активности или фрагмента передайте реализацию ActivityResultCallback в вызов registerForActivityResult() . ActivityResultCallback определяет, как ваше приложение обрабатывает ответ пользователя на запрос разрешения.

    Сохраните ссылку на возвращаемое значение registerForActivityResult() , которое имеет тип ActivityResultLauncher .

  2. Чтобы при необходимости отобразить диалоговое окно системных разрешений, вызовите метод launch() для экземпляра ActivityResultLauncher , сохраненного на предыдущем шаге.

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

    Примечание: Ваше приложение не может настраивать диалог, который появляется при вызове launch() . Чтобы предоставить пользователю больше информации или контекста, измените пользовательский интерфейс вашего приложения, чтобы пользователям было проще понять, почему функция в вашем приложении требует определенного разрешения. Например, вы можете изменить текст на кнопке, которая включает функцию.

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

Следующий фрагмент кода показывает, как обрабатывать ответ о разрешениях:

Котлин

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
    registerForActivityResult(RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // feature requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    }

Ява

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher, as an instance variable.
private ActivityResultLauncher<String> requestPermissionLauncher =
    registerForActivityResult(new RequestPermission(), isGranted -> {
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // feature requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    });

А этот фрагмент кода демонстрирует рекомендуемый процесс проверки наличия разрешения и запроса разрешения у пользователя при необходимости:

Котлин

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user continue
        // using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        // The registered ActivityResultCallback gets the result of this request.
        requestPermissionLauncher.launch(
                Manifest.permission.REQUESTED_PERMISSION)
    }
}

Ява

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    // The registered ActivityResultCallback gets the result of this request.
    requestPermissionLauncher.launch(
            Manifest.permission.REQUESTED_PERMISSION);
}

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

В качестве альтернативы разрешению системе управлять кодом запроса разрешения , вы можете управлять кодом запроса разрешения самостоятельно. Для этого включите код запроса в вызов requestPermissions() .

Следующий фрагмент кода демонстрирует, как запросить разрешение с помощью кода запроса:

Котлин

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
        performAction(...)
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user continue
        // using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        requestPermissions(CONTEXT,
                arrayOf(Manifest.permission.REQUESTED_PERMISSION),
                REQUEST_CODE)
    }
}

Ява

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    requestPermissions(CONTEXT,
            new String[] { Manifest.permission.REQUESTED_PERMISSION },
            REQUEST_CODE);
}

После того, как пользователь отвечает на диалог системных разрешений, система вызывает реализацию onRequestPermissionsResult() вашего приложения. Система передает ответ пользователя на диалог разрешений, а также код запроса, который вы определили, как показано в следующем фрагменте кода:

Котлин

override fun onRequestPermissionsResult(requestCode: Int,
        permissions: Array<String>, grantResults: IntArray) {
    when (requestCode) {
        PERMISSION_REQUEST_CODE -> {
            // If request is cancelled, the result arrays are empty.
            if ((grantResults.isNotEmpty() &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            } else {
                // Explain to the user that the feature is unavailable because
                // the feature requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return
        }

        // Add other 'when' lines to check for other
        // permissions this app might request.
        else -> {
            // Ignore all other requests.
        }
    }
}

Ява

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
        int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            }  else {
                // Explain to the user that the feature is unavailable because
                // the feature requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return;
        }
        // Other 'case' lines to check for other
        // permissions this app might request.
    }
}

Запросить разрешение на местоположение

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

Расположение на переднем плане

Если ваше приложение содержит функцию, которая делится или получает информацию о местоположении только один раз или в течение определенного периода времени, то эта функция требует доступа к местоположению на переднем плане. Вот некоторые примеры:

  • В навигационном приложении появилась функция, позволяющая пользователям получать пошаговые инструкции.
  • В приложении для обмена сообщениями появилась функция, позволяющая пользователям делиться своим текущим местоположением с другими пользователями.

Система считает, что ваше приложение использует данные о местоположении на переднем плане, если функция вашего приложения получает доступ к текущему местоположению устройства в одной из следующих ситуаций:

  • Видна активность, принадлежащая вашему приложению.
  • Ваше приложение запускает службу переднего плана. Когда служба переднего плана запущена, система повышает осведомленность пользователя, показывая постоянное уведомление. Ваше приложение сохраняет доступ, когда оно находится в фоновом режиме, например, когда пользователь нажимает кнопку «Домой» на своем устройстве или выключает дисплей своего устройства.

    На Android 10 (уровень API 29) и выше необходимо объявить тип службы переднего плана location , как показано в следующем фрагменте кода. На более ранних версиях Android рекомендуется объявить этот тип службы переднего плана.

    <!-- Recommended for Android 9 (API level 28) and lower. -->
    <!-- Required for Android 10 (API level 29) and higher. -->
    <service
        android:name="MyNavigationService"
        android:foregroundServiceType="location" ... >
        <!-- Any inner elements go here. -->
    </service>

Вы заявляете о необходимости определения местоположения на переднем плане, когда ваше приложение запрашивает разрешение ACCESS_COARSE_LOCATION или разрешение ACCESS_FINE_LOCATION , как показано в следующем фрагменте:

<manifest ... >
  <!-- Include this permission any time your app needs location information. -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

  <!-- Include only if your app benefits from precise location access. -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

Фоновое местоположение

Приложению требуется фоновый доступ к местоположению, если функция в приложении постоянно делится местоположением с другими пользователями или использует API Geofencing . Вот несколько примеров:

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

Система считает, что ваше приложение использует фоновое местоположение, если оно обращается к текущему местоположению устройства в любой ситуации, отличной от описанной в разделе о переднем плане местоположения . Точность фонового местоположения такая же, как и точность переднего плана местоположения , которая зависит от разрешений на местоположение, которые объявляет ваше приложение.

На Android 10 (уровень API 29) и выше необходимо объявить разрешение ACCESS_BACKGROUND_LOCATION в манифесте вашего приложения, чтобы запросить доступ к местоположению в фоновом режиме во время выполнения. В более ранних версиях Android, когда ваше приложение получает доступ к местоположению в фоновом режиме, оно автоматически получает и доступ к местоположению в фоновом режиме.

<manifest ... >
  <!-- Required only when requesting background location access on
       Android 10 (API level 29) and higher. -->
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

Обработка отказа в разрешении

Если пользователь отклоняет запрос на разрешение, ваше приложение должно помочь пользователям понять последствия отклонения разрешения. В частности, ваше приложение должно информировать пользователей о функциях, которые не работают из-за отсутствия разрешения. При этом помните о следующих рекомендациях:

  • Направляйте внимание пользователя. Выделите определенную часть пользовательского интерфейса вашего приложения, где функциональность ограничена, поскольку у вашего приложения нет необходимого разрешения. Вот примеры того, что вы можете сделать:

    • Показывать сообщение там, где должны были появиться результаты или данные функции.
    • Отобразить другую кнопку, содержащую значок ошибки и цвет.
  • Будьте конкретны. Не показывайте общее сообщение. Вместо этого дайте понять, какие функции недоступны, потому что у вашего приложения нет необходимого разрешения.

  • Не блокируйте пользовательский интерфейс. Другими словами, не отображайте полноэкранное предупреждающее сообщение, которое вообще не позволяет пользователям продолжать использовать ваше приложение.

В то же время ваше приложение должно уважать решение пользователя отклонить разрешение. Начиная с Android 11 (API уровня 30), если пользователь нажимает «Отклонить» для определенного разрешения более одного раза в течение жизненного цикла установки вашего приложения на устройстве, пользователь не видит диалоговое окно системных разрешений, если ваше приложение снова запрашивает это разрешение. Действие пользователя подразумевает «больше не спрашивать». В предыдущих версиях пользователи видели диалоговое окно системных разрешений каждый раз, когда ваше приложение запрашивало разрешение, если они ранее не выбрали флажок или опцию «больше не спрашивать».

Если пользователь отклоняет запрос на разрешение более одного раза, это считается постоянным отказом. Очень важно запрашивать у пользователей разрешения только тогда, когда им нужен доступ к определенной функции, в противном случае вы можете непреднамеренно потерять возможность повторно запрашивать разрешения.

В определенных ситуациях разрешение может быть отклонено автоматически, без каких-либо действий со стороны пользователя. (Разрешение может быть предоставлено автоматически.) Важно не предполагать ничего об автоматическом поведении. Каждый раз, когда вашему приложению требуется доступ к функциональным возможностям, требующим разрешения, проверяйте, что вашему приложению по-прежнему предоставлено это разрешение.

Чтобы обеспечить наилучший пользовательский опыт при запросе разрешений для приложений, см. также Рекомендации по предоставлению разрешений для приложений .

Проверяйте статус отказа при тестировании и отладке

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

adb shell dumpsys package PACKAGE_NAME

Где PACKAGE_NAME — имя проверяемого пакета.

Вывод команды содержит разделы, которые выглядят следующим образом:

...
runtime permissions:
  android.permission.POST_NOTIFICATIONS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
  android.permission.ACCESS_FINE_LOCATION: granted=false, flags=[ USER_SET|USER_FIXED|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
  android.permission.BLUETOOTH_CONNECT: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
...

Разрешения, которые были отклонены пользователем один раз, помечаются USER_SET . Разрешения, которые были отклонены навсегда путем выбора Deny дважды, помечаются USER_FIXED .

Чтобы убедиться, что тестировщики видят диалог запроса во время тестирования, сбросьте эти флаги, когда закончите отладку своего приложения. Для этого используйте команду:

adb shell pm clear-permission-flags PACKAGE_NAME PERMISSION_NAME user-set user-fixed

PERMISSION_NAME — имя разрешения, которое вы хотите сбросить.

Чтобы просмотреть полный список разрешений приложений Android, посетите страницу справки по API разрешений .

Одноразовые разрешения

Опция «Только в этот раз» — вторая из трех кнопок в диалоговом окне.
Рисунок 2. Системное диалоговое окно, которое появляется, когда приложение запрашивает одноразовое разрешение.

Начиная с Android 11 (уровень API 30), всякий раз, когда ваше приложение запрашивает разрешение, связанное с местоположением, микрофоном или камерой, диалоговое окно разрешений, отображаемое для пользователя, содержит параметр « Только в этот раз» , как показано на рисунке 2. Если пользователь выбирает этот параметр в диалоговом окне, вашему приложению предоставляется временное одноразовое разрешение .

Затем ваше приложение может получить доступ к соответствующим данным в течение определенного периода времени, который зависит от поведения вашего приложения и действий пользователя:

  • Пока активность вашего приложения видна, ваше приложение может получить доступ к данным.
  • Если пользователь переведет ваше приложение в фоновый режим, оно сможет продолжить получать доступ к данным в течение короткого периода времени.
  • Если вы запускаете службу переднего плана, пока активность видна, а затем пользователь переводит ваше приложение в фоновый режим, ваше приложение может продолжать получать доступ к данным до тех пор, пока служба переднего плана не остановится.

Процесс приложения завершается при отзыве разрешения

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

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

Сбросить неиспользуемые разрешения

Android предоставляет несколько способов сброса неиспользуемых разрешений среды выполнения до состояния по умолчанию, когда они отклонены:

Удалить доступ к приложению

На Android 13 (API уровня 33) и выше вы можете удалить доступ вашего приложения к разрешениям времени выполнения, которые больше не требуются вашему приложению. При обновлении приложения выполните этот шаг, чтобы пользователи с большей вероятностью поняли, почему ваше приложение продолжает запрашивать определенные разрешения. Эти знания помогают повысить доверие пользователей к вашему приложению.

Чтобы удалить доступ к разрешению времени выполнения, передайте имя этого разрешения в revokeSelfPermissionOnKill() . Чтобы удалить доступ к группе разрешений времени выполнения одновременно, передайте коллекцию имен разрешений в revokeSelfPermissionsOnKill() . Процесс удаления разрешения происходит асинхронно и завершает все процессы, связанные с UID вашего приложения.

Чтобы система удалила доступ вашего приложения к разрешениям, все процессы, привязанные к вашему приложению, должны быть завершены. Когда вы вызываете API, система определяет, когда безопасно завершить эти процессы. Обычно система ждет, пока ваше приложение не проведет продолжительное время в фоновом режиме, а не на переднем плане.

Чтобы сообщить пользователю, что вашему приложению больше не требуется доступ к определенным разрешениям времени выполнения, покажите диалоговое окно при следующем запуске пользователем вашего приложения. Этот диалог может включать список разрешений.

Автоматический сброс разрешений неиспользуемых приложений

Если ваше приложение предназначено для Android 11 (уровень API 30) или выше и не используется в течение нескольких месяцев, система защищает пользовательские данные, автоматически сбрасывая конфиденциальные разрешения времени выполнения, которые пользователь предоставил вашему приложению. Узнайте больше в руководстве о спящем режиме приложения .

При необходимости запросите возможность стать обработчиком по умолчанию

Некоторые приложения зависят от доступа к конфиденциальной информации пользователя, связанной с журналами вызовов и SMS-сообщениями. Если вы хотите запросить разрешения, относящиеся к журналам вызовов и SMS-сообщениям, и опубликовать свое приложение в Play Store, вы должны предложить пользователю установить ваше приложение в качестве обработчика по умолчанию для основной системной функции, прежде чем запрашивать эти разрешения времени выполнения.

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

Предоставьте все разрешения на выполнение для целей тестирования.

Чтобы автоматически предоставить все разрешения времени выполнения при установке приложения на эмуляторе или тестовом устройстве, используйте параметр -g для команды adb shell install , как показано в следующем фрагменте кода:

adb shell install -g PATH_TO_APK_FILE

Дополнительные ресурсы

Дополнительную информацию о разрешениях можно найти в следующих статьях:

Чтобы узнать больше о запросе разрешений, ознакомьтесь с примерами разрешений.

Вы также можете выполнить эту лабораторную работу, демонстрирующую лучшие практики обеспечения конфиденциальности .