You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 13设备上如何从C/C++原生端写入DCIM文件夹?

解决Android 13下MediaStore结合原生代码写入DCIM的问题

问题根源

Android 13强化了SELinux策略与/proc文件系统的访问限制,你之前通过/proc/self/fd/拼接路径让C++代码访问文件的方式会被拦截——因为该路径对应的文件属于MediaStore的沙箱化资源,直接通过路径访问会触发权限校验失败。

无需SAF的MediaStore解决方案

核心思路是直接传递文件描述符(fd)给C++代码,而非转换为路径。ParcelFileDescriptor返回的fd本身就是有效的、拥有写入权限的文件描述符,原生代码可直接用它进行IO操作,完全绕开路径访问的权限问题。

步骤1:保留原有MediaStore条目插入逻辑

这部分代码在Android 13上依然有效,无需修改:

Uri placeholderUri = null;
ContentResolver contentResolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();        
contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, "TEST_VIDEO");
contentValues.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
contentValues.put(MediaStore.Video.Media.RELATIVE_PATH, "DCIM/" + "APP_NAME");
try {
   placeholderUri = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
} catch (RuntimeException e) {
   e.printStackTrace();
}

步骤2:获取ParcelFileDescriptor并传递fd到C++

不再拼接/proc路径,直接把fd的数值传递给原生层:

if (placeholderUri != null) {
    try (ParcelFileDescriptor fd = context.getContentResolver().openFileDescriptor(placeholderUri, "rw")) {
        if (fd != null) {
            // 调用原生方法,传入fd
            nativeWriteVideoData(fd.getFd());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

步骤3:C++层直接操作fd

在原生代码中,直接使用传入的fd进行写入,无需再次打开文件:

#include <jni.h>
#include <stdio.h>
#include <unistd.h>

extern "C" JNIEXPORT void JNICALL
Java_com_your_package_YourActivity_nativeWriteVideoData(JNIEnv* env, jobject thiz, jint fd) {
    // 替换为你的图像处理/视频录制写入逻辑
    const char* testData = "Sample video data";
    ssize_t bytesWritten = write(fd, testData, strlen(testData));
    
    if (bytesWritten == -1) {
        perror("Failed to write to fd");
    }

    // 若Java层使用try-with-resources,fd会自动关闭,无需手动调用close(fd)
}

关键注意事项

  • fd生命周期管理:在Java层用try-with-resources包裹ParcelFileDescriptor,确保操作完成后自动释放资源;若原生代码需要长时间写入,需保持ParcelFileDescriptor的引用,避免fd被提前回收。
  • 权限说明:Android 13及以上版本,写入视频到MediaStore无需申请WRITE_EXTERNAL_STORAGE权限,系统默认允许创建媒体文件。
  • 兼容性:该方案兼容Android 10/11/13,无需针对不同版本做分支处理。

内容的提问来源于stack exchange,提问作者yellowsubmarine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 02:05:34