升级AGP 7.4.2至8.x后第三方含.so的Jar包编译报错求助
解决方案:AGP 8.x 兼容第三方带Native库的Jar包
核心问题原因
AGP 8.x 对Jar包中Native库的结构校验逻辑做了升级:原AGP 7.x会自动识别Jar内lib/<ABI>/libxxx.so的结构,但AGP 8.x解压Jar时会移除lib目录,导致校验逻辑误将armeabi-v9a这类ABI目录当成文件名,抛出is not an ABI错误;如果手动去掉Jar里的lib目录,AGP能通过校验,但打包时so不会被放到APK的lib/<ABI>目录,运行时就会触发UnsatisfiedLinkError。
下面是三种可行的解决方法:
方法一:用Gradle任务重新打包Jar(推荐)
通过Gradle任务自动修改第三方Jar的结构,将lib/<ABI>/so移动到AGP 8.x识别的jni/<ABI>/so目录,同时保留原类文件结构:
在app模块的build.gradle.kts(Groovy写法类似)中添加以下代码:
// 定义修复第三方Jar的任务 tasks.register<Copy>("fixThirdPartyJar") { val inputJar = file("libs/your-third-party-lib.jar") // 替换成你的第三方Jar路径 val tempDir = file("$buildDir/temp/fixed-lib") val outputJar = file("$buildDir/outputs/fixed-third-party-lib.jar") // 第一步:解压原Jar到临时目录 from(zipTree(inputJar)) into(tempDir) // 第二步:移动so文件到jni目录下的对应ABI文件夹 doLast { // 遍历所有so文件 tempDir.walkTopDown().filter { it.extension == "so" }.forEach { soFile -> val abiName = soFile.parentFile.name // 获取armeabi-v9a这类ABI名称 val targetDir = file("$tempDir/jni/$abiName") targetDir.mkdirs() // 创建目标目录 soFile.copyTo(targetDir.resolve(soFile.name), overwrite = true) // 移动so soFile.delete() // 删除原文件 } // 删除原有的lib目录 file("$tempDir/lib").deleteRecursively() } // 第三步:重新打包成新的Jar doLast { zip(outputJar).from(tempDir) } } // 让编译任务依赖修复任务,确保编译前先处理Jar tasks.named("compileDebugKotlin") { dependsOn("fixThirdPartyJar") } tasks.named("compileReleaseKotlin") { dependsOn("fixThirdPartyJar") } // 替换依赖:使用修复后的Jar,注释掉原来的Jar依赖 dependencies { // implementation(files("libs/your-third-party-lib.jar")) implementation(files("$buildDir/outputs/fixed-third-party-lib.jar")) }
执行./gradlew fixThirdPartyJar生成修复后的Jar,再正常编译项目即可。
方法二:将Jar转换为标准AAR包
AAR是Android库的标准格式,AGP对其Native库结构的支持更稳定,步骤如下:
- 创建一个临时目录,比如
third-party-aar - 在该目录下创建
jni文件夹,将第三方Jar中lib目录下的所有ABI子目录(如armeabi-v9a)复制到jni下 - 将第三方Jar中的类文件单独打包成
classes.jar(可以用jar xf your-third-party-lib.jar解压后,再用jar cf classes.jar com/打包类目录) - 在
third-party-aar下创建空的AndroidManifest.xml(内容至少为<manifest package="com.your.thirdparty"/>) - 将
third-party-aar目录下的所有文件打包成.aar(用zip -r your-third-party-lib.aar .) - 将生成的AAR放到项目
libs目录,替换原来的Jar依赖:
dependencies { implementation(files("libs/your-third-party-lib.aar")) }
方法三:配置AGP强制识别Native库路径
如果不想修改Jar包,可以尝试配置AGP的sourceSets和packagingOptions,强制指定Native库的来源路径:
android { sourceSets { main { jniLibs.srcDirs("libs/your-third-party-lib.jar!/lib") } } packagingOptions { jniLibs { pickFirsts.add("lib/**/*.so") } } }
注意:这个方法在部分AGP 8.x版本中可能不生效,因为Gradle解压Jar时仍会处理lib目录,优先推荐前两种方法。
内容的提问来源于stack exchange,提问作者bj0
相关产品推荐
相关产品推荐

