





















































In Android, each application runs with distinct system IDs known as Linux user ID and Group ID. The system parts are also separated into distinct IDs, forming isolated zones for applications—from each other and from the system. As part of this isolated life cycle scheme, accessing services or other applications' data requires that you declare this desire in advance by requesting a permission.
This is done by adding the uses-permission element to your AndroidManifest.xml file. Your manifest may have zero or more uses-permission elements, and all of them must be the direct children of the root <manifest> element.
Trying to access data or features without proper permission should give out a security exception (using a SecurityException class), informing you about the missing permission in most cases.
The sendBroadcast(Intent) method is exceptional as it checks permissions after the method call has returned, so you will not receive an exception if there are permission failures. A permission failure should be printed to the system log. Note that in Android versions prior to Marshmallow, missing permissions were due to missing declarations in the manifest. Hence, it is important that you keep permissions in mind when you come up with the feature list for your app.
(For more resources related to this topic, see here.)
Android Marshmallow introduces a new application permissions model, allowing a simpler process for users when installing and/or upgrading applications. Applications running on Marshmallow should work according to a new permissions model, where the user can grant or revoke permissions after the installation—permissions are not given until there is user acceptance.
Supporting the new permissions model is backward-compatible, which means your apps can still
With the Android Marshmallow version, a new application permissions model has been introduced.
Let's review it a bit more thoroughly:
If an app targets an Android Marshmallow version, it must use the new permissions model.
When working with permissions, we divide them into groups. This division is done for fast user interaction when reviewing and approving permissions. Granting is done only once per permission group. If you add a new permission or request a new permission from the same permission group and the user has already approved that group, the system will grant you the added permission without bothering the user about the approval.
For more information on this, visit https://developer.android.com/reference/android/content/pm/PermissionInfo.html#constants[GS1] .
When the user installs an app, the app is granted only those permissions that are listed in the manifest that belongs to the PROTECTION_NORMAL group.
Requesting permissions from the PROTECTION_SIGNATURE group will be granted only if the application is signed with the same certificate as the app with the declared permission.
Apps cannot request signature permissions at runtime.
System components automatically receive all the permissions listed in their manifests.
Android Marshmallow showcased a new permissions model where users were able to directly manage app permissions at application runtime. Google has altered the old permissions model, mostly to enable easier and frictionless installations and auto-updates for users as well as for app developers. This allows users to install the app without the need to preapprove each permission the application needs. The user can install the app without going through the phase of checking each permission and declining the installation due to a single permission.
Users can grant or revoke permissions for installed apps, leaving the tweaking and the freedom of choice in the users' hands.
Most of the applications will need to address these issues when updating the target API to 23.
Well, after all the explanations, we've reached the coding part, and this is where we will get our coding hands dirty. The following are the methods used for coding permissions:
Even if your app is not yet targeting Android Marshmallow, you should test your app and prepare to support it.
In the Android Marshmallow permissions model, your app must ask the user for individual permissions at runtime. There is limited compatibility support for legacy apps, and you should test your app and also test a version to make sure it's supported.
You can use the following test guide and conduct app testing with the new behavior:
The adb command shell can be quite helpful to check for permissions:
adb shell pm list permissions -g
adb shell pm [grant|revoke] <permission.name>
adb install -g <path_to_apk>
When we want to adjust our application to the new model, we need to make sure that we organize our steps and leave no permission stranded:
By now, you should be familiar with Build.VERSION.SDK_INT.
Context.checkSelfPermission(String permission_name)
With this, we silently check whether permissions are granted or not.
This method returns immediately, so any permission-related controls/flows should be dealt with by checking this first.
You can request more than one permission at once. The second argument is a simple request code returned in the callback so that you can recognize the calls. This is just like how we've been dealing with startActivityForResult() and onActivityResult() for years.
Another new API is Activity.shouldShowRequestPermissionRationale(String permission).
This method returns true when you have requested a permission and the user denied the request. It's considered a good practice after verifying that you explain to the user why you need that exact permission. The user can decide to turn down the permission request and select the Don't ask again option; then, this method will return false.
The following sample code checks whether the app has permission to read the user's contacts. It requests the permission if required, and the result callback returns to onRequestPermissionsResult:
if (checkSelfPermission(Manifest.permission.READ_CONTACTS) !=
PackageManager.PERMISSION_GRANTED) {
requestPermissions(new
String[]{Manifest.permission.READ_CONTACTS},
SAMPLE_MATRIXY_READ_CONTACTS);
}
//Now this is our callback
@Override
public void onRequestPermissionsResult(int requestCode, String
permissions[], int[] grantResults) {
switch (requestCode) {
case SAMPLE_MATRIXY_READ_CONTACTS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission granted - we can continue the feature flow.
} else {
// permission denied! - we should disable the functionality
that depends on this permission.
}
}
}
Just to make sure we all know the constants used, here's the explanation:
public static final int PERMISSION_DENIED=-1:
Since it's API level 1, permission has not been granted to the given package
public static final int PERMISSION_GRANTED=0:
Since it's API level 1. permission has been granted to the given package.
If the user denies your permission request, your app should take the appropriate action, such as notifying the user why this permission is required or explaining that the feature can't work without it.
Your app cannot assume user interaction has taken place because the user can choose to reject granting a permission along with the do not show again option; your permission request is automatically rejected and onRequestPermissionsResult gets the result back.
To learn more about Android 6 Essentials, the following books published by Packt Publishing (https://www.packtpub.com/) are recommended:
Android User Interface Development: Beginner's Guide (https://www.packtpub.com/application-development/android-user-interface-development-beginners-guide)
Android Native Development Kit Cookbook (https://www.packtpub.com/application-development/android-native-development-kit-cookbook)
Further resources on this subject: