I am sharing an image, and this code works properly for devices before Android 6:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri uri = Uri.fromFile(new File(mFilename));
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle));
However I get the toast error "can't attach empty files" when I try to share using Android 6.
I verified that the file exists and it's not zero-length.
Anyone has a solution for this?
Another way I used to workaround this issue was to get content provider style URI using
MediaScannerConnection
right after you wrote your file to the public directory:This may be a shorter solution for your needs.
I solved it by implementing a
FileProvider
, as suggested by @CommonsWareYou first need to configure a FileProvider:
first, add the
<provider>
to your file manifest XMLsecond, define your file paths in a separate XML file, I called it "file_provider_paths.xml"
you can find the complete explanation in this documentation page
after you have set up your file provider in XML, this is the code to share the image file:
One limitation of the Android 6.0 runtime permission system is that there will be corner cases that cause problems. What you encountered is one: trying to share a file on external storage to an app that does not have the runtime permission checks in place for that particular UI path.
I say that this is a "corner case" because, for this bug in the receiving app to affect the user, the user cannot have previously used that app and granted the necessary permission. Either:
The user has never used that app before, yet it still trying to share content to it, or
The user revoked the permission via Settings, but did not realize that it would break this bit of functionality
Both of those are low probability events.
You, as the sender, have two main options:
Switch away from using
file://
Uri
values, in favor of a file-servingContentProvider
likeFileProvider
, so the permission is no longer needed, orJust living with the corner case
Alternatively, you don't need to have a ContentProvider / FileProvider . You can simply add the flag that grants read permission on the uri that is shared. Specifically,
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
should do the trick.