卸载并重新安装应用程序后访问 public 文件夹中创建的文件?
Accessing files created in public folders after uninstall and reinstall of app?
我正在使用 SqliteImportExporter 库将我的数据库文件导入和导出到 public 文件夹“Documents”。我不认为该文件具有 MIME 类型,它只是从字节流创建的并且具有 .db 文件扩展名。
定位 Android API 30 后,如果我卸载并重新安装我的应用程序,它无法访问它之前创建的文件,无法导入或覆盖它。
Android documentation 讨论了使用 ACTION_OPEN_DOCUMENT_TREE
意图来授予对整个目录及其内容的访问权限。选择目录给权限后,还是进不去。这个过程返回的URI是不是有什么神奇的地方,或者在获得许可后我还能使用这个库吗?我正在为库提供文件的绝对路径 - 在我将 API 30 和 运行 应用程序定位到 API 30 AVD 之前一直有效。
有人可以为我指明正确的方向吗?
编辑:我的问题现在简单地归结为,当目标 API 30 时,如何简单地将文件 to/from 复制到共享文件夹(例如文档文件夹),并且仍然保持对 API 21岁起。
声望低于 50,所以添加我的评论作为答案。
请参考这篇。如此处所述,一旦卸载,您的应用程序就不再拥有其自己创建的文件的所有权,您必须在该文件夹的许可下工作。
I'm using SqliteImportExporter library
请注意,该库似乎没有得到维护。
Is there something magic about the URI returned by this process
是的。例如,您可以使用 DocumentFile.fromTreeUri()
将其包装在 DocumentFile
中,然后使用 DocumentFile
直接在该树的根中获取表示文档的 DocumentFile
对象,等等。
就我个人而言,我在 this sample project demonstrating importing and exporting databases (covered in this book、FWIW 中使用了 ACTION_CREATE_DOCUMENT
/ActivityResultContracts.CreateDocument()
和 ACTION_OPEN_DOCUMENT
/ActivityResultContracts.OpenDocument()
。
How can one simply copy a file to/from the shared folders (e.g. documents folder)
您已有代码。您的问题是 uninstall/reinstall 周期和失去对该文件的权限。你有几个选择来处理这个问题。
首先,您可以要求用户删除您的旧应用程序安装创建的文件,这样您就可以再次将您的硬编码(?)文件名写入您的硬编码目的地。用户可以使用预安装的文件管理器执行此操作,例如,如果用户有一个。
其次,您可以让用户选择一个文件名。如果他们选择了一个您由于此权限问题而无法使用的文件,请告诉用户并要求用户给您另一个文件名。或者,您可以自动调整文件名,就像 Web 浏览器在下载文件时所做的那样(例如,将 (1)
添加到名称中)。
第三,您可以停止写入 Documents/
,而是写入 getExternalFilesDir()
(Context
上的方法)。两个主要的缺点是这个目录不那么方便,并且当你的应用程序被卸载时它的内容会被删除。
第四,您可以按照我在该示例中所做的操作:使用 ACTION_CREATE_DOCUMENT
/ActivityResultContracts.CreateDocument()
让用户选择在何处创建导出的数据库以及如何调用它。然后,您可以使用 ContentResolver
和 openOutputStream()
为您返回的 Uri
获取 OutputStream
,并且您可以将数据库的字节复制到 OutputStream
.对于稍后的导入,使用 ACTION_OPEN_DOCUMENT
/ActivityResultContracts.OpenDocument()
让用户选择一个导出的数据库供您使用,并使用 ContentResolver
和 openInputStream()
反转该过程。这为用户提供了最大的灵活性,因为您不会将它们锁定在特定位置和特定文件名中。这确实意味着用户需要选择一个位置并确认您建议的文件名。
还有其他可能性,例如对 ACTION_OPEN_DOCUMENT_TREE
大惊小怪,但恕我直言,这个特别麻烦。
我正在使用 SqliteImportExporter 库将我的数据库文件导入和导出到 public 文件夹“Documents”。我不认为该文件具有 MIME 类型,它只是从字节流创建的并且具有 .db 文件扩展名。
定位 Android API 30 后,如果我卸载并重新安装我的应用程序,它无法访问它之前创建的文件,无法导入或覆盖它。
Android documentation 讨论了使用 ACTION_OPEN_DOCUMENT_TREE
意图来授予对整个目录及其内容的访问权限。选择目录给权限后,还是进不去。这个过程返回的URI是不是有什么神奇的地方,或者在获得许可后我还能使用这个库吗?我正在为库提供文件的绝对路径 - 在我将 API 30 和 运行 应用程序定位到 API 30 AVD 之前一直有效。
有人可以为我指明正确的方向吗?
编辑:我的问题现在简单地归结为,当目标 API 30 时,如何简单地将文件 to/from 复制到共享文件夹(例如文档文件夹),并且仍然保持对 API 21岁起。
声望低于 50,所以添加我的评论作为答案。
请参考这篇
I'm using SqliteImportExporter library
请注意,该库似乎没有得到维护。
Is there something magic about the URI returned by this process
是的。例如,您可以使用 DocumentFile.fromTreeUri()
将其包装在 DocumentFile
中,然后使用 DocumentFile
直接在该树的根中获取表示文档的 DocumentFile
对象,等等。
就我个人而言,我在 this sample project demonstrating importing and exporting databases (covered in this book、FWIW 中使用了 ACTION_CREATE_DOCUMENT
/ActivityResultContracts.CreateDocument()
和 ACTION_OPEN_DOCUMENT
/ActivityResultContracts.OpenDocument()
。
How can one simply copy a file to/from the shared folders (e.g. documents folder)
您已有代码。您的问题是 uninstall/reinstall 周期和失去对该文件的权限。你有几个选择来处理这个问题。
首先,您可以要求用户删除您的旧应用程序安装创建的文件,这样您就可以再次将您的硬编码(?)文件名写入您的硬编码目的地。用户可以使用预安装的文件管理器执行此操作,例如,如果用户有一个。
其次,您可以让用户选择一个文件名。如果他们选择了一个您由于此权限问题而无法使用的文件,请告诉用户并要求用户给您另一个文件名。或者,您可以自动调整文件名,就像 Web 浏览器在下载文件时所做的那样(例如,将 (1)
添加到名称中)。
第三,您可以停止写入 Documents/
,而是写入 getExternalFilesDir()
(Context
上的方法)。两个主要的缺点是这个目录不那么方便,并且当你的应用程序被卸载时它的内容会被删除。
第四,您可以按照我在该示例中所做的操作:使用 ACTION_CREATE_DOCUMENT
/ActivityResultContracts.CreateDocument()
让用户选择在何处创建导出的数据库以及如何调用它。然后,您可以使用 ContentResolver
和 openOutputStream()
为您返回的 Uri
获取 OutputStream
,并且您可以将数据库的字节复制到 OutputStream
.对于稍后的导入,使用 ACTION_OPEN_DOCUMENT
/ActivityResultContracts.OpenDocument()
让用户选择一个导出的数据库供您使用,并使用 ContentResolver
和 openInputStream()
反转该过程。这为用户提供了最大的灵活性,因为您不会将它们锁定在特定位置和特定文件名中。这确实意味着用户需要选择一个位置并确认您建议的文件名。
还有其他可能性,例如对 ACTION_OPEN_DOCUMENT_TREE
大惊小怪,但恕我直言,这个特别麻烦。