Home > OS >  Where does this "isGranted" variable come from when getting permissions?
Where does this "isGranted" variable come from when getting permissions?

Time:09-17

I'm only a beginner Kotlin programmer, with some experience in other languages but nothing particularly advanced. I'm struggling to understand what exactly is happening in this code, which comes from an Android course but matches this article on requesting permissions from the user. I understand the overall effect, but one part is really tripping me up.

private val cameraResultLauncher = registerForActivityResult(
            ActivityResultContracts.RequestPermission()) {
                isGranted ->
                if(isGranted) {
                    Toast.makeText(this,
                        "Permission granted for camera", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this,
                        "Permission denied for camera", Toast.LENGTH_SHORT).show()
                }
            }

Where exactly is the value of the variable isGranted coming from? I understand that we call registerForActivityResult, passing it the result of ActivityResultContracts.RequestPermission(), and then assign all that to cameraResultLauncher... right? But somehow data from that is being used in the lambda expression that follows, and is being assigned to the parameter isGranted? I don't understand why this code is only executed at the end of a cameraResultLauncher.launch() call, either. Is the lambda expression stored as part of the variable itself? Does calling launch() trigger it, or calling the variable at all?

I've tried to research this myself, but I'm not sure of the name for this structure, and most of what I've found regarding advanced use of lambda expressions goes way over my head. If someone could explain or at least provide links explaining the flow of information in this structure, I would be very grateful.

CodePudding user response:

The registerForActivityResult takes a ActivityResultContract to identify & build a relevant Intent with extras & a callback ActivityResultCallback for notifying the result.

Since you have to wait for the result until the said operation is completed, the callback approach is used.

  1. RequestPermission extends ActivityResultContract.
    See all the different types of Contracts here.

  2. The call to cameraResultLauncher.launch() fires the provided intent.
    Permissions Intent in this case.

  3. Depending on what the user does next (accept, deny permission),
    the result is then sent back via the ActivityResultCallback i.e in the lambda block. In case of RequestPermission, the result type is a Boolean.

CodePudding user response:

It comes from ActivityResultCallback which is the second argument of function registerForActivityResult . Check the function definition ..

 public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
        @NonNull ActivityResultContract<I, O> contract,
        @NonNull ActivityResultCallback<O> callback) {
    return registerForActivityResult(contract, mActivityResultRegistry, callback);
}

Since its a single method interface it can be converted to lambda thats called SAM conversion and also its the last parameter so it can be moved outside of braces .. that lambda is equivalent to code below for IDE will give u hint to convert this to lambda . hence the sort variant ..

val cameraResultLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission(),
    object : ActivityResultCallback<Boolean> {
        override fun onActivityResult(isGranted: Boolean) {
            if(isGranted) {
                // Granted
            } else {
                // Denied
            }
        }
    })
  • Related