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

Android Library编译后丢失方法,作为AAR依赖时出现方法找不到错误

Compose自定义导航库AAR引入Android端方法不存在问题排查

问题复现场景

开发的Compose跨平台导航库,作为AAR引入Android项目时触发方法不存在异常,直接导入源码则运行正常,报错堆栈如下:

No virtual method setUi(Lkotlin/jvm/functions/Function5;)V in class Lcom/nom/rougthnav/ScreenConfiguration; or its super classes (declaration of 'com.nom.rougthnav.ScreenConfiguration' appears in /data/data/com.nom.myapplication/code_cache/.overlay/base.apk/classes.dex)
    at com.nom.myapplication.MainActivity$onCreate$1$1$1$router$2$1.invoke(MainActivity.kt:33)
    at com.nom.myapplication.MainActivity$onCreate$1$1$1$router$2$1.invoke(MainActivity.kt:31)
    at com.nom.rougthnav.Router.screen(Router.kt:75)
    at com.nom.rougthnav.Router.screen(Router.kt:47)

涉及的接口定义:

interface RouterScope<K> {
    fun <T> screen(
        tag: K,
        modelFactory: () -> T,
        block: @Composable (model: T, back: Back, nav: Nav<K>) -> Unit
    )

    var initialTag: K
    var link: String
    fun route(tag: K, initial: K, block: RouterScope<K>.() -> Unit)
    var tagConverter: ((String) -> K)?
}

库的build.gradle.kts配置:

plugins {
    id("org.jetbrains.kotlin.android")
    id("com.android.library")
    `maven-publish`
}

android {
    compileSdk = 30

    defaultConfig {
//        applicationId = "com.nom.rougthnav"
        minSdk = 27
        targetSdk = 30
//        versionCode = 1
//        versionName = "1.0"
        version = "1.6"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    kotlinOptions {
        jvmTarget = "11"
    }
}

dependencies {

    implementation("androidx.core:core-ktx:1.6.0")
    implementation("androidx.appcompat:appcompat:1.3.1")
    implementation("com.google.android.material:material:1.4.0")
    val compose = "1.0.3"
    implementation("androidx.compose.ui:ui:$compose")
    implementation("androidx.compose.ui:ui-tooling-preview:$compose")
    implementation("androidx.compose.ui:ui-tooling:$compose")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.3")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
}

afterEvaluate {
    publishing {
        publications {
            register("release",MavenPublication::class){
                from(components["release"])
                groupId = "com.nom.roughtnav"
                artifactId = "core"
                version = "${project.version}"
            }
        }
    }
}

排查思路

  • 首先补全库模块的Compose编译配置,当前android配置块中缺失Compose构建开关和编译器版本指定,添加以下配置:
    android {
        // 原有配置不变
        buildFeatures {
            compose true
        }
        composeOptions {
            // 版本要和使用的Compose版本、Kotlin版本严格对应,Compose 1.0.3对应kotlinCompilerExtensionVersion为1.0.3,Kotlin版本为1.5.31
            kotlinCompilerExtensionVersion = "1.0.3"
        }
    }
    
    没有该配置时,库编译阶段不会对@Composable注解做正确的插桩处理,生成的方法签名和宿主App编译时生成的调用签名不匹配,就会触发方法不存在异常。源码导入时会继承宿主App的编译配置,所以不会出问题。
  • 严格对齐库和宿主App的Kotlin版本、Compose编译器版本、Compose依赖版本,三者的版本映射关系是强制绑定的,任意一个版本不匹配都会导致@Composable函数插桩后的签名不一致。
  • 调整Compose相关依赖的声明方式,将implementation改为api,确保宿主App可以获取到一致的Compose依赖版本,避免间接依赖的版本冲突。
  • 用反编译工具(如Jadx)分别查看AAR包中screen方法的签名,以及宿主App编译后调用该方法的签名,确认两者的参数类型、数量是否一致,可快速定位是否为插桩差异导致的问题。
  • 检查maven发布配置是否遗漏了kotlin元数据信息,确保发布的AAR包含完整的kotlin编译元数据,避免宿主App编译时无法识别kotlin特有的函数签名信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:27:03