Android 11+下无法在可移除SD卡共享目录创建文件的技术咨询
Android 11+下QT C++应用SD卡共享目录写入方案
问题背景
开发面向Android 11+的QT C++应用,通过SAF让用户选择文件夹下载媒体文件:
- 可正常操作的路径:
"/storage/emulated/0/Download/"(主外部共享存储)"/storage/emulated/0/Android/data/com.app.app/files"(主应用私有存储)"/storage/XXXX-XXXX/Android/data/com.app.app/files"(SD卡应用私有存储)
- 无法操作的路径:
"/storage/XXXX-XXXX/Download/"(SD卡外部共享目录),报错Cannot create file: /storage/9016-4EF8/...
- 核心矛盾:SD卡应用私有存储的文件无法被其他应用(图库、编辑器等)访问,主存储容量不足的用户需要将可被其他应用访问的文件存到SD卡
可行解决方案
1. 基于SAF Uri操作文件(推荐)
Android 11+对SD卡共享目录的写入必须通过SAF的DocumentFile API,不能直接用标准C++路径读写。QT中需通过JNI桥接实现:
- 用户通过SAF选择SD卡共享目录后,保存返回的
Uri(而非路径字符串) - 写入文件时,通过JNI调用
DocumentFile.createFile()创建目标文件,再用ContentResolver.openOutputStream()获取输出流,将下载内容写入 - 此方式创建的文件位于共享目录,其他应用可正常访问,且符合Android权限规范
2. 申请MANAGE_EXTERNAL_STORAGE权限(限特定场景)
若应用属于文件管理器、备份类等符合Google Play权限政策的类型,可申请全文件访问权限:
- 在
AndroidManifest.xml中添加权限声明:<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> - 引导用户到系统设置授予权限:通过
Intent(ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)跳转 - 获权后可直接用标准C++函数(如
std::ofstream、fopen)读写SD卡共享目录 - 注意:非合规应用申请此权限会被Google Play拒绝上架
3. 用MediaStore API存储媒体文件(仅适用于媒体类文件)
如果下载的是图片、视频、音频等媒体文件,可通过MediaStore API插入到SD卡的媒体集合:
- 通过JNI调用
ContentResolver.insert(),指定存储位置为SD卡的媒体目录(如MediaStore.Images.Media.EXTERNAL_CONTENT_URI) - 获取插入后的
Uri,打开输出流写入文件内容 - 该方式创建的文件会被系统媒体库自动索引,图库等应用可直接识别访问
QT C++实现注意事项
- 禁止直接用标准C++文件操作函数访问SD卡共享目录路径,必须通过JNI桥接Android原生API
- 封装JNI工具类,提供
createFileFromUri、writeStreamToUri等接口供QT代码调用 - 对用户选择的SAF目录Uri,调用
takePersistableUriPermission获取持久权限,避免应用重启后丢失访问权限
内容的提问来源于stack exchange,提问作者RomaFUN
相关产品推荐
相关产品推荐

