Handling permission requests in Android for Flutter plugins

While building the Android functionality for a plugin recently I had to handle a system permission request. Although all the parts of that are simple it took me a while to figure out how to put them together. In hopes of making it simpler for others looking to do this here’s all the bits in one place. Note: Code examples are Kotlin, there’s a full gist here.

Handling the callback

The part that I had to search a bit to pull together was how to handle the Android permission callback in my plugin. The Android documentation for it is here but doing it in a plugin is a bit different. Here’s the relevant code for a Flutter plugin.

Implement the callback interface

First add the PluginRegistry.RequestPermissionsResultListener interface to the plugin class declaration. I also define the request code to use, myPermissionCode and a variable to hold the result of the permission check, permissionGranted. The request code value can be anything you want. It is an identifier that you give to the requestPermissions call and that is then given back in the result handler so that you know if the result matches your request.

class MyPlugin ( activity: Activity): MethodCallHandler, 
  PluginRegistry.RequestPermissionsResultListener
    private val myPermissionCode = 72
    private var permissionGranted: Boolean = false

Then implement the method from that interface. Note the test for the matching myPermissionCode to ensure that the result is for the permission request you made. If it is then I store the granted state into a boolean then call a method on my plugin to do something with the new permission. That part depends on what your plugin wants to do with the permission.

override fun onRequestPermissionsResult( requestCode: Int, 
  permissions: Array<out String>?, 
  grantResults: IntArray?): Boolean {

  when (requestCode) {
    myPermissionCode -> {
      if ( null != grantResults ) {
        permissionGranted = grantResults.isNotEmpty() &&
        grantResults.get(0) == PackageManager.PERMISSION_GRANTED
        }
      // do something here to handle the permission state
      updatePluginState()
      }
   }
   return true
}

Register the callback

Now that the interface is implemented it has to be registered with the Flutter plugin registrar so that it will be invoked. I add this code to the generated registerWith method that is already in the plugin. The new line is the call to registrar.addRequestPermissionsResultListener.

companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
  val channel = MethodChannel(registrar.messenger(), "myPluginChannel")
  val myPlugin = MyPlugin()
  registrar.addRequestPermissionsResultListener(myPlugin)
  channel.setMethodCallHandler(myPlugin)
  }
}

Check for permission

With this code in place you can now successfully check for a permission and if not yet granted ask the user to provide it. This example shows checking if a single Android permission, READ_EXTERNAL_STORAGE, has already been granted and if not showing the system dialog requesting permission from the user. Note that the system prompt and the user response is non-blocking and the response is returned via the callback.

private fun checkPermission(context: Application) {
  permissionGranted = ContextCompat.checkSelfPermission(context,
    Manifest.permission.READ_EXTERNAL_STORAGE) == 
    PackageManager.PERMISSION_GRANTED
  if ( !permissionGranted ) {
    ActivityCompat.requestPermissions(pluginActivity,
      arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),   
      myPermissionCode )
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *