Receive Share Image intents in Flutter

In the previous post, we covered how to handle Share Text intents. This post builds on the previous one, so check it out if you haven't done so yet. This time we'll go through receiving Share Image intents. Note that this works for regular files too.

Intent Filter

The intent filter is slightly more complicated than for text. In this codelab at developer.android.com, they show an intent filter that supports single and multiple images, many image types and even panoramic images. I'll try them all eventually, but to start, I'll try supporting single image shares with this intent filter:

<intent-filter>
    <action android:name="android.intent.action.SEND" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="image/*" />
</intent-filter>

To support other types of files, change the mimeType accordingly. The rest of the code is exactly the same.

Android code

class MainActivity(): FlutterActivity() {
  private var sharedImage: ByteArray? = null;

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    GeneratedPluginRegistrant.registerWith(this)

    val action = intent.action
    val type = intent.type

    if (Intent.ACTION_SEND.equals(action) && type != null) {
      if ("text/plain".equals(type)) {
        handleSendText(intent)
      } else {
        handleSendImage(intent)
      }
    }

    MethodChannel(flutterView, "app.channel.shared.data")
            .setMethodCallHandler { call, result ->
              if (call.method.contentEquals("getSharedImage")) {
                result.success(sharedImage)
                sharedImage = null
              }
            }
  }

  fun handleSendImage(intent : Intent) {
    val uri = intent.getClipData().getItemAt(0).getUri()
    val inputStream = contentResolver.openInputStream(uri)
    sharedImage = inputStream.readBytes()
  }
}

Flutter side

Finally the getter in Flutter looks like this:

Future<List<int>> getSharedImage() async {
  return platform.invokeMethod("getSharedImage");
}

Unit tests

I was unable to write the tests for it, because of some type conversion. I get the following error:

type 'List<dynamic>' is not a subtype of type 'List<int>'

Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=BUG.md

When the exception was thrown, this was the stack:
#0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:13)

I will look into it some other time.