最近我一直在苦恼这个问题,现在我想分享一下我找到的解决方案,使用支持库中的FileProvider。它是Content Provider的扩展,可以很好地解决这个问题,而且不需要太多额外的工作。
正如链接中所解释的那样,要激活Content Provider:在你的清单文件中写入:
<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>
...
元数据应该指示res/xml文件夹中的一个xml文件(我将其命名为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>
当您使用内部文件夹时,路径为空,但是如果要使用更一般的位置(我们现在谈论的是内部存储路径),您应该使用其他路径。您编写的名称将用于内容提供程序提供给文件的URL。
现在,您可以通过简单地使用以下内容生成新的、全局可读的URL:
Uri contentUri = FileProvider.getUriForFile(context, "com.yourdomain.yourapp.fileprovider", file);
从res/xml/file_paths.xml元数据的路径中选择任意文件。
现在只需使用:
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();
}
当您将URL附加到文件时,无需授予权限,它会自动完成。
您不需要使文件MODE_WORLD_READABLE,此模式现已弃用,请使用MODE_PRIVATE。内容提供程序将为同一文件创建新的URL,其他应用程序可以访问该URL。
值得注意的是,我只在模拟器上测试过与Gmail的情况。