How to Determine if User Clicked Never Ask Again During Ask for Permission
Overview
By default, an Android app starts with zero permissions granted to information technology. When the app needs to use any of the protected features of the device (sending network requests, accessing the camera, sending an SMS, etc) it must obtain the appropriate permission from the user to do so.
Before Marshmallow, permissions were handled at install-time and specified in the AndroidManifest.xml
within the projection. Full list of permissions tin be found hither. After Marshmallow, permissions must at present be requested at runtime before being used. In that location are a number of libraries bachelor to make runtime permissions easier. If y'all to get started quickly, cheque out our guide on managing runtime permissions with PermissionsDispatcher.
Permissions before Marshmallow
Permissions were much simpler before Marshmallow (API 23). All permissions were handled at install-time. When a user went to install an app from the Google Play Shop, the user was presented a list of permissions that the app required (some people referred to this as a "wall of permissions". The user could either have all the permissions and proceed to install the app or decide not to install the app. Information technology was an all or nada arroyo. There was no way to grant only certain permissions to the app and no manner for the user to revoke sure permissions after the app was installed.
Example of pre-Marshmallow permissions requested by the Dropbox app:
For an app developer, permissions were very simple. To request one of the many permissions, simply specify it in the AndroidManifest.xml
:
For example, an application that needs to read the user'south contacts would add together the post-obit to it's AndroidManifest.xml
:
<manifest xmlns:android= "http://schemas.android.com/apk/res/android" package= "com.android.app.myapp" > <uses-permission android:name= "android.permission.READ_CONTACTS" /> ... </manifest>
That's all there was to it. The user had no way of irresolute permissions, fifty-fifty after installing the app. This made it easy for developers to deal with permissions, just wasn't the all-time user feel.
Permission Updates in Marshmallow
Marshmallow brought big changes to the permissions model. It introduced the concept of runtime permissions. These are permissions that are requested while the app is running (instead of before the app is installed). These permission can then exist immune or denied by the user. For approved permissions, these tin also be revoked at a later on fourth dimension.
This means there are a couple more things to consider when working with permissions for a Marshmallow app. Continue in mind that your targetSdkVersion
must exist >= 23
and your emulator / device must be running Marshmallow to meet the new permissions model. If this isn't the case, run across the backwards compatibility department to understand how permissions will behave on your configuration.
Normal Permissions
When you lot demand to add a new permission, first check this page to see if the permission is considered a PROTECTION_NORMAL
permission. In Marshmallow, Google has designated certain permissions to be "safe" and called these "Normal Permissions". These are things like ACCESS_NETWORK_STATE
, Net
, etc. which tin't do much damage. Normal permissions are automatically granted at install time and never prompt the user asking for permission.
Important: Normal Permissions must exist added to the AndroidManifest
:
<manifest xmlns:android= "http://schemas.android.com/apk/res/android" package= "com.android.app.myapp" > <uses-permission android:name= "android.permission.INTERNET" /> ... </manifest>
Runtime Permissions
If the permission you need to add isn't listed nether the normal permissions, you'll demand to deal with "Runtime Permissions". Runtime permissions are permissions that are requested as they are needed while the app is running. These permissions volition show a dialog to the user, similar to the following one:
The first footstep when calculation a "Runtime Permission" is to add together it to the AndroidManifest
:
<manifest xmlns:android= "http://schemas.android.com/apk/res/android" package= "com.codepath.androidpermissionsdemo" > <uses-permission android:name= "android.permission.READ_CONTACTS" /> ... </manifest>
Side by side, you'll need to initiate the permission request and handle the result. The following code shows how to exercise this in the context of an Activity
, simply this is besides possible from inside a Fragment
.
// MainActivity.coffee public class MainActivity extends AppCompatActivity { @Override protected void onCreate ( Parcel savedInstanceState ) { super . onCreate ( savedInstanceState ); setContentView ( R . layout . activity_main ); // In an bodily app, you'd want to request a permission when the user performs an action // that requires that permission. getPermissionToReadUserContacts (); } // Identifier for the permission request private static final int READ_CONTACTS_PERMISSIONS_REQUEST = i ; // Called when the user is performing an action which requires the app to read the // user'due south contacts public void getPermissionToReadUserContacts () { // 1) Use the support library version ContextCompat.checkSelfPermission(...) to avoid // checking the build version since Context.checkSelfPermission(...) is only available // in Marshmallow // 2) Ever check for permission (even if permission has already been granted) // since the user can revoke permissions at any time through Settings if ( ContextCompat . checkSelfPermission ( this , Manifest . permission . READ_CONTACTS ) != PackageManager . PERMISSION_GRANTED ) { // The permission is NOT already granted. // Check if the user has been asked about this permission already and denied // it. If so, we desire to give more explanation nigh why the permission is needed. if ( shouldShowRequestPermissionRationale ( Manifest . permission . READ_CONTACTS )) { // Show our own UI to explicate to the user why we need to read the contacts // earlier actually requesting the permission and showing the default UI } // Fire off an async request to actually go the permission // This will evidence the standard permission request dialog UI requestPermissions ( new Cord []{ Manifest . permission . READ_CONTACTS }, READ_CONTACTS_PERMISSIONS_REQUEST ); } } // Callback with the request from calling requestPermissions(...) @Override public void onRequestPermissionsResult ( int requestCode , @NonNull String permissions [], @NonNull int [] grantResults ) { // Brand sure it's our original READ_CONTACTS request if ( requestCode == READ_CONTACTS_PERMISSIONS_REQUEST ) { if ( grantResults . length == i && grantResults [ 0 ] == PackageManager . PERMISSION_GRANTED ) { Toast . makeText ( this , "Read Contacts permission granted" , Toast . LENGTH_SHORT ). bear witness (); } else { // showRationale = false if user clicks Never Inquire Again, otherwise true boolean showRationale = shouldShowRequestPermissionRationale ( this , Manifest . permission . READ_CONTACTS ); if ( showRationale ) { // do something hither to handle degraded style } else { Toast . makeText ( this , "Read Contacts permission denied" , Toast . LENGTH_SHORT ). prove (); } } } else { super . onRequestPermissionsResult ( requestCode , permissions , grantResults ); } } }
Permission Groups
Permission Groups avoids spamming the user with a lot of permission requests while assuasive the app programmer to only asking the minimal amount of permissions needed at any betoken in time.
Related permissions are grouped into one of the permission groups. When an app requests a permission that belongs to a particular permission group (i.e. READ_CONTACTS), Android asks the user about the college level group instead (CONTACTS). This style when the app later on needs the WRITE_CONTACTS permission, Android can automatically grant this itself without prompting the user.
In near of your interaction with the permission API's you'll exist working with the private permissions and not the permission groups, just pay close attending to what the API expects as both permissions and permission groups are Strings.
Backwards Compatibility
There are two main scenarios to think about when it comes to backwards compatibility:
- Your app is targeting an API less than Marshmallow (
TargetSdkVersion
<23
), but the emulator / device is Marshmallow:- Your app will continue to use the old permissions model.
- All permissions listed in the
AndroidManifest
will be asked for at install time. - Users volition exist able to revoke permissions after the app is installed. It's important to test this scenario since the results of certain actions without the appropriate permission can be unexpected.
- The emulator / device is running something older than Marshmallow, but yous app targets Marshmallow (
TargetSdkVersion
>=23
):- Your app will continue to use the old permissions model.
- All permissions listed in the
AndroidManifest
will be asked for at install time.
How to Inquire For Permissions
Google recommends in this video that there are four patterns to consider when thinking about permissions:
Each pattern dictates a different mode of requesting permissions. For example, when requesting for critical but unclear permissions, use a warm welcome screen to help understand a permission is requested. For critical permissions, such every bit a photographic camera app that needs camera permission, ask up-front for information technology. Secondary features can be requested later in context, such as a geotagging app when asking for a location permission. For permissions that are secondary and unclear, you lot should include a rationale explanation if y'all really need them.
Storage permissions
Rethink near whether you lot need read/write storage permissions (i.eastward. android.permission.WRITE_EXTERNAL_STORAGE
or android.permission.READ_EXTERNAL_STORAGE
), which give you all files on the SD card. Instead, you should use methods on Context to access package-specific directories on external storage. Your app always have admission to read/write to these directories,so there is no demand to permissions to request it:
// Application-specific call that doesn't require external storage permissions // Tin can be Surroundings.DIRECTORY_PICTURES, Environment.DIRECTORY_PODCASTS, Surroundings.DIRECTORY_RINGTONES, // Surroundings.DIRECTORY_NOTIFICATIONS, Environment.DIRECTORY_PICTURES, or Surround.MOVIES File dir = MyActivity . this . getExternalFilesDir ( Surround . DIRECTORY_PICTURES );
Managing Permissions using ADB
Permissions can also exist managed on the command-line using adb
with the following commands.
Prove all Android permissions:
$ adb shell pm listing permissions -d -thou
Dumping app permission state:
$adb trounce dumpsys package com.PackageName.enterprise
Granting and revoking runtime permissions:
$adb shell pm grant com.PackageName.enterprise some.permission.NAME $adb shell pm revoke com.PackageName.enterprise android.permission.READ_CONTACTS
Installing an app with all permissions granted:
$adb install -thousand myAPP.apk
References
- http://developer.android.com/guide/topics/security/permissions.html
- http://developer.android.com/preview/features/runtime-permissions.html
- https://github.com/googlesamples/android-RuntimePermissions
Source: https://guides.codepath.com/android/Understanding-App-Permissions
0 Response to "How to Determine if User Clicked Never Ask Again During Ask for Permission"
Post a Comment