How to request permission android

Android permissions

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

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

Полный список существующих разрешений можно посмотреть здесь. Характеристика Protection level подскажет насколько опасно это разрешение. А здесь можно сразу просмотреть весь список normal разрешений.

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

Вот пример манифеста с разрешениями:

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

В этом материале мы подробно рассмотрим, как происходит это подтверждение.

До Android 6

До выхода Android 6 все было просто и легко. Когда пользователь устанавливал приложение с манифестом, который мы рассмотрели чуть выше, то он видел такой экран:

Система показывает разрешения, которые были прописаны в манифесте. Сначала те, которые могут быть опасными с точки зрения приватности (отправка смс, доступ к камере/местоположению/контактам), а затем — обычные (интернет, bluetooth).

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

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

Если же в манифесте не указать разрешение READ_CONTACTS, то его не будет и в списке тех разрешений, которые подтверждает пользователь. Соответственно, система не предоставит этому приложению доступ к контактам. И при попытке получить список контактов, будет ошибка:
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2

Android 6

С выходом Android 6 механизм подтверждения поменялся. Теперь при установке приложения пользователь больше не видит списка запрашиваемых разрешений. Приложение автоматически получает все требуемые normal разрешения, а dangerous разрешения необходимо будет программно запрашивать в процессе работы приложения.

Т.е. теперь недостаточно просто указать в манифесте, что вам нужен, например, доступ к контактам. Когда вы в коде попытаетесь запросить список контактов, то получите ошибку SecurityException: Permission Denial. Потому что вы явно не запрашивали это разрешение, и пользователь его не подтверждал.

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

Давайте посмотрим, как это выглядит на практике.

Проверка текущего статуса разрешения выполняется методом checkSelfPermission

На вход метод требует Context и название разрешения. Он вернет константу PackageManager.PERMISSION_GRANTED (если разрешение есть) или PackageManager.PERMISSION_DENIED (если разрешения нет).

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

Если разрешения нет, то нам надо его запросить. Это выполняется методом requestPermissions. Схема его работы похожа на метод startActivityForResult. Мы вызываем метод, передаем ему данные и request code, а ответ потом получаем в определенном onResult методе.

Добавим запрос разрешения к уже имеющейся проверке.

Проверяем разрешение READ_CONTACTS. Если оно есть, то читаем контакты. Иначе запрашиваем разрешение READ_CONTACTS методом requestPermissions. На вход метод требует Activity, список требуемых разрешений, и request code. Обратите внимание, что для разрешений используется массив. Т.е. вы можете запросить сразу несколько разрешений.

Читайте также:  Android failed to resolve dependency

После вызова метода requestPermissions система покажет следующий диалог

Здесь будет отображено разрешение, которое мы запросили методом requestPermissions. Пользователь может либо подтвердить его (ALLOW), либо отказать (DENY). Если будет запрошено сразу несколько разрешений, то на каждое из них будет показан отдельный диалог. И пользователь может какие-то разрешения подтвердить, а какие-то нет.

Решение пользователя мы получим в методе onRequestPermissionsResult

Проверяем, что requestСode тот же, что мы указывали в requestPermissions. В массиве permissions придут название разрешений, которые мы запрашивали. В массиве grantResults придут ответы пользователя на запросы разрешений.

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

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

Далее поговорим про некоторые дополнительные возможности, нюансы и прочие мелочи.

Манифест

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

Всегда проверяйте разрешение

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

Don’t ask again

Когда вы первый раз делаете запрос на какое-либо разрешение, пользователь может отказать. При последующих запросах этого же разрешения, в диалоге появится чекбокс Don’t ask again

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

Объяснение для пользователя

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

Диалог, который показывается при запросе разрешения, — системный, вы не можете менять его содержимое и добавлять туда свой текст. Но вы можете сделать свой диалог или что-то подобное и показать его перед тем, как будете делать запрос разрешения.

Есть метод shouldShowRequestPermissionRationale, который может быть полезен в данной ситуации. Передаете ему название разрешения, а он вам в виде boolean ответит, надо ли показывать объяснение для пользователя.

Т.е. вы сначала проверяете наличие разрешения. Если его нет, то вызываете shouldShowRequestPermissionRationale, чтобы решить, надо ли показывать объяснение пользователю. Если не надо, то делаете запрос разрешения. А если надо, то показываете ваш диалог с объяснением, а после этого диалога делаете запрос разрешения.

Алгоритм работы метода shouldShowRequestPermissionRationale прост.

Если вы еще ни разу не запрашивали это разрешение, то он вернет false. Т.е. перед первым запросом разрешения ничего объяснять не надо.

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

Если пользователь ставил галку Don’t ask again, то метод вернет false. Запрос полномочий все равно не будет выполнен. Объяснять что-то не имеет смысла.

Разумеется, вы можете показывать дополнительную информацию согласно вашим правилам и не использовать метод shouldShowRequestPermissionRationale.

Группы

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

Например, разрешения READ_CONTACTS и WRITE_CONTACTS принадлежат группе CONTACTS. И если пользователь уже подтверждал разрешение на READ_CONTACTS, то при проверке WRITE_CONTACTS вы получите PERMISSION_GRANTED.

Android 6 и targetSdkVersion 23

Схема работы разрешений зависит от версии Android, на которой запущено приложение и от параметра targetSdkVersion приложения.

Новая схема будет работать, если версия Android >= 6 И targetSdkVersion >= 23.

В остальных случаях, т.е. когда targetSdkVersion

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

Читайте также:  Framaroot для всех андроид

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Handle Runtime Permissions in Android

  • From beginning with Android 6.0 Marshmallow (API LEVEL 23)(
    Marshmallow was released on October 5, 2015 ), Google has introduced a new runtime permission model.
  • According to this model users are not prompted for permission at the time of installing the app, rather developers need to check for and request permission at runtime (i.e. The particular permission must required before performing any action)
  • Users can then allow or deny the permission, users can also grant or revoke permission anytime from settings even if the app is already installed.
  • Developers have to handle all the use cases. If not handled properly, it can cause application crashes.

Now here we’ll look into the android runtime permissions and handle them.

Types of Runtime Permissions

Android defines basically three types of permissions:

  1. Normal Permissions
  2. Signature Permissions
  3. Dangerous Permissions

Both Normal and Dangerous permissions must be defined in the Manifest file. But only Dangerous permissions are checked at runtime, Normal permissions are not.

Normal Permissions

Some permissions are automatically granted to the application. Just we need to declare those permissions in AndroidManifest.xml and it will work fine. Those permissions are called Normal Permissions. An example of a normal permission is INTERNET .

Normal Permissions are automatically granted to the application.

Signature Permissions

A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission. If the certificates match, the system automatically grants the permission without notifying the user or asking for the user’s explicit approval.

Dangerous Permissions

Some permissions may affect the users private information, or could potentially affect his data or the operation of other application are called Dangerous Permissions. For example, the ability to read the user’s contacts is a dangerous permission. Some other examples are CONTACTS , CAMERA , CALENDAR, LOCATION , PHONE , STORAGE , SENSORS , MICROPHONE, etc.

Dangerous permissions must be granted by the user at runtime to the app.

Dangerous permissions are grouped into categories that make it easier for the user to understand what they are allowing the application to do. If any permission in a Permission Group is granted. Another permission in the same group will be automatically granted as well. For example , once WRITE_CONTACTS is granted, application will also grant READ_CONTACTS and GET_ACCOUNTS as all three permissions in the same group.

Before Marshmallow (API 23)

Before Marshmallow (API 23) all the requested permissions are presented to the user before installing the application. If the user denies a required permission, the related application cannot be installed. And there was no way to grant or deny any permission after installation.

Workflow of Runtime Permission

Here is the workflow of runtime permission to open camera in android.

First of all we check the SDK Version. If SDK version is less than 23(Marshmallow) then we don’t need to ask for permission as Runtime Permission started from Marshmallow. And we can open camera.

If SDK version is equal to or greater than 23, then we check the permission is already granted or not by calling contextCompat.checkSelfPermission(). If permission is granted then we can open camera. If the permission is not granted we must request for the permission to the user. But in this case, we have to handle three cases.

Case 1:

The permission never asked before.

Case 2:

The permission asked before but user denied without checking ‘Never ask again’.

Case 3:

The permission asked before but user denied with checking ‘Never ask again’.

Only a method can handle our three cases . The method is shouldShowRequestPermissionRationale. the method returns a boolean value.

This method returns true if the the permission asked before but the user denied without checking ‘Never ask again’. which matches our Case 2.

But it will return false in two cases.

  • If the permission is requested first time. Which matches our Case 1.
  • If the permission asked before but the user denied with checking ‘Never ask again’. Which matches our Case 3.
Читайте также:  Zinnia journal and planner для андроид

So here only shouldShowRequestPermissionRationale method can match our three cases. Now just need to solve them with help of this method.

Solution of Case 2:

Solution of case 2 is very easy. Because the method shouldShowRequestPermissionRationale returns true only when the permission asked before but the user denied without checking ‘Never ask again’. So we can just give an explanation about why the app needs this permission. And if the user agree to our explanation we can request for permission again. That’s it.

Solution of Case 1 and Case 3:

But solution of case 1 and case 2 is little tricky. Because we know the method shouldShowRequestPermissionRationale returns false if the permission never asked before (Case 1) or the permission asked but the user denied with checking ‘Never ask again’ (Case 3). But we have to catch this two cases. How can we do that ?

Yes we can do this with the help of Shared Preferences , We can just put a flag on Shared Preferences for checking weather the permission is being asked first time or not. And the problem is solved. By this following code we can put our flag on Shared Preferences.

In firstTimeAsking, we just put a boolean flag with the permission string as key.

In isFirstTimeAsking, we get the value associated with the permission string and return it.

Notice that we set the default value as true. That’s why if the key is not in the preference file or even if the file itself is not created, the android framework will automatically create a file with the name we gave and will return the default value we set.

We will call this method every time when a permission request is required but after first call, we set the flag as false using firstTimeAsking(permission, false).

Here is the code.

We can put all these logic in a method and use a callback to get which case we should handle now. The code would be like this.

Now all the three cases are solved.

If you still getting confused on how to use it and you want to be more clear then see this full project Runtime Permission in Android in Github.

Handle the permissions request response

When the user responds to your app’s permission request, the system invokes your app’s onRequestPermissionsResult() method. So you have to override that method to find out whether the permission was granted or denied. And the same request code that you passed to requestPermissions() method is also passed to the callback. For deeper understanding, you see the following callback method:

Asking for Multiple Permissions at a time

Permissions from Fragment

In Fragment, you can ask for permission in two ways

Way 1:

In this way you will get permission result on onRequestPermissionsResult method of the activity not the fragment. That’s why you have to override the onRequestPermissionsResult method of the activity instead of Fragment.

Way 2:

In this way you will get permission result on onRequestPermissionsResult() method of fragment. But you must call

in activity’s onRequestPermissionsResult() method.

So the best way is

1) In fragment, ask permission just using

2) In activity’s onRequestPermissionsResult, call

so it will pass the result to fragment. Mind it this is the most important call and you must do it.

3) Now in fragment’s onRequestPermissionsResult, write the code that you want to handle the result.

ContextCompat vs AcitvityCompat

ActivityCompat is a subclass (child) of ContextCompat so you can pass either one whenever object of ContextCompat class is required.

This method is used simply for checking whether you are having requested permission available for your app or not.

This method is used for requesting permissions.

Shorten source code with 3rd Party Library

There are many popular permissions libraries that you can use for shorten your code. Some of them are given below:

I hope this article will helpful for you. Feel free to give your feedback in comment below: I would be very happy to get new suggestions.

Источник

Оцените статью