最后我设法通过混合 CommonsWare 答案 this answer 和 this one 解决了这个问题。在此先感谢大家!
分步解决方案:
首先,让我们从一些 XML 开始。
- 配置
AndroidManifest.xml 并在<application> 部分中添加以下行。我将它们放在我的 </activity> 和 </application> 结束标记之间,但请将此位置作为我个人的选择:根据您的清单布局,它可能不适合您。
AndroidManifest.xml
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
当我使用 API 29 时,我是 AndroidX 库。如果您也想使用它,请考虑通过在 Android Studio 中单击 Refactor > Migrate to AndroidX... 来运行 AndroidX 迁移向导,风险自负。
- 现在在
/res/xml 中创建一个名为file_paths.xml 的文件并填写如下:
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="my_sounds" path="/"/>
</paths>
注意my_sounds 名称是任意的。 path 字段中的 / 是您的文件将存储在缓存路径中的位置。为了方便起见,我只是让它这样。如果您不想使用缓存路径,here 是您可以使用的可用标签的完整列表。
现在我们将回到 Java 并开始编写处理共享的方法。首先,我们需要将资源文件夹中的文件复制到File 对象。然而,这个File 需要指向我们在 XML 部分中配置的文件提供程序创建的路径。让我们划分任务:
- 用您的文件数据创建一个
InputStream,并用一个辅助过程用它填充一个File。
public void handleMediaSend(int position)
File sound;
try {
InputStream inputStream = getResources().openRawResource(sounds.get(position).getSound()); // equivalent to R.raw.yoursound
sound = File.createTempFile("sound", ".mp3");
copyFile(inputStream, new FileOutputStream(sound));
} catch (IOException e) {
throw new RuntimeException("Can't create temp file", e);
}
辅助程序:
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1)
out.write(buffer, 0, read);
}
现在您的资源已成功传输到内部存储中的缓存目录(使用调试器查看是哪一个)。
- 获取
Uri 并分享File。
final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";
Uri uri = getUriForFile(getApplicationContext(), AUTHORITY, sound);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/mp3"); // or whatever.
share.putExtra(Intent.EXTRA_STREAM, uri);
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(share, "Share"));
把它们放在一起,我们最终会得到这个方法:
完整方法
public void handleMediaSend(int position) { // Depends on your implementation.
File sound;
try {
InputStream inputStream = getResources().openRawResource(sounds.get(position).getSound()); // equivalent to R.raw.yoursound
sound = File.createTempFile("sound", ".mp3");
copyFile(inputStream, new FileOutputStream(sound));
} catch (IOException e) {
throw new RuntimeException("Can't create temp file", e);
}
final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";
Uri uri = getUriForFile(getApplicationContext(), AUTHORITY, sound);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/mp3"); // or whatever.
share.putExtra(Intent.EXTRA_STREAM, uri);
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(share, "Share"));
}