Runtime Permissions

In Android 6.0 Marshmallow application will not be granted any permission at installation time. Instead, application has to ask a user for a permission one-by-one at runtime.

The Permission request dialog  will not launch automatically. Developer has to call for it manually. In the case that developer try to call some function that requires a permission which a user has not granted yet, the function will suddenly throw an Exception which will lead to the application crashing.

Besides, user is also able to revoke the granted permission anytime through phone's Settings application.

Runtime Permission will work like described only when we set the application's targetSdkVersion to 23 which mean it is declared that application has already been tested on API Level 23. And this feature will work only on Android 6.0 Marshmallow. The same app will run with same old behavior on pre-Marshmallow device.

If the application's targetSdkVersion is set to less than 23, it will be assumed that an application is not tested with new permission system yet and will switch to the same old behavior: a user has to accept every single permission at install time and they will be all granted once installed!  Anyway, please, note that user still can revoke a permission after that! Although Android 6.0 warns the user when they try to do that but they can revoke anyway.

Automatically granted permissions

There are some permissions that will be automatically granted at install time and will not be able to revoke. We call it Normal Permission (PROTECTION_NORMAL). Here is a full list of them:

  • android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
  • android.permission.ACCESS_NETWORK_STATE
  • android.permission.ACCESS_NOTIFICATION_POLICY
  • 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.CHANGE_WIMAX_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.READ_SYNC_SETTINGS
  • android.permission.READ_SYNC_STATS
  • android.permission.RECEIVE_BOOT_COMPLETED
  • android.permission.REORDER_TASKS
  • android.permission.REQUEST_INSTALL_PACKAGES
  • 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.USE_FINGERPRINT
  • android.permission.VIBRATE
  • android.permission.WAKE_LOCK
  • android.permission.WRITE_SYNC_SETTINGS
  • com.android.alarm.permission.SET_ALARM
  • com.android.launcher.permission.INSTALL_SHORTCUT
  • com.android.launcher.permission.UNINSTALL_SHORTCUT

Just simply declare those permissions in AndroidManifest.xml, and it will work just fine. No need to check for the permission listed above since it couldn't be revoked.

Support new Runtime Permission

Now it's time to make our application support new Runtime Permission perfectly. Start with setting targetSdkVersion to 23 in AndroidManifest.xml.

First of all, the Android Native allows you yo check if permission has been already granted or not, see the sample below:

bool val = PermissionsManager.IsPermissionGranted(AN_Permission.WRITE_EXTERNAL_STORAGE);
if(val) {
  Debug.Log("WRITE_EXTERNAL_STORAGE Granted");
} else {
  Debug.Log("WRITE_EXTERNAL_STORAGE Denied");
}

In case permissions haven't been granted yet, you may present the dialog asking user to grant certain permissions to your app. When the dialog is completed, ActionPermissionsRequestCompleted will be fired  after the dialog completed. The code snipped can be found below:

PermissionsManager.ActionPermissionsRequestCompleted += HandleActionPermissionsRequestCompleted;

PermissionsManager.Instance.RequestPermissions(AN_MenifestPermission.WRITE_EXTERNAL_STORAGE, AN_MenifestPermission.CAMERA);

void HandleActionPermissionsRequestCompleted (AN_GrantPermissionsResult res) {
  Debug.Log("HandleActionPermissionsRequestCompleted");
  
  foreach(KeyValuePair<AN_MenifestPermission, AN_PermissionState> pair in res.RequestedPermissionsState) {
    Debug.Log(pair.Key.GetFullName() + " / " + pair.Value.ToString());
  }
  
}