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

Каждое приложение Android работает в «песочнице» с ограниченным доступом. If your app needs to use resources or information outside of its own sandbox, you can declare a runtime permission and set up a permission request that provides this access. Эти шаги являются частью рабочего процесса использования разрешений .

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

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

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

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

Для этого используйте контракт RequestPermission , включенный в библиотеку AndroidX, где вы разрешаете системе управлять кодом запроса разрешения за вас. Because using the RequestPermission contract simplifies your logic, it is the recommended solution when possible. Однако при необходимости вы также можете самостоятельно управлять кодом запроса как частью запроса на разрешение и включить этот код запроса в логику обратного вызова разрешения.

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

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

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

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

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

  1. In your activity or fragment's initialization logic, pass in an implementation of ActivityResultCallback into a call to 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);
}

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

As an alternative to allowing the system to manage the permission request code , you can manage the permission request code yourself. Для этого включите код запроса в вызов 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.
    }
}

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

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

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

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

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

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

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

    On Android 10 (API level 29) and higher, you must declare a foreground service type of location , as shown in the following code snippet. В более ранних версиях 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 геозон . Несколько примеров включают следующее:

  • В приложении для обмена семейным местоположением функция позволяет пользователям постоянно делиться своим местоположением с членами семьи.
  • В приложении 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>

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

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

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

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

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

В то же время ваше приложение должно уважать решение пользователя отказать в разрешении. Starting in Android 11 (API level 30), if the user taps Deny for a specific permission more than once during your app's lifetime of installation on a device, the user doesn't see the system permissions dialog if your app requests that permission again. Действие пользователя подразумевает «больше не спрашивать». В предыдущих версиях пользователи видели диалоговое окно системных разрешений каждый раз, когда ваше приложение запрашивало разрешение, если только они ранее не установили флажок или параметр «Больше не спрашивать».

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

В определенных ситуациях в разрешении может быть отказано автоматически без каких-либо действий со стороны пользователя. (A permission might be granted automatically as well.) It's important to not assume anything about automatic behavior. Каждый раз, когда вашему приложению требуется доступ к функциям, для которых требуется разрешение, убедитесь, что вашему приложению по-прежнему предоставлено это разрешение.

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

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

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

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 . Разрешения, которые были окончательно отклонены двойным выбором Запретить, помечаются 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

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

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

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

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