Hi There,
In our recent article, we have been looking into the ActivityResult API in android, this API was introduced as an alternative to the deprecated startActivityForResult and onActivityResult callback, along with that we found out that onRequestPermissionsResult is also deprecated, a callback used to capture result back after the user responded to runtime permission prompt. In this article, we will be learning about how to get runtime permission in android with ActivityResult API
You can learn in detail about the Android Activity Result API in this article:
[Tutorial] Get Android Activity Result in Kotlin With ActivityResult API
What is a Runtime Permission In Android:
Runtime permissions, also known as dangerous permissions, give your app additional access to restricted data, and they allow your app to perform restricted actions that more substantially affect the system and other apps. Therefore, you need to request runtime permissions in your app before you can access the restricted data or perform restricted actions. When your app requests runtime permission, the system presents a runtime permission prompt
Source: Permission on Android | Android Developers
As explained in the android developer's docs, runtime permission aka dangerous permission is to ask the user for confirmation in order to use some of the features from his device, for example, access to the files stored in the device or access to the user's current location, back in the days these permissions were informed to the user during install time, to increase the security and privacy of the user these runtime permissions were introduced, this helps protect the user's data and privacy because without the user's knowledge no application can access any of the data which require this permission, few examples are storage, location, camera, and microphone. You can the developer's docs for more information on which permissions are runtime permissions.
How to ask runtime permission in android with kotlin:
Now that we know what are runtime permission and how that's going to impact our application, there are some times where we might need this permission in our application lets to say we want to store some data in the user's devices for him to easily access is next time or when opens the application without internet, we don't want the user to stare at an empty white screen right, so for that purpose, we need to ask the user for permission to access to their storage.
And that's now easy with the ActivityResult API as it helps us achieve with less code and verify type safety, and we can also say that for these purposes the ActivityResult API was introduced. The ActivityResult API provides some pre-defined contracts that help us to request permission which confirms type safety. We share a detailed article on ActivityResult API with Custom Contract Here
How to use ActivityResult API to Get Runtime Permission
Since the onRequestPermissionsResult is deprecated, we are going with the ActivityResult API to get the result back from the user's interaction on the status of the permission he has chosen during the prompt. To start, we register a start activity for result with a contract, whereas android provides us with some useful contract in which two of them were related to permissions which are RequestMultiplePermissions for requesting multiple permission (pretty obvious I know) and RequestPermission for requesting single permission, so we register our call back with these contracts. Refer to the code below:
private val requestStoragePermission =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions())
{ permissionGranted ->
if (permissionGranted.isNotEmpty()) {
if (permissionGranted[permissionArray[0]]!! &&
permissionGranted[permissionArray[1]]!!) {
permissionStatusTextView.text = "Permission Granted"
} else {
permissionStatusTextView.text = "User denied permission"
}
}
}
In the above piece of code, we register a callback with the ActivityResultContracts.RequestMultiplePermssions, which will then provide as a map of string and a boolean, which will hold the information about the permissions we asked and the result as boolean whether the permission is granted or not, if it's granted the result will be true and it will be false when the permission is not granted. In this tutorial we are using multiple permission related to storage, read, and write storage which is stored in the permission array like below
private val permissionArray = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
So in the result, we check the permissionGranted map to check whether these two permissions were granted or not.
Start the Runtime Permission Workflow to get Access:
Once the callback is registered now we use it to launch and ask the user to provide us the permission, But before that Android has suggested some guidelines or even we can as rules for asking the user these dangerous permissions which are clearly explained here
Workflow for requesting permissions since this post not exactly about android permissions rather how to get that permission using ActivityResult API so here are only giving you the brief about it, and Just to make sure read those workflow points carefully because lots have changed since the last time I have read. Now let's continue with our implementation, Since we are asking for storage permission in our example I use this simple function to ask for the permission, Refer to the code below:
private fun checkStoragePermission() {
if (isAllPermissionGranted()) {
permissionStatusTextView.text = "Permission Already Granted"
} else {
if (requireActivity().shouldShowRequestPermissionRationale(permissionArray[0])
|| requireActivity().shouldShowRequestPermissionRationale(permissionArray[1])
) {
Toast.makeText(
requireContext(),
"In order to demonstrate the success scenario we
need you to allow access to the permission",
Toast.LENGTH_LONG
).show()
requestStoragePermission.launch(permissionArray)
} else {
requestStoragePermission.launch(permissionArray)
}
}
}
As mentioned in the developer's guide, before doing any operation based on the dangerous permission it is advisable to always check the permission, as the user might have manually removed the permission at any time from the app settings, like that I start with a simple helper function to check is all the permission already granted or not, then if the permissions not provided, I start by checking do I have to give any information on why I need that permission, why because this is suggested in the workflow and a good practise too because you will not want to provide you personal files to be accessed by any other apps without knowing the real reason right, so we check that by calling shouldShowRequestPermissionRationale with the permission string, the android system will provide a boolean to decide whether we have to show the information about why we need the permission or not, this usually triggered only after the user denied the permission for least once, though this is not documented as far as I know.
In case you have missed:
So in here, we show a little toast about why we need this permission and then we launch our ActivityResultLauncher with the array of permissions we need from the user, simple as it is, isn't it? Now the system will provide the permission prompt to the user where the user can choose to allow or deny the permission, once the user has responded the callback will be triggered with the list of permission and its status whether the user has granted it the access or not from there we can continue our work accordingly.
What to do when permission denied:
In most cases, granting runtime permission will allow the user to continue using your application, there might be chances where the user might have denied the permission for the android version before 11, which means up to android 10 the application can ask for permission once the user has denied the access after some tries the system will provide one more option to the user with "Deny and Don't ask again" if the user chooses this option you will not be able to ask for the same permission again, but from starting Android 11 if the user denied the permission more than once the system will consider as the "Don't ask again" choice in which cases you cannot ask for the permission anymore rather you can ask the user to manually allow the permission from the settings You can check this answer from StackOverflow:
https://stackoverflow.com/a/61410621/7111648
Conclusion:
I hope this article helps you can get a clear picture from our sample project if you wanted to get a hands-on experience on how this actually works, for this tutorial we continued the code from our previous article so you can expect the same pattern here, these android runtime permissions were requested from android fragment to demonstrate the features of the ActivityResult API get the source code from GitHub link here:
https://github.com/blackzshaik/ActivityResultAPISample/tree/request-permission
~~~Thanks Don't forget to Like Our Facebook Page~~~
You might be interested:
Sharing is Caring!!!
keywords:
Request multiple permissions android
Android request permission at runtime example Kotlin
multiple runtime permissions android example
android runtime permissions example github
android storage location permission programmatically
how to ask runtime permission in android
0 Comments
Have doubts? Shoot your thoughts....