Qt 6 Android 11应用读写文件权限被拒问题求助
解决Qt 6 + Android 11(SDK 31)下Widget应用的TXT文件写入权限问题
问题背景
基于Qt 6、CMake开发面向Android 11(SDK 31)的Widget应用,当前遇到.txt文件写入权限被拒的问题——应用可以创建.txt文件,但无法写入内容。
已尝试的无效方案
- 通过QJniObject调用
isExternalStorageManager检查权限,未授权时跳转至全文件权限设置页,但该设置项呈灰色,无法开启 - 递归请求
android.permission.MANAGE_EXTERNAL_STORAGE权限,同时试过READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE以及QtAndroidPrivate::Storage相关方法,均无效果 - 尝试申请
android.permission.MANAGE_DOCUMENTS权限,问题依旧
报错信息
return (<E Qt JAVA : openParcelFdForContentUrl: java.lang.SecurityException: Permission Denial: writing com.android.providers.downloads.DownloadStorageProvider uri content://com.android.providers.downloads.documents/document/62.txt from pid=2455, uid=10179 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()> )
相关代码
QString filename = QFileDialog::getSaveFileName(); filename = filename + ".txt"; qDebug() << "the file name is : " + filename; ui->startPageProgramName->setText(test.toString()); auto result = QtAndroidPrivate::checkPermission("android.permission.MANAGE_DOCUMENTS").result(); if(result == QtAndroidPrivate::PermissionResult::Denied){ result = QtAndroidPrivate::requestPermission(QString("android.permission.MANAGE_DOCUMENTS")).result(); } QFile file(filename); if(!file.open(QIODevice::WriteOnly)){ qDebug() << file.errorString(); return; }else{ QTextStream out(&file); out << "QString::fromStdString(mainPro_->programToString())"; qDebug() << &out; out.flush(); out << "testing som more"; out << "agian"; file.close(); }
解决方向
- 适配Android分区存储规则:Android 11起强制分区存储,
MANAGE_EXTERNAL_STORAGE权限仅对文件管理器等特定类型应用开放,普通应用无法正常获取。如果你的应用不属于这类,别再死磕这个权限,转而用以下几种方式:- 应用专属目录:写入应用私有目录(无需额外权限),Qt可通过
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)获取该路径 - MediaStore:如果是媒体类文件,通过MediaStore API写入公共媒体目录
- SAF存储访问框架:通过SAF获取的URI需要用Android原生API写入,不能直接用Qt的QFile操作
- 应用专属目录:写入应用私有目录(无需额外权限),Qt可通过
- 正确处理SAF返回的URI:你用
QFileDialog::getSaveFileName()拿到的是content URI,不是本地文件路径,QFile直接操作会触发权限问题。需要通过JNI调用Android的ContentResolver来写入:- 把QString类型的URI转为Android的Uri对象
- 获取App的ContentResolver实例
- 调用
openOutputStream(Uri)获取输出流,再把数据写入这个流
- 放弃无效权限申请:
MANAGE_DOCUMENTS是系统级权限,普通应用根本申请不到,不用再尝试。 - 配置清单文件:在AndroidManifest.xml中正确声明权限,同时可添加
android:requestLegacyExternalStorage="true"作为临时过渡方案(长期还是建议适配分区存储)。
内容的提问来源于stack exchange,提问作者rasmus klitgaard
相关产品推荐
相关产品推荐

