uni-app 安卓10+文件共享获取共享文件时无外部储存读取权限
uni-app 安卓10+文件共享获取共享文件时无外部储存读取权限
操作步骤:
- 微信,qq浏览器打开文档 => 其他应用打开、发送到其他 => 选择APP => 本应用获取文件路径上传到服务器
预期结果:
- 获取文件信息上传
实际结果:
- 无法获取文件上传
bug描述:
在开发文件共享时,微信、QQ浏览器,分享文件,发现安卓10以下对于文件共享获取外部文件权限是有权限的,安卓10+虽然已经有了读写权限,但是无法读取到文件。 示例文件路径:
- 微信分享文件路径: /storage/emulated/0/Android/data/com.tencent.mm/MicroMsg/Download/文件名
- QQ分享文件路径: /storage/emulated/0/QQBrowser/editcopyfiles/文件名
| 信息类别 | 详细信息 |
|----------------|------------|
| 产品分类 | uniapp/App |
| PC开发环境操作系统 | Windows |
| PC开发环境操作系统版本号 | 20H2 |
| HBuilderX类型 | 正式 |
| HBuilderX版本号 | 3.2.12 |
| 手机系统 | Android |
| 手机系统版本号 | Android 11 |
| 手机厂商 | 小米 |
| 手机机型 | 安卓10+ |
| 页面类型 | vue |
| 打包方式 | 云端 |
| 项目创建方式 | HBuilderX |
更多关于uni-app 安卓10+文件共享获取共享文件时无外部储存读取权限的实战教程也可以访问 https://www.itying.com/category-93-b0.html
是否为相同问题,查看:https://ask.dcloud.net.cn/question/133886
更多关于uni-app 安卓10+文件共享获取共享文件时无外部储存读取权限的实战教程也可以访问 https://www.itying.com/category-93-b0.html
对
目前未找到方法解决
安卓端的话可以采用原生插件的方式获取文件管理器
这是一个典型的Android 10+(API 29+)分区存储(Scoped Storage)权限问题。在Android 10及以上版本,应用默认无法直接访问其他应用私有目录(如/storage/emulated/0/Android/data/com.tencent.mm/),即使拥有READ_EXTERNAL_STORAGE权限。
解决方案:
-
使用
uni.chooseFileAPI(推荐) 这是uni-app官方提供的文件选择接口,会自动处理Android权限适配:uni.chooseFile({ success: (res) => { const tempFilePaths = res.tempFilePaths; // tempFilePaths[0] 为临时文件路径,可直接上传 } }); -
处理Content URI 当用户通过"其他应用打开"分享文件时,系统传递的是Content URI而非真实路径。需要转换:
// 在App.vue的onLaunch或页面中监听 plus.globalEvent.addEventListener('intent', (e) => { const uri = e.payload; if (uri.startsWith('content://')) { // 将content:// URI转换为可访问的路径 plus.io.resolveLocalFileSystemURL(uri, (entry) => { const filePath = entry.toLocalURL(); // 使用filePath上传 }); } }); -
配置Android权限 在
manifest.json中确保以下配置:{ "app-plus": { "distribute": { "android": { "permissions": [ "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>", "<uses-permission android:name=\"android.permission.MANAGE_EXTERNAL_STORAGE\"/>" ] } } } }注意:
MANAGE_EXTERNAL_STORAGE需要Google Play审核,且仅用于特定文件管理场景。 -
使用临时文件 对于微信/QQ浏览器分享的文件,可先复制到应用私有目录:
plus.io.resolveLocalFileSystemURL(sourcePath, (entry) => { entry.copyTo(plus.io.PRIVATE_WWW, 'tempfile', (newEntry) => { const localPath = newEntry.toLocalURL(); // 上传localPath }); });

