无法弄清楚如何一起使用 ACTION_VIEW 和存储访问框架
Can't figure out how to use ACTION_VIEW and Storage Access Framework together
经过大约一个星期的拔头发,我终于完成了并准备寻求帮助。
基本上在我的应用程序中,我使用下面的 Intent 创建一个新的 PDF,这是通过存储访问框架完成的。
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "application/pdf"
intent.putExtra(Intent.EXTRA_TITLE, title)
startActivityForResult(intent, 1234)
之后,我在 onActivityResult() 方法上获取 Uri,如下所示:
uri = dataIntent.data
if (uri != null) {
val takeFlags = data.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
contentResolver.takePersistableUriPermission(uri, takeFlags)
generatePdf(uri)
}
PDF 生成没问题,当我需要调用 ACTION_VIEW 让用户查看生成的文件或使用 ACTION_SEND 共享文件时,问题就来了。
ACTION_VIEW 用法示例(是的,我同时使用 Kotlin 和 Java):
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(uri, mimeType);
startActivity(intent);
我这辈子都想不出如何获取另一个应用程序可以使用的 Uri。
到目前为止我尝试了什么:
- This answer,但抛出以下异常:java.lang.IllegalArgumentException:列'_data'不存在。可用列:[_display_name、_size]
- DocumentFile,使用DocumentFile.fromFile(file),将Uri从content://com.myapp.provider/root/document/primary:folder-created-by-the-user/generated-pdf.pdf 到 file:///root/document/primary:folder-created-by-the-user/generated-pdf.pdf, 还是打不开应用它
- 很多其他的事情我什至不记得了
如果有人能阐明这个问题,我们将不胜感激。
原则上使用与创建文件时相同的 uri。但是...您不能授予对该 uri 的读取 uri 权限。你说对了。但是您不能将此类权限转发给文档的查看者。
相反,您应该实施 ContentProvider。然后你可以提供你的文件的内容。
正如 blackapps 在他的回复中所说,我必须做的是实现一个 ContentProvider,更具体地说是一个 DocumentProvider。
跟随 this link and this link 终于成功了。我实现了一个 CustomDocumentProvider,它在我的应用程序的私有文件 (context.getFilesDir().getAbsolutePath() + "/folderToExpose") 中公开了一个文件夹,之后在该文件夹中创建的所有文件都公开给其他应用程序,我可以使用 ACTION_VIEW 和 ACTION_SEND 正常。
如果有人碰巧遇到这个问题,只需确保您要公开的文件夹不包含任何对您的应用至关重要的文件,例如数据库文件,因为用户将拥有对所有应用的完全访问权限它的内容。如果它是一个新文件夹,请确保通过调用 mkdirs() 来创建它。
经过大约一个星期的拔头发,我终于完成了并准备寻求帮助。
基本上在我的应用程序中,我使用下面的 Intent 创建一个新的 PDF,这是通过存储访问框架完成的。
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "application/pdf"
intent.putExtra(Intent.EXTRA_TITLE, title)
startActivityForResult(intent, 1234)
之后,我在 onActivityResult() 方法上获取 Uri,如下所示:
uri = dataIntent.data
if (uri != null) {
val takeFlags = data.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
contentResolver.takePersistableUriPermission(uri, takeFlags)
generatePdf(uri)
}
PDF 生成没问题,当我需要调用 ACTION_VIEW 让用户查看生成的文件或使用 ACTION_SEND 共享文件时,问题就来了。
ACTION_VIEW 用法示例(是的,我同时使用 Kotlin 和 Java):
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(uri, mimeType);
startActivity(intent);
我这辈子都想不出如何获取另一个应用程序可以使用的 Uri。
到目前为止我尝试了什么:
- This answer,但抛出以下异常:java.lang.IllegalArgumentException:列'_data'不存在。可用列:[_display_name、_size]
- DocumentFile,使用DocumentFile.fromFile(file),将Uri从content://com.myapp.provider/root/document/primary:folder-created-by-the-user/generated-pdf.pdf 到 file:///root/document/primary:folder-created-by-the-user/generated-pdf.pdf, 还是打不开应用它
- 很多其他的事情我什至不记得了
如果有人能阐明这个问题,我们将不胜感激。
原则上使用与创建文件时相同的 uri。但是...您不能授予对该 uri 的读取 uri 权限。你说对了。但是您不能将此类权限转发给文档的查看者。
相反,您应该实施 ContentProvider。然后你可以提供你的文件的内容。
正如 blackapps 在他的回复中所说,我必须做的是实现一个 ContentProvider,更具体地说是一个 DocumentProvider。
跟随 this link and this link 终于成功了。我实现了一个 CustomDocumentProvider,它在我的应用程序的私有文件 (context.getFilesDir().getAbsolutePath() + "/folderToExpose") 中公开了一个文件夹,之后在该文件夹中创建的所有文件都公开给其他应用程序,我可以使用 ACTION_VIEW 和 ACTION_SEND 正常。
如果有人碰巧遇到这个问题,只需确保您要公开的文件夹不包含任何对您的应用至关重要的文件,例如数据库文件,因为用户将拥有对所有应用的完全访问权限它的内容。如果它是一个新文件夹,请确保通过调用 mkdirs() 来创建它。