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

KMM Android端如何从打包为AAR的模块中读取assets目录下的文件列表

KMM Android端AAR内资源目录读取解决方案

问题根因

Android 打包AAR及后续集成到APK的过程中,JVM资源的目录条目不会被保留,仅会保留实际文件的完整路径,因此ClassLoader.getResource(文件夹路径) 天然无法在Android运行时环境生效。单元测试可以正常运行是因为测试运行在本地JVM环境,读取的是本地文件系统的真实目录结构,和Android运行时的资源加载逻辑完全不同。

方案1:构建时生成资源索引(跨端通用,推荐)

就是你已经在使用的方案,可通过Gradle自动生成索引避免手动维护,稳定性最高,兼容AAR分发场景:

  1. 在共享模块的build.gradle.kts中添加自动生成索引的任务:
task generateAssetIndex {
    def assetsDir = file("src/commonMain/assets")
    def outputDir = file("src/commonMain/assets")
    outputs.file(outputDir.resolve("asset_index.json"))
    
    doLast {
        def index = []
        fileTree(assetsDir).visit { file ->
            if (file.isFile() && !file.name.endsWith("asset_index.json")) {
                // 存储相对assets根目录的路径
                index.add(file.relativePath.toString())
            }
        }
        outputDir.mkdirs()
        outputDir.resolve("asset_index.json").text = groovy.json.JsonOutput.toJson(index)
    }
}

// 绑定到预编译任务,每次构建自动更新索引
tasks.named("preBuild").configure {
    dependsOn generateAssetIndex
}
  1. common层读取索引后批量加载文件:
// 读取索引文件
val indexContent = this::class.java.classLoader!!.getResource("asset_index.json")?.readText()
val allFilePaths = Json.decodeFromString<List<String>>(indexContent)
// 筛选指定目录下的文件
val folder1Files = allFilePaths.filter { it.startsWith("folder1/") }
// 逐个读取文件
folder1Files.forEach { path ->
    val fileContent = this::class.java.classLoader!!.getResource(path)?.readText()
    // 业务逻辑处理文件内容
}

该方案的所有逻辑都可以放在common层,不需要依赖Android专属API,对上层应用完全无感知,适配AAR作为第三方库分发的场景。

方案2:Android专属AssetManager实现

如果可以接受Android端单独实现逻辑,不需要修改构建流程,代码更简洁:

  1. 首先修改build.gradle.kts的资源配置,将资源从resources改为assets目录配置:
android {
    compileSdkVersion(29)
    sourceSets["main"].assets.srcDirs("src/commonMain/assets")
    ...
}
  1. 通过expect/actual声明获取上下文的方法,Android端返回ApplicationContext,之后调用AssetManager读取目录:
// Android侧实现
actual fun getAssetFileList(folderPath: String): List<String> {
    // context为你通过KMM注入的Application上下文
    return context.assets.list(folderPath)?.toList() ?: emptyList()
}

拿到文件名后拼接完整路径,即可按原有方式读取单个文件内容。

方案选择建议

  • 若需要尽可能多的逻辑下沉到common层,优先选择构建索引方案
  • 若不介意Android端单独适配,优先选择AssetManager方案,无需额外构建配置

内容的提问来源于stack exchange,提问作者Kevin Bassa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 11:36:03