Share Video Preview Image using ACTION_SEND with Android Sharesheet

556 Views Asked by At

Since Android 10+, the Android Sharesheet has supported providing image previews of files shared using ACTION_SEND. Making a custom ActivityResultContract with the Android documentation for sending binary content, you get something like this:

class ShareVideo : ActivityResultContract<Uri, Unit>() {
    override fun createIntent(context: Context, input: Uri): Intent {
        return Intent(Intent.ACTION_SEND).apply {
            type = "video/*"
            putExtra(Intent.EXTRA_STREAM, input)
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
    }

    override fun parseResult(resultCode: Int, intent: Intent?) {
        return
    }
}

...
@Composable
fun ShareVideo(file: Uri) {
    val shareVideo = rememberLauncherForActivityResult(ShareVideo()) {}

    Button(onClick={ shareVideo.launch(file) }) {
       Text("Share Video")
    }
}

However, this does not result in a preview image in the Sharesheet. What am I doing wrong? Sharesheet without preview

1

There are 1 best solutions below

0
On

As it turns out, every answer implementing ACTION_SEND wraps the Intent(Intent.ACTION_SEND) with Intent.createChooser(...)

That is, every ACTION_SEND intent should be wrapped inside of an ACTION_CHOOSER intent, which itself mostly copies the information found in the ACTION_SEND intent, which makes you wonder what the difference is. According to the documentation, the ACTION_CHOOSER intent has a richer interface for when defaults are not allowed, or don't make sense. The ACTION_SEND intent is a simpler interface for when a default is intended.

So the correct ActivityResultContract implementation for sharing binary files with ACTION_SEND is something like

class ShareVideo : ActivityResultContract<Uri, Unit>() {
    override fun createIntent(context: Context, input: Uri): Intent {
        return Intent.createChooser(Intent(Intent.ACTION_SEND).apply {
            type = "video/*"
            putExtra(Intent.EXTRA_STREAM, input)
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }, null)
    }

    override fun parseResult(resultCode: Int, intent: Intent?) {
        return
    }
}

Sharesheet with an image preview