Android-使用Google Scoped Storage API以本机C / C ++代码访问文件

格雷格科

我需要在本机C / C ++代码中的Android应用程序中按文件名打开文件。本机代码是我不希望修改的第三方库,但是它们通常需要文件名作为读取/写入文件的参数。借助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!

将此传递给本机C / C ++代码是可行的,但前提是该文件位于电话主存储器中如果用户尝试打开插入到手机插槽中的外部SD卡上的文件,则该文件不起作用-这种方式打开的文件没有读取权限。我只能获取文件描述符int编号并使用fdopen(fd)。但这需要修改第三方库(开放源代码或许可的)的源代码,并且每当更新这些库的原始源时都会感到头疼。

有没有更好的解决方案来解决这个问题?不,我不想听到添加的解决方案

android:requestLegacyExternalStorage="true"

到AndroidManifest.xml应用程序部分-Google威胁要在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权限。在花了几个月的时间将我的应用程序转换为Storage Access Framework(SAF)之后,我现在需要一两个星期的时间才能将其转换回至少是读取文件的一部分,再转换为常规文件访问权限...谢谢Google!讽刺地感谢您所花费的时间和精力,并衷心感谢您至少部分地理解了我们的观点!

因此,不再需要下面列出的我以前的答案,请放心!

在Android“ Scoped Storage” BS上度过了我美好的一天之后,我找到了一种有效的解决方案,无需修改第三方本地库的源代码,只要该源代码具有并可以构建它们即可。

我的解决方案(非常不令人满意)是:在C / C ++编译命令中添加以下选项:

-include "[some/path/]idiocy_fopen_fd.h"

如您所见,idiocy_fopen_fd.h如下所示,对常规fopen()的每次调用都被idiocy_fopen_fd()代码替换,该代码检查文件名是否以“ / proc / self / fd /”开头,以及因此,提取文件描述符编号,然后调用fdopen()而不是fopen()...如果某人有更好的解决方案,最好是在您没有第三方库的源代码时也可以使用,请分享。

#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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在本机C代码中使用Android InputStreams

来自分类Dev

如何使用本机代码C在Android上打开Tap设备?

来自分类Dev

如何使用Android访问存储在Bluemix Object Storage中的文件?

来自分类Dev

如何在Android Studio中使用本机C ++代码使用opencv

来自分类Dev

使用C#中的HMAC密钥将文件上传到Google Cloud Storage

来自分类Dev

使用android_native_app_glue.c时可以从Java调用本机代码吗

来自分类Dev

如何使用C ++本机代码链接到Android Studio项目中的GLES2

来自分类Dev

在C ++ / CLI代码中使用本机对象

来自分类Dev

使用Android NDK在C或C ++中创建本地本机模块?

来自分类Dev

使用Google Mock for C代码

来自分类Dev

如何在Android Studio中使用本机C库

来自分类Dev

使用OpenCV和本机代码C ++从视频文件读取帧

来自分类Dev

使用ndk构建错误使用多个c文件编译本机android库*没有规则可作为目标

来自分类Dev

在适用于Android的Apache Cordova中访问C ++代码

来自分类Dev

是否可以在ARC中使用本机C ++代码?

来自分类Dev

是否可以在ARC中使用本机C ++代码?

来自分类Dev

使用ios框架获取ios的本机c ++代码

来自分类Dev

使用REST API和C#将PDF文件上传到Azure Blob存储(不使用任何AZURE STORAGE SDK)

来自分类Dev

Android和本机C / C ++调用

来自分类Dev

如何使用Android Studio中创建的应用程序将文件上传到Google Cloud Storage?

来自分类Dev

如何使用Google API在Google Storage上创建一个空文件夹?

来自分类Dev

使用C#mono的WindowsAzure.Storage

来自分类Dev

使用C#mono的WindowsAzure.Storage

来自分类Dev

编写C#函数以从Google Cloud Storage用CSV文件加载BigQuery的问题

来自分类Dev

本机/ C ++ / Java Android NDK / JNI-在活动之间共享本机代码(MSDN hello-jni示例修改)

来自分类Dev

使用C#访问公共Google日历

来自分类Dev

我们如何使用 WPF/C# 可执行文件调试 DLL(使用本机 C/C++ 构建)源代码?

来自分类Dev

使用C ++的ios应用访问文件

来自分类Dev

C-使用更多指针访问文件

Related 相关文章

  1. 1

    在本机C代码中使用Android InputStreams

  2. 2

    如何使用本机代码C在Android上打开Tap设备?

  3. 3

    如何使用Android访问存储在Bluemix Object Storage中的文件?

  4. 4

    如何在Android Studio中使用本机C ++代码使用opencv

  5. 5

    使用C#中的HMAC密钥将文件上传到Google Cloud Storage

  6. 6

    使用android_native_app_glue.c时可以从Java调用本机代码吗

  7. 7

    如何使用C ++本机代码链接到Android Studio项目中的GLES2

  8. 8

    在C ++ / CLI代码中使用本机对象

  9. 9

    使用Android NDK在C或C ++中创建本地本机模块?

  10. 10

    使用Google Mock for C代码

  11. 11

    如何在Android Studio中使用本机C库

  12. 12

    使用OpenCV和本机代码C ++从视频文件读取帧

  13. 13

    使用ndk构建错误使用多个c文件编译本机android库*没有规则可作为目标

  14. 14

    在适用于Android的Apache Cordova中访问C ++代码

  15. 15

    是否可以在ARC中使用本机C ++代码?

  16. 16

    是否可以在ARC中使用本机C ++代码?

  17. 17

    使用ios框架获取ios的本机c ++代码

  18. 18

    使用REST API和C#将PDF文件上传到Azure Blob存储(不使用任何AZURE STORAGE SDK)

  19. 19

    Android和本机C / C ++调用

  20. 20

    如何使用Android Studio中创建的应用程序将文件上传到Google Cloud Storage?

  21. 21

    如何使用Google API在Google Storage上创建一个空文件夹?

  22. 22

    使用C#mono的WindowsAzure.Storage

  23. 23

    使用C#mono的WindowsAzure.Storage

  24. 24

    编写C#函数以从Google Cloud Storage用CSV文件加载BigQuery的问题

  25. 25

    本机/ C ++ / Java Android NDK / JNI-在活动之间共享本机代码(MSDN hello-jni示例修改)

  26. 26

    使用C#访问公共Google日历

  27. 27

    我们如何使用 WPF/C# 可执行文件调试 DLL(使用本机 C/C++ 构建)源代码?

  28. 28

    使用C ++的ios应用访问文件

  29. 29

    C-使用更多指针访问文件

热门标签

归档