I have been struggling with this issue lately and I would like to share the solution I found, using FileProvider, from the support library. its an extension of Content Provider that solve this problem well without work-around, and its not too-much work.
As explained in the link, to activate the content provider:
in your manifest, write:
<application
....
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.youdomain.yourapp.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
...
the meta data should indicate an xml file in res/xml folder (I named it file_paths.xml):
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path path="" name="document"/>
</paths>
the path is empty when you use the internal files folder, but if for more general location (we are now talking about the internal storage path) you should use other paths. the name you write will be used for the url that the content provider with give to the file.
and now, you can generate a new, world readable url simply by using:
Uri contentUri = FileProvider.getUriForFile(context, "com.yourdomain.yourapp.fileprovider", file);
on any file from a path in the res/xml/file_paths.xml metadata.
and now just use:
Intent mailIntent = new Intent(Intent.ACTION_SEND);
mailIntent.setType("message/rfc822");
mailIntent.putExtra(Intent.EXTRA_EMAIL, recipients);
mailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
mailIntent.putExtra(Intent.EXTRA_TEXT, body);
mailIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
try {
startActivity(Intent.createChooser(mailIntent, "Send email.."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(this, R.string.Message_No_Email_Service, Toast.LENGTH_SHORT).show();
}
you don't need to give a permission, you do it automatically when you attach the url to the file.
and you don't need to make your file MODE_WORLD_READABLE, this mode is now deprecated, make it MODE_PRIVATE, the content provider creates new url for the same file which is accessible by other applications.
I should note that I only tested it on an emulator with Gmail.