gre*_*gko 8 java-native-interface android scoped-storage
我需要在原生 C/C++ 代码中的 Android 应用程序中按文件名打开文件。本机代码是我不想修改的第 3 方库,但它们通常需要文件名作为读/写文件的参数。使用 Google 的“范围存储”API 并在 Android 10 或更高版本中禁用对文件的本机访问,这是一个真正的问题。
一个众所周知的解决方案是获取文件描述符并使用“proc/self/fd/FD_NUMER”技巧,例如:
ParcelFileDescriptor mParcelFileDescriptor = null;
String getFileNameThatICanUseInNativeCode(Context context, DocumentFile doc) {
try {
Uri uri = doc.getUri();
mParcelFileDescriptor =
context.getContentResolver().openFileDescriptor(uri, "r");
if (mParcelFileDescriptor != null) {
int fd = mParcelFileDescriptor.getFd();
return "/proc/self/fd/" + fd;
}
}
catch (FileNotFoundException fne) {
return "";
}
}
// Don't forget to close mParcelFileDescriptor when done!
Run Code Online (Sandbox Code Playgroud)
将此传递给本机 C/C++ 代码有效,但前提是文件位于手机主存储中。如果用户尝试打开插入手机插槽的外部 SD 卡上的文件,则不起作用 - 以这种方式打开的文件没有读取权限。我只能获取文件描述符 int 号并使用 fdopen(fd)。但这将需要修改 3rd 方库(开源或许可)的源代码,并且每次更新这些库的原始源时都会令人头疼。
有没有更好的解决这个问题的方法?不,我不想听到添加的解决方案
android:requestLegacyExternalStorage="true"
Run Code Online (Sandbox Code Playgroud)
到 AndroidManifest.xml 应用程序部分 - 谷歌威胁要在 2020 年的下一个 Android 版本中禁用它,因此需要一个永久的解决方案。另一个简单但愚蠢的解决方案是将用户尝试打开的整个(可能很大)文件复制到私有应用程序目录中。愚蠢而无用...
2020 年 5 月 19 日更新:刚刚发现:READ_EXTERNAL_STORAGE 权限允许您在 Android 11 上运行并面向 API 30(或更高版本)时读取文件,但不能列出目录内容。我将它作为错误提交,并得到了“这是按预期工作”的回复(https://issuetracker.google.com/issues/156660903)。如果有人关心,请在那里以及他们的“调查”中发表评论:https : //google.qualtrics.com/jfe/form/SV_9HOzzyeCIEw0ij3?Source=scoped-storage我不知道如何继续在 Android 上开发应用程序这些限制。
2020 年 5 月 17 日更新:Google 终于承认并允许在 Android 11 及更高版本中使用 READ_EXTERNAL_STORAGE 权限。在花了几个月将我的应用程序转换为存储访问框架 (SAF) 之后,我现在需要一两个星期的时间将其转换回常规文件访问,至少是读取文件部分……谢谢谷歌!讽刺地感谢您损失的时间和精力,真诚地感谢您至少部分理解了我们的观点!
所以,我之前列出的答案不再需要了,松了一口气!
在 Android “Scoped Storage” BS 上浪费了我生命中的又一天美好时光之后,我找到了一个有效的解决方案,无需修改 3rd 方本机库的源代码,前提是拥有这些库的源代码并且可以构建它们。
我(非常不满意)的解决方案是:在 C/C++ 编译命令中添加以下选项:
-include "[some/path/]idiocy_fopen_fd.h"
Run Code Online (Sandbox Code Playgroud)
并且 idiocy_fopen_fd.h 如下所示,如您所见,对常规 fopen() 的每次调用都被替换为 idiocy_fopen_fd() 代码,该代码检查文件名是否以“/proc/self/fd/”开头,如果因此,提取文件描述符编号并调用 fdopen() 而不是 fopen() ...如果有人有更好的解决方案,最好在您没有第 3 方库的源代码时也能工作,请分享。
#ifndef fopen_fd
#include <stdio.h>
#include <string.h>
#include <unistd.h> // for dup()
#ifdef __cplusplus
extern "C" {
#endif
inline FILE* idiocy_fopen_fd(const char* fname, const char * mode) {
if (strstr(fname, "/proc/self/fd/") == fname) {
int fd = atoi(fname + 14);
if (fd != 0) {
// Why dup(fd) below: if we called fdopen() on the
// original fd value, and the native code closes
// and tries re-open that file, the second fdopen(fd)
// would fail, return NULL - after closing the
// original fd received from Android, it's no longer valid.
FILE *fp = fdopen(dup(fd), mode);
// Why rewind(fp): if the native code closes and
// opens again the file, the file read/write position
// would not change, because with dup(fd) it's still
// the same file...
rewind(fp);
return fp;
}
}
return fopen(fname, mode);
}
// Note that the above leaves the original file descriptor
// opened when finished - close parcelFileDescriptor in
// Java/Kotlin when your native code returns!
#ifdef __cplusplus
}
#endif
#define fopen idiocy_fopen_fd
#endif
Run Code Online (Sandbox Code Playgroud)
2020 年 5 月 19 日更新:刚刚发现:READ_EXTERNAL_STORAGE 权限允许您在 Android 11 上运行并以 API 30(或更高版本)为目标时读取文件,但不能列出目录内容。我将它作为错误提交,并得到了“这是按预期工作”的回复(https://issuetracker.google.com/issues/156660903)。如果有人关心,请在那里以及在他们的“调查”中发表评论:https : //google.qualtrics.com/jfe/form/SV_9HOzzyeCIEw0ij3?Source=scoped-storage我不知道如何继续在 Android 上开发应用程序这些限制。
o 考虑将应用切换到 SAF 的任何人,我都会从 Google Play 开发者控制台发布我的应用的月平均收视率图表。2020 年 1 月,我使用 SAF 而不是常规文件访问发布了我的应用程序的第一个版本,请参见附图。随着越来越多的用户更新,收视率下降,很多评论说我毁了一个好应用。即使现在该应用程序的活跃安装量也超过了 100 万。
2020 年 5 月 17 日更新: Google 终于承认并允许在 Android 11 及更高版本中使用 READ_EXTERNAL_STORAGE 权限。在花了几个月将我的应用程序转换为存储访问框架 (SAF) 之后,我现在需要一两个星期的时间将其转换回常规文件访问,至少是读取文件部分……谢谢谷歌!讽刺地感谢您损失的时间和精力,真诚地感谢您至少部分理解了我们的观点!
这并不是“范围存储”噩梦的结束。Google 正在 Android 11 中再次“改进”它(请参阅https://developer.android.com/preview/privacy/storage) - 我们迄今为止为使其工作所做的一切可能很快就会被扔进垃圾桶。
请考虑评论并支持我的请求,即不限制对 Android 11 中下载目录的 Scoped Storage 访问,和/或改进系统“文件”界面:https : //issuetracker.google.com/issues/151759806
我正在认真考虑放弃Android平台的进一步开发……在我看来,傲慢、控制欲强的“父母”接管了Android系统的进化,他们认为我们其他人都是小孩子,他们需要安装安全门到处都是我们的房子,严重限制了我们的行动自由。好难过。
格雷格
| 归档时间: |
|
| 查看次数: |
2858 次 |
| 最近记录: |