如何从assets目录获取java.io.File对象?
问题描述
我的assets目录下有一个Markdown文件,用的Markdown阅读器必须传入java.io.File对象才能解析显示内容,但试了URI方式根本拿不到有效的File对象。以下是我写的代码片段:
val markDown = File("file:///asset/GalacticAstronomy.md") if (markDown.exists()) { Toast.makeText(baseContext, "File exist", Toast.LENGTH_SHORT).show() } else Toast .makeText(baseContext, "File doesn't exist", Toast.LENGTH_SHORT).show() setContent { MaterialTheme { MarkDown( file = markDown, modifier = Modifier.fillMaxSize() ) } }
注意:我不是要读取文件内容,所以assets.open("file")这种方法解决不了我的问题
解决方案
Assets里的文件是打包在APK里的资源,不是设备文件系统里的真实文件,所以直接用URI肯定拿不到有效的java.io.File对象。解决办法是先把assets里的文件复制到设备的内部或外部存储,再获取对应的File实例:
- 先写个工具方法,把assets文件复制到内部存储:
private fun copyAssetToInternalStorage(assetFileName: String): File? { val outputFile = File(filesDir, assetFileName) // 如果已经复制过,直接返回 if (outputFile.exists()) { return outputFile } return try { // 打开assets文件流,复制到内部存储 assets.open(assetFileName).use { inputStream -> FileOutputStream(outputFile).use { outputStream -> inputStream.copyTo(outputStream) } } outputFile } catch (e: IOException) { e.printStackTrace() null } }
- 然后在代码里调用这个方法获取File对象:
val markDownFile = copyAssetToInternalStorage("GalacticAstronomy.md") markDownFile?.let { file -> Toast.makeText(baseContext, "File exist", Toast.LENGTH_SHORT).show() setContent { MaterialTheme { MarkDown( file = file, modifier = Modifier.fillMaxSize() ) } } } ?: run { Toast.makeText(baseContext, "File doesn't exist", Toast.LENGTH_SHORT).show() }
补充说明
- 内部存储的
filesDir是应用的私有目录,不需要额外权限就能读写 - 复制操作只需要做一次,之后直接用已经复制好的文件就行,不用重复复制浪费资源
- 如果要放到外部存储,可以把
filesDir换成getExternalFilesDir(null),不过Android 13及以下版本需要动态申请存储权限
内容的提问来源于stack exchange,提问作者tycoon
相关产品推荐
相关产品推荐

