Deprecated requestPermissions()
In every application, we generally have the requirement of requesting permissions, and to do so we use the combination of requestPermissions() and onRequestPermissionResult() methods.
requestPermissions() method is used to request multiple permissions at runtime. This function call expects two parameters an array of strings representing the permissions that we want to request and an integer value representing request code which would be used later on for differentiating between the results obtained.
requestPermissions(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
AppConstant.LOCATION_PERMISSION
)On other hand overriden onRequestPermissionResult() method is used to capture the results obtained from requestPermissions(). It returns three values first is an integer value which denotes the request code, second is an array of strings representing permissions, and third is an array of integers representing results granted.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) { if (requestCode == AppConstant.LOCATION_PERMISSION) {
if (permissions.isEmpty() && grantResults.isEmpty()) {
return
}
if (permissions[0] ==
Manifest.permission.ACCESS_FINE_LOCATION &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
) { // do something which you want to do
// when permission granted }
else if (permissions[0] ==
Manifest.permission.ACCESS_FINE_LOCATION &&
grantResults[0] == PackageManager.PERMISSION_DENIED
) { // if permission denied then check whether never ask
// again is selected or not by making use of
// !ActivityCompat.shouldShowRequestPermissionRationale(
// requireActivity(),
// Manifest.permission.ACCESS_FINE_LOCATION) }
}
}
All of the above methods work fine but now AndroidStudio has started giving warnings for deprecation of requestPermissions() and the same applies for onRequestPermissionResult() the only difference here is that no warning is given for this method but it’s also deprecated.
So, what’s the solution to remove this deprecation warning?
The solution is to use the new ActivityResultAPI introduced in Android Jetpack which also makes it easier to request runtime permission.
To implement ActivityResultAPI follow the steps below -
1 Make sure that we are using androidx.activity and androidx.fragment libraries in the module’s build.gradle
implementation("androidx.activity:activity-ktx:1.3.1")
implementation("androidx.fragment:fragment-ktx:1.3.6")2In activity or fragment’s initialization logic, we need to pass ActivityResultContract (represents what type of permission to request single or multiple) and implementation of ActivityResultCallback (defines how the app handles the user’s response to the permission request) into a call to registerForActivityResult(). Keep a reference to the return value of registerForActivityResult(), which is of type ActivityResultLauncher.
ActivityResultContract to use for Single Permission Request -
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> // returns boolean representind whether the
// permission is granted or not if (isGranted) { // permission granted continue the normal workflow of app Log.i("DEBUG", "permission granted")
} else { // if permission denied then check whether never ask
// again is selected or not by making use of
// !ActivityCompat.shouldShowRequestPermissionRationale(
// requireActivity(), Manifest.permission.CAMERA) Log.i("DEBUG", "permission denied")
}
}
ActivityResultContract to use for Multiple Permissions Request -
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->// returns Map<String, Boolean> where String represents the
// permission requested and boolean represents the
// permission granted or not// iterate over each entry of map and take action needed for
// each permission requestedpermissions.forEach { actionMap ->
when (actionMap.key) {
Manifest.permission.CAMERA -> {
if (actionMap.value) {// permission granted continue the normal
// workflow of appLog.i("DEBUG", "permission granted")
} else {// if permission denied then check whether never
// ask again is selected or not by making use of
// !ActivityCompat.shouldShowRequest
// PermissionRationale(requireActivity(),
// Manifest.permission.CAMERA)Log.i("DEBUG", "permission denied")
}
}
}
}
}
3To display the system permissions dialog when necessary, call the launch() method on the instance of ActivityResultLauncher that you saved in the previous step.
Get Rohit Gupta’s stories in your inbox
Join Medium for free to get updates from this writer.
launch() to use for Single Permission Request -
requestPermission.launch(Manifest.permission.CAMERA)launch() to use for Multiple Permissions Request -
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_FINE_LOCATION
)
)After launch() is called, the system permissions dialog appears. When the user makes a choice, the system asynchronously invokes the ActivityResultCallback where we have provided the implementation of how fragment or activity handles those results.
For single permission request -
class MainActivity : AppCompatActivity() {
private val requestPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> // returns boolean representind whether the
// permission is granted or not if (isGranted) { // permission granted continue the normal workflow of app Log.i("DEBUG", "permission granted")
} else { // if permission denied then check whether never ask
// again is selected or not by making use of
// !ActivityCompat.shouldShowRequestPermissionRationale(
// requireActivity(), Manifest.permission.CAMERA) Log.i("DEBUG", "permission denied")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener { // call launch with string containing permission to be
// requested to show the system permission dialog requestPermission.launch(Manifest.permission.CAMERA)
}
}
}
For multiple permissions requests -
class MainActivity : AppCompatActivity() {
private val requestPermission =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> // returns Map<String, Boolean> where String represents the
// permission requested and boolean represents the
// permission granted or not // iterate over each entry of map and take action needed for
// each permission requested permissions.forEach { actionMap ->
when (actionMap.key) {
Manifest.permission.CAMERA -> {
if (actionMap.value) { // permission granted continue the normal
// workflow of app Log.i("DEBUG", "permission granted")
} else { // if permission denied then check whether never
// ask again is selected or not by making use of
// !ActivityCompat.shouldShowRequest
// PermissionRationale(requireActivity(),
// Manifest.permission.CAMERA) Log.i("DEBUG", "permission denied")
}
}
}
}
} override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener { // call launch with an array of string containing
// permission to be requested to show the system
// permission dialog
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
}
}
}
Final Thoughts -
Using requstPermissions() is fine if we have single permission to request at a time but what if we need to request multiple permissions? In that case, things get complicated and there will be additional overhead to maintain those permission codes, and also there will be more code we need to write with this approach. But with the new ActivityResultAPI, the system will handle the request codes so we just need to pass permission that needs to be requested.
Useful Links -https://developer.android.com/training/permissions/requesting









