如何解决Android 10的存储混乱

Raf*_*l T 6 android file android-fileprovider storage-access-framework scoped-storage

由于Android在有关文件访问的不同主要版本之间非常不一致,因此我感到有些失落。我尝试尽可能简单地描述问题:

我的公司使用商业本地DRM保护我们提供的其他本地库。我们有一个许可应用程序,该应用程序调用了一些Voodoo来结束/ sdcard / companyname / LicenseContainer /中的许可文件。其他受保护的应用程序以本机代码查看此目录,检查用户是否具有有效的许可证。

但是,Android 10更新仅提供,使该工作流程完全无效scoped storage access。我们可以使用一种方法Storage Manager来授予访问权限,不幸的是,现在也已弃用该方法。

所以我的问题是:一个应用程序如何将文件保存到/ sdcard / FOLDER上的某个位置

  1. 应用删除后未删除
  2. 其他应用可使用本机代码访问

对于所有可能的解决方案(SAF,FileProvider等),我有点不知所措,这些解决方案通常会调用一个应用程序将权限授予另一个应用程序的权限。但是,如果没有安装的第一个应用程序将文件放到那里,则应该可以访问这些文件。

我知道必须有解决方案,因为最近的FileManagers(即Files by Google)可以访问整个/sdcard/目录。

在不调用“黑客”之类的情况下,最简单,最适合未来的路线是什么 android:requestLegacyExternalStorage="true"

gre*_*gko 6

您可以要求用户授予您访问任何文件或目录的权限,包括内部存储或外部 SD 卡的根目录。您可以使此访问权限对您的应用程序永久有效,之后能够使用 Scoped Storage API 在任何地方读取/写入文件,直到应用程序被卸载或重置。

然后,如果您需要在本机 C/C++ 代码中读取或写入文件,您可以获取该文件的 Linux 文件描述符(int 号)并将其传递给本机代码以与 fdopen() 调用一起使用。

下面是一个 Java 代码片段,用于从单个文件 Uri 中获取文件描述符(字符串形式类似于 content://...)

    ParcelFileDescriptor parcelFileDescriptor =
            getContentResolver().openFileDescriptor(uri, "r"); // gets FileNotFoundException here, if file we used to have was deleted
    int fd = parcelFileDescriptor.getFd(); // detachFd() if we want to close in native code
Run Code Online (Sandbox Code Playgroud)

如果您有本机库的源代码,或者可以使用 C FILE* 调用它们 - 它将正常工作。唯一的问题是当您没有源代码并且他们需要文件路径/名称时。* 更新 *:仍然可以使用路径/文件名字符串传递给需要文件名的 C/C++ 函数。只需创建一个符号链接名称,而不是“真实路径/文件名”,如下所示:

// fd is file descriptor obtained in Java code above
char fileName[32];
sprintf(fileName, "/proc/self/fd/%d", fd);
// The above fileName can be passed to C/C++ functions that expect a file name.
// They can read or write to it, depending on permissions to fd given in Java,
// but I guess C/C++ code can not create a new file. Someone correct me,
// if I'm mistaken here.
Run Code Online (Sandbox Code Playgroud)

但是,目前我不确定当您以这种方式在应用程序“沙箱”之外的目录中创建文件时,系统是否会在卸载后删除该文件......需要编写一个快速测试Android 10 来找出答案,然后我们仍然不知道 Google 将来是否会改变这种行为。