Android项目添加预编译NDK(.so)库报找不到符号错误如何解决
问题解决步骤
首先明确:编译阶段报cannot find symbol(找不到符号)是Java代码引用缺失导致的,和.so文件的加载配置没有直接关系,不要在Gradle JNI配置上浪费排查时间,按以下顺序排查即可:
1. 优先恢复被误删的Java层JNI接口类
你移除C源码子项目的时候,大概率把声明native方法的Java类、JNI对应的包装类一起删掉了:
- .so文件只是C/C++代码编译后的二进制实现,本身不包含Java类定义,所有和JNI方法对应的Java类必须完整保留在项目中
- 这些Java类的包名、类名、方法名、方法参数/返回值类型必须和原项目完全一致,哪怕改一个字符,要么编译期报找不到符号,要么运行时触发
UnsatisfiedLinkError - 从原项目的版本提交记录里找回这些类,放回原本的包路径下即可解决编译期找不到符号的问题
2. 补全Gradle配置避免运行时加载so失败
等编译报错解决后,打开app模块下的build.gradle(注意是app目录下的构建文件,不是项目根目录的),在android{}配置块中补充以下内容,保证构建时能正确打包你放入的预编译so:
android { // 保留你原本已有的compileSdk、defaultConfig、buildTypes等配置不要动 sourceSets { main { // 指定jniLibs目录为你存放so的路径 jniLibs.srcDirs = ['src/main/jniLibs'] } } defaultConfig { ndk { // 指定打包的ABI架构,你当前只有armeabi-v7a的so就只加这个 abiFilters 'armeabi-v7a' // 如果后续要支持64位架构,需要单独获取对应arm64-v8a版本的so放到对应目录,再把架构名加到这里 } } }
- 你当前存放so的路径
app/src/main/jniLibs/armeabi-v7a/libxcore.so是符合规范的,不要额外多套目录层级 - 注意不要把so放错ABI文件夹,比如把armeabi-v7a的so放到arm64-v8a目录下,会导致运行时加载失败
3. 保留so加载逻辑
原项目中一定存在so加载的代码,一般是在JNI接口类的静态代码块中,不要删除这段逻辑:
static { // 注意参数是so文件名去掉lib前缀和.so后缀,libxcore.so对应传入"xcore" System.loadLibrary("xcore"); }
要保证这段代码在你调用任何native方法之前执行到。
补充说明
如果你是从加固过的APK中提取的so,可能存在so被裁剪、加密的情况,这类问题只会在运行时触发报错,不会导致编译期的找不到符号问题。
内容的提问来源于stack exchange,提问作者user1055568
相关产品推荐
相关产品推荐

