Android Runtime Permissions using registerForActivityResult

Akhil jain
CodeX
Published in
3 min readApr 2, 2021

Android recently deprecated its old ActivityResult API and introduced new ones with AndroidX Activity 1.2.0-alpha02. It makes it easier to request runtime permissions.

With new APIs available, developers can now register for results, launch for results and then handle the result produced by the system.

But Why?

When starting an activity for a result, it’s likely that your process and activity will be destroyed due to a lack of memory in memory-intensive operations like camera use. As a consequence, the Activity Result APIs decouple the result callback from the location in your code where the other activity is launched.

Hence unfortunately when the process or activity is recreated, the callback has to register it every time, even if the logic of launching the other activity only happens based on user input or other business logic.

What is different?

Previously we had to manage the request code while requesting permissions by passing it to the requestPermissions() method. And then use that request code while fetching the result in OnRequestPermissionResult() method as shown below.

ActivityCompat.requestPermissions(context,permissionArray,
requestCode)
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
REQUEST_CODE -> {
if ((grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED){
// Permission is granted.
} else {
//permission is denied.
}
return
}
}
}

With New Activity Result API we don’t have to manage request codes ourselves as the system handles it itself internally.

New Activity Result API provides registerForActivityResult() API for registering the result callback. It takes an ActivityResultContract and an ActivityResultCallback and returns an ActivityResultLauncher using which we can launch other activity as shown below.

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

findViewById<Button>(R.id.button).setOnClickListener {
activityResultLauncher.launch(Manifest.permission.CAMERA)
}
}


private val activityResultLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission()){isGranted ->
// Handle Permission granted/rejected
if (isGranted) {
// Permission is granted
} else {
// Permission is denied
}
}
}
  • ActivityResultContract specifies the input type needed to produce the result. In above example ActivityResultContracts.RequestPermission() is used which means the activity launcher will require android permissions as input.
  • ActivityResultCallback specifies how we handle the user’s response to the permission request
  • When the launch() method is called with CAMERA permission as input then a permission dialog requesting CAMERA permission will be displayed. Based on the user’s response to the permission, the system invokes activityResultCallback.

Similarly, multiple permissions can be requested at the same time by passing Array of Permissions instead of single permission as input and we get a MutableMap with permission as key and grant result as value in activityResultCallback.

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

findViewById<Button>(R.id.button).setOnClickListener {
activityResultLauncher.launch(
arrayOf(Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE)
)

}
}


private val activityResultLauncher =
registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions())
{ permissions ->
// Handle Permission granted/rejected
permissions.entries.forEach {
val permissionName = it.key
val isGranted = it.value
if (isGranted) {
// Permission is granted
} else {
// Permission is denied
}
}
}
}

You can check out official documentation using below mentioned link for further reading:

https://developer.android.com/training/basics/intents/result

https://developer.android.com/training/permissions/requesting

--

--