Android 11 MediaStore存储zip文件后无法访问及获取路径求解
问题解决办法
核心错误原因
- 构造MediaStore Content Uri的逻辑错误:MediaStore的内容Uri需要绑定文件的唯一
_id字段,你直接拼接文件名的方式不符合系统规则 - 分区存储限制:Android 10及以上系统不允许直接将
content://开头的Uri转换为File对象操作,所有content Uri都需要通过ContentResolver访问
修正后读取代码
val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { MediaStore.Files.getContentUri("external") } else { MediaStore.Video.Media.EXTERNAL_CONTENT_URI } val projection = arrayOf( MediaStore.Files.FileColumns.RELATIVE_PATH, MediaStore.Files.FileColumns.DISPLAY_NAME, MediaStore.Files.FileColumns.SIZE, MediaStore.Files.FileColumns._ID ) // 直接添加筛选条件,不需要遍历所有文件 val selection = "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ?" val selectionArgs = arrayOf("2.1.2.zip") val cursor = requireContext().contentResolver.query( collection, projection, selection, selectionArgs, null ) // use方法自动管理cursor关闭 cursor?.use { if (it.moveToFirst()) { val fileId = it.getLong(it.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)) // 正确构造Content Uri val targetUri = ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"), fileId) // 通过ContentResolver打开文件流操作 requireContext().contentResolver.openInputStream(targetUri)?.use { zipStream -> // 此处写你的zip文件处理逻辑,比如用ZipInputStream读取文件内容 Log.d("TAG", "文件读取成功,有效Uri为:$targetUri") } ?: run { Log.d("TAG", "打开文件流失败") } } else { Log.d("TAG", "未找到匹配的zip文件") } }
额外优化建议
- 保存文件时补充RELATIVE_PATH字段,明确指定存储路径,避免系统默认分配路径不符合预期:
// Java保存代码添加这一行 contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
- Android 11及以上如果需要访问其他应用创建的公共目录文件,需要申请
READ_EXTERNAL_STORAGE权限,自身应用创建的文件不需要额外权限 - 如果需要调用第三方应用打开该zip文件,启动Intent时需要添加
FLAG_GRANT_READ_URI_PERMISSION标记,授予对方临时访问权限
内容的提问来源于stack exchange,提问作者Jakub Zając
相关产品推荐
相关产品推荐

