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

Кто не в теме, немного теории:

Как вы помните, до версии Android 6.0 все запрашиваемые разрешения отображались пользователю при установке приложения. И если пользователь не предоставлял приложению хотя бы одно разрешение из списка, приложение не устанавливалось.

Теперь все изменилось.

Начиная с Android API 23 разрешения поделили на обычные (normal) и опасные (dangerous).

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

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

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

Во вторых, в связи с этим изменилось поведение приложений при установке, и здесь возможны варианты.

Например, рассмотрим случай, когда устройство работает под управлением Android версии 5.1 или ниже, или целевая версия SDK в файле сборки приложения имеет значение 22 или ниже.

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

Если же устройство работает под управлением Android 6.0 или выше, или целевая версия SDK установлена на 23 или выше, то приложение может быть установлено без запросов разрешений. Но при этом ему будут предоставлены только обычные, безопасные разрешения.

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

Теперь давайте рассмотрим пример работы с разрешениями на практике.

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

Исходный код этого проекта вы можете посмотреть ниже:

В макете экрана одна кнопка.

Также нужен идентификатор для корневого view, это понадобится для работы снекбара.

Поскольку снекбар является компонентом библиотеки материального дизайна, добавьте ее в зависимости файла сборки модуля проекта.

Также нам понадобится разрешение на запись в память, пропишем его в манифесте.

Теперь рассмотрим код класса MainActivity.

Константа PERMISSION_REQUEST_CODE хранит произвольное значение, по которому в дальнейшем можно определить, на какой запрос разрешения вам пришел ответ.

Аналогично мы получали результат от activity, используя startActivityForResult, вспоминаем уроки по этой теме на нашем канале StartAndroid.

В методе onCreate создадим кнопку и присвоим ей слушатель нажатия.

В методе onClick проверяем логический результат метода hasPermissions, и вызываем метод создания папки, makeFolder. В этом методе мы просто создаем новый файл с именем fandroid и выводим несколько тостов с сообщениями, в зависимости от того, удалось или не удалось создать файл, или он уже создан.

Если же результат в методе onClick равен false, то вызываем метод requestPermissionWithRationale, который будет в свою очередь вызывать метод запроса разрешения. Мы перейдем к нему позже.

Ниже метод hasPermissions, который с помощью метода checkCallingOrSelfPermission в цикле проверяет предоставленные приложению разрешения и сравнивает их с тем, которое нам необходимо.

При отсутствии разрешения метод будет возвращать false, а при наличии разрешения — true.

В методе requestPerms создаем массив permissions , который содержит ссылки на константы класса Manifest с кодами разрешений. Поскольку используется массив, то одновременно можно запрашивать несколько разрешений.

После проверки версии устройства Запрос разрешения выполняет метод requestPermissions, которому мы передаем массив нужных нам разрешений и константу PERMISSION_REQUEST_CODE

После вызова этого метода пользователю отображается диалоговое окно с запросом разрешения.

Ответ пользователя приходит в метод onRequestPermissionsResult. Параметры requestCode и permissions содержат данные, которые вы передавали при запросе разрешений. Основные данные здесь несет массив grantResults, в котором находится информация о том, получены разрешения или нет. Каждому i-му элементу permissions соответствует i-ый элемент из grantResults.

Здесь мы обрабатываем ответ — проверяем, если разрешение предоставлено пользователем, о чем будет свидетельствовать ответ PERMISSION_GRANTED, то вызываем метод makeFolder, а если нет, то проверяем версию устройства,

и если она равна Андроид 6.0 или выше — проверяем, отказывался ли ранее пользователь предоставлять это разрешение. В таком случае метод с длинным названием shouldShowRequestPermissionRationale вернет нам true.

Одной из проблем может стать опция “Don’t ask again”, которая появляется при повторном запросе разрешения. При её выборе диалог запроса не будет больше появляться.

Метод shouldShowRequestPermissionRationale в таком случае будет возвращать false, а в onRequestPermissionsResult будет получен результат PERMISSION_DENIED — отказ в получении разрешения.

И останется единственный способ — попросить пользователя включить разрешение непосредственно через настройки приложения в разделе Permissions.

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

настройки открывает метод openApplicationSettings(), где мы создаем и отправляем соответствующий интент. В примере используются startActivityForResult и onActivityResult чтобы определить, что пользователь вернулся из activity настроек обратно в приложение и попробовать выполнить действие, которое нельзя было сделать без нужного разрешения.

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

это мы обыграем в методе requestPermissionWithRationale() — Запрос разрешения с обоснованием

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

Здесь же будет вызываться метод получения разрешения в случае первого запроса.

Теперь установим приложение на устройство и проверим его работу на эмуляторе с Андроид 6.0 (процесс тестирования смотрите в видео выше).

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

Если пользователь отказал, то приложение продолжает работу, но папка не создается.

При повторном нажатии кнопки всплывает снекбар с объяснением необходимости предоставления запроса и кнопкой, при нажатии которой вновь отображается запрос.

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

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

На этом все. Вопросы задавайте в комментариях к уроку.

Android runtime permissions пример реализации обновлено: Март 29, 2017 автором: Виталий Непочатов

Добавить комментарий