java - Intent.ACTION_SEND 定位 API 级别 24+

标签 java android

尝试使用 Intent 发送文件时出现 android.os.StrictMode.onFileUriExposed 异常。据我了解,这是因为我的目标是 24> 并且不再支持 file://,应该使用 content://

首先我想说我见过类似的问题,例如 this , this我还看到了this博客文章。

但问题是,所有帖子在拍照时都会引用 URI,在我的例子中,文件已使用 Uri 成功保存,现在我想使用 Intent 发送图像,如下所示:

shareBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent sharingIntent = new Intent(Intent.ACTION_SEND);
            Uri screenshotUri = Uri.parse("file://" + directoryToStore + "/" + filename);
            //the Uri above  - file:///storage/emulated/0/Android/data/myPackageName/files/SavedImages/test.jpeg
            sharingIntent.setType("image/jpeg");
            sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
            startActivity(Intent.createChooser(sharingIntent, "Share image using"));
        }
    });

通过执行上述操作,我只会在某些运行 19> 的设备上发生崩溃。在我的 Samsung J7Pro (Android 7.0 API 24) 上进行测试,我没有遇到崩溃。

我看到其中一些答案说我可以使用:

StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());

但这不是首选方式。

所以,我的问题是。当目标为 24> 时,我应该如何处理发送文件。我是否应该执行 if/else 语句检查版本,例如 if (Build.VERSION.SDK_INT >= 19) { ,然后对运行 <24 的设备使用普通 Uri 以及如何更改 file ://content://?我也不明白为什么崩溃只发生在某些设备上。


编辑1:

我已经完成了下面建议的答案,但文件并未按 Intent 传递,相反,当我尝试发送电子邮件时,我收到一个 Toast无法附加文件图像。

最佳答案

从应用程序共享文件的正确方法是 content provider ,具体来说FileProvider .

添加您的FileProvider到 AnroidManifest.xml:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.MyFileProvider"
    android:exported="false"
    android:grantUriPermissions="true" >
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/shared_paths"/>
</provider>

接下来,通过添加 xml 资源来添加引用的资源(Android Studio:右键单击“app”-> 新建 -> 文件夹 -> XML 资源 fodler) 然后,在这个新文件夹中创建一个名为 shared_paths.xml 的 xml 文件。 (应与 AndroidManifest.xml 中的值匹配)。 shared_paths.xml 的内容:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="SavedImages" path="SavedImages/"/>
</paths>

编辑:从 <files-path ../> 更改元素类型至<external-path .. />documentation 。 重要提示:更改 path属性以满足您的需求。

最后更改您的代码如下:

shareBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent sharingIntent = new Intent(Intent.ACTION_SEND);
            Uri screenshotUri = FileProvider.getUriForFile(context, context.getPackageName() + ".MyFileProvider", new File(directoryToStore, filename))
            //the Uri above  - file:///storage/emulated/0/Android/data/myPackageName/files/SavedImages/test.jpeg
            sharingIntent.setType("image/jpeg");
            sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
            sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Intent chooserIntent = Intent.createChooser(sharingIntent, "Share image using");
            chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(chooserIntent);
        }
    });

关于java - Intent.ACTION_SEND 定位 API 级别 24+,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51462659/

相关文章:

android - Smali 多重分包 "has already been interned"

java - 如何在 Java、Android 上使用 Intent?

java - 我如何遍历一个int

Java BufferedImage 在 appletviewer 中工作,但在浏览器中不起作用

java - 如何从url加载图片

android - 从相机拍照时出现空指针异常

java - 如何使用java从html中删除 "&#160;"字符串?

java - 按列分组并对 csv 文件进行排序 Spark

java - 如何通过互联网获取地理数据?

java - 我应该为 Android 布局使用 Java 还是 XML?