如何在没有所有文件权限的情况下使用本机库在共享存储中按名称打开文件?

Mat*_*uhn 7 android android-ndk android-permissions

我们正在编写一个针对 Android 进行交叉编译的 C++ 应用程序。该应用程序使用本机库(即gdalQt)来读取和写入文件。

这些文件通常相互引用(例如,xml 文件,引用其旁边的其他文件;或者 shapefile,其中多个文件具有共同的基本名称)。上述库需要能够通过路径 ( fopen(name)) 打开文件才能访问所有信息。

常见用例有:

  • 使用浏览器下载 zip 文件,使用文件管理器(例如 amaze)解压缩,然后在我们的应用程序中打开内容
  • 使用文件共享应用程序(例如 nextcloud、syncthing...)来同步文件夹。然后我们的应用程序会编辑此文件夹中的文件。

由于 API 级别 30 ,Google PlayStore 限制文件访问,并且只允许在特定的应用程序特定目录中进行不受限制的直接文件访问。

在共享文件夹(例如下载文件夹、外部存储设备中的根文件夹等)中,只能通过直接文件访问来访问文件类型的子集。

共享存储文档中提到的访问媒体文件

如果您没有任何与存储相关的权限,则可以使用文件 API 访问应用程序特定目录中的文件以及归属于您的应用程序的媒体文件。

我们测试中的媒体文件包括图像、视频……但不包括此处所需的文件类型(.dbf、.shp、.qgs)。

还有存储访问框架,其中 DocumentProvider用于流式传输单个文件和意图(如OPEN_DOCUMENT_TREE )的数据,但是这些将通过与本机调用不兼容的 URI 生成访问fopen(name)

我们发现能够按名称打开文件(通过本机实验室)的唯一选项是使用所有文件权限 ( MANAGE_EXTERNAL_STORAGE)。这效果很好,但需要列入白名单才能在 Google Play 商店上发布。

谷歌支持建议使用系统文件选择器(有时将建议扩展到“或其他隐私友好的方法”)。

问:如果您的库之前可以使用路径,那么它们仍然可以。问题从哪里开始呢?

答:在 Android 11 上,未经许可MANAGE_EXTERNAL_STORAGE,我们在多次测试中看到,通过路径字符串直接打开共享位置中的非媒体文件不再起作用。文件打开失败。我们还注意到,执行目录列表(使用 Qt API)仅显示媒体文件扩展名,跳过所有其他类型。

如何在没有所有文件权限 ( MANAGE_EXTERNAL_STORAGE) 的情况下通过本机库共享位置中的文件路径(字符串)打开文件?