Need support handling runtime permissions?
Managing permissions is easier with the latest revision of the v4 or v13 support libraries (23, which is the same as the Android Marshmallow API version, so it's easy to remember)
The support libraries now provide several new methods to manage permissions and work properly on any device that can use these libraries. This, for instance, saves you the time required to check for a sufficient API level regardless of whether the device runs Android Marshmallow or not. If an app is installed on a device running Android Marshmallow, proper behavior is achieved—as if you're running the same framework calls. Even when running on lower versions, you get the expected behavior from the support library methods.
The v4 support library has the following methods:
ActivityCompat.checkSelfPermission (Context context, String permission)
:This checks whether your app has a permission.
PERMISSION_GRANTED
is returned if the app has the permission; otherwise,PERMISSION_DENIED
is returned.ActivityCompat.requestPermissions (Activity activity, String[] permissions, int requestCode
:This requests permissions, if required. If the device is not running Android 6.0, you will get a callback.
ActivityCompat.OnRequestPermissionsResultCallback(int requestCode, String[] permissions, int[] grantResults)
:This passes
PERMISSION_GRANTED
if the app already has the specified permission andPERMISSION_DENIED
if it does not.ActivityCompat.shouldShowRequestPermissionRationale (Activity activity, String permission)
:This returns
true
if the user has denied a permission request at least once and has not yet selected the Don't ask again option.
According to the design patterns, we should now give our users more information about the feature and why these permissions are so important to the app.
Note
If the device is not running Android Marshmallow, shouldShowRequestPermissionRationale
will always return false
.
The PermissionChecker
class is also included in v4.
This class provides several methods for apps that use IPC to check whether a particular package has a specified permission when IPC calls are made.
Android has a compatibility mode, allowing users to revoke access to permission-protected methods for legacy apps. When a user revokes access in the compatibility mode, the app's permissions remain the same but access to the APIs is restricted.
The PermissionChecker
method verifies app permissions in normal as well as legacy modes.
Note
If your app acts as a middleman on behalf of other apps and needs to call platform methods that require runtime permissions, you should use the appropriate PermissionChecker
method in order to ensure that the other app is allowed to perform the operation.
The v13 support library provides the following permission methods:
FragmentCompat.requestPermissions()
:This requests permissions, if required. If the device is not running Android 6.0, you will get a callback.
FragmentCompat.OnRequestPermissionsResultCallback
:This passes
PERMISSION_GRANTED
if the app already has the specified permission andPERMISSION_DENIED
if it does not.FragmentCompat.shouldShowRequestPermissionRationale()
:This returns
true
if the user has denied a permission request at least once and has not yet selected the Don't ask again option.
According to the design patterns, we should now give our users more information about the feature and why this permission is so important to the app.
Note
If the device is not running Android Marshmallow, it will always return false
.
You can check out the sample project for the three ways to handle permissions:
https://github.com/MaTriXy/PermissionMigrationGuide
For more information on permission design patterns, read Patterns – Permissions by Google at https://www.google.com/design/spec/patterns/permissions.html.
Some permissions are normal and safer to use
The Android system flags permissions according to their protection levels. The levels are describes at http://developer.android.com/reference/android/content/pm/PermissionInfo.html.
The level that is relevant to our discussion is PROTECTION_NORMAL
, in which permissions are considered to have little or no risk when applications have them.
Let's say you want to build a flashlight app; allowing your app to turn on the flash is not considered a huge risk to privacy or security, and this is why flashlight permission is flagged PROTECTION_NORMAL
.
When you declare normal permissions in the manifest, the system grants these permissions automatically at the time of installation. There is no prompt to grant permissions for a normal permissions group, and these permissions can't be revoked by users.
This means that you can be sure that normal permissions are granted at the time of installation.
Currently, the permissions classified as PROTECTION_NORMAL
are as follows:
android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
android.permission.ACCESS_WIMAX_STATE
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.CHANGE_NETWORK_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.DISABLE_KEYGUARD
android.permission.EXPAND_STATUS_BAR
android.permission.FLASHLIGHT
android.permission.GET_ACCOUNTS
android.permission.GET_PACKAGE_SIZE
android.permission.INTERNET
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.NFC
android.permission.PERSISTENT_ACTIVITY
android.permission.READ_SYNC_SETTINGS
android.permission.READ_SYNC_STATS
android.permission.READ_USER_DICTIONARY
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.REORDER_TASKS
android.permission.SET_TIME_ZONE
android.permission.SET_WALLPAPER
android.permission.SET_WALLPAPER_HINTS
android.permission.SUBSCRIBED_FEEDS_READ
android.permission.TRANSMIT_IR
android.permission.VIBRATE
android.permission.WAKE_LOCK
android.permission.WRITE_SETTINGS
android.permission.WRITE_SYNC_SETTINGS
android.permission.WRITE_USER_DICTIONARY
com.android.alarm.permission.SET_ALARM
com.android.launcher.permission.INSTALL_SHORTCUT