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

在Android Jetpack Compose中加载存储Zip文件遇文件不存在问题求助

问题解决:Content URI转File导致的FileNotFoundException

错误原因

你通过ActivityResultContracts.GetContent()获取的是Content URI(示例中的content://com.android.providers.downloads.documents/document/raw:/storage/emulated/0/Download/images.zip),这类URI并非本地文件系统的真实路径,直接用uri.path创建File对象必然找不到文件——因为/document/raw:/storage/emulated/0/Download/images.zip根本不是合法的文件系统路径。

解决方案

放弃直接用File处理Content URI,改用ContentResolver获取文件输入流,通过ZipInputStream读取Zip内容,同时将解压后的文件存到应用私有目录,避免权限问题。

修改后的代码

  1. 更新Composable,传入Context并限制文件选择类型为Zip:
@Composable
fun Content(paddingValues: PaddingValues){
    val context = LocalContext.current
    val fileSearch=
        rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) {
           openFile(it, context)
        }
    Button(onClick = { fileSearch.launch("application/zip") }) {
        Text("Search Zip File")
    }
}
  1. 重写openFile函数,用ContentResolver处理URI:
fun openFile(uri: Uri?, context: Context) {
    uri ?: return
    // 通过ContentResolver获取Zip文件的输入流
    context.contentResolver.openInputStream(uri)?.use { inputStream ->
        ZipInputStream(inputStream).use { zipStream ->
            var entry: ZipEntry? = zipStream.nextEntry
            // 用应用私有缓存目录存放解压后的图片,避免权限问题
            val outputDir = context.cacheDir
            while (entry != null) {
                // 只处理文件,跳过目录项
                if (!entry.isDirectory) {
                    val outputFile = File(outputDir, entry.name)
                    // 创建必要的父目录
                    outputFile.parentFile?.mkdirs()
                    // 将Zip中的文件写入本地
                    outputFile.outputStream().use { outputStream ->
                        zipStream.copyTo(outputStream)
                    }
                    // 此处可收集outputFile的路径,后续在LazyColumn中加载展示
                }
                zipStream.closeEntry()
                entry = zipStream.nextEntry
            }
        }
    }
}

额外注意事项

  • 权限问题:Android 11+的Scoped Storage机制下,使用GetContent()无需申请WRITE_EXTERNAL_STORAGE权限,因为文件写入的是应用私有目录,系统默认允许访问。
  • 文件过滤:将launch("*/*")改为launch("application/zip"),可让文件选择器只显示Zip文件,提升用户体验。
  • 性能优化:若Zip文件较大,建议在协程中执行解压操作,避免阻塞主线程;定期清理缓存目录,防止占用过多存储。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:05:30