ACTION_SEND, the Chooser, and ClipData
Roderick Gadellaa pointed out an interesting problem with the “share sheet”. In Android 10+, the share sheet can show a preview of your content. In particular, it can show a preview of an image that you are sharing. The catch is that the share sheet needs to know what image that is… and whether it does depends on how you are sharing it.
Sharing content involves ACTION_SEND
, and if we use EXTRA_STREAM
to supply
a Uri
, we need to add FLAG_GRANT_READ_URI_PERMISSION
and/or FLAG_GRANT_WRITE_URI_PERMISSION
on the Intent
:
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, uri)
type = "image/webp"
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
Frequently, when using ACTION_SEND
, we wrap it in a chooser Intent
, such
as via Intent.createChooser()
. So, we pass our Intent
to createChooser()
and
roll from there:
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, uri)
type = "image/webp"
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(intent, null))
And, if you try this, you will not get a preview in the share sheet.
This, however, works:
val intent = Intent(Intent.ACTION_SEND).apply {
clipData = ClipData.newRawUri(null, uri)
putExtra(Intent.EXTRA_STREAM, uri)
type = "image/webp"
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(intent, null))
The reason is that the framework copies the ClipData
out of the ACTION_SEND
and puts it in the ACTION_CHOOSER
Intent
created by createChooser()
.
It does not copy any EXTRA_STREAM
value, though.
There is also the possibility that you are using ShareCompat.IntentBuilder
:
ShareCompat.IntentBuilder.from(this)
.setType("image/webp")
.addStream(uri)
.startChooser()
This too fails… for now. cketti filed an issue for that one, and while it is fixed, I do not believe that fix has shipped yet.
UPDATE 2021-01-13: The fix is available in androidx.core:core:1.5.0-beta01
!
Ideally, you use setClipData()
on an ACTION_SEND
Intent
or that repaired version
of ShareCompat.IntentBuilder
, so your shared images are able to be previewed
properly.