Android新项目使用.so文件是否需沿用原包名?多设备.so生成与使用疑问
关于生成多架构.so文件及复用.so包名问题的解答
嘿,针对你遇到的两个问题,我给你梳理下实际开发里的解决方案:
一、生成适配多设备的不同架构.so文件
你之前从APK里只解压出一个.so,大概率是因为原项目只配置编译了一种CPU架构。要生成多架构的.so,你需要在Module级的build.gradle文件里做如下配置:
- 找到
android块下的defaultConfig,添加ndk配置,指定要支持的ABI架构:
android { defaultConfig { // 其他原有配置... ndk { // 按需选择,主流推荐这几个覆盖绝大多数设备 abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } }
- 重新编译项目(点击Android Studio的Build -> Make Project),编译完成后,你可以在项目的
build/intermediates/ndkBuild/debug/obj/local/目录下找到对应每个架构的文件夹,里面就有各自的.so文件。
现在安卓设备主流是arm架构:armeabi-v7a适配32位arm设备,arm64-v8a适配64位arm设备;x86和x86_64主要给模拟器或少数x86架构设备使用,你可以根据需求取舍。
二、新项目复用.so是否需要遵循原包名?
答案是不需要强制遵循原包名,但有个关键细节要注意:
如果原项目的JNI函数是用静态注册的方式(也就是函数名是Java_原包名_类名_函数名这种格式,比如Java_com_example_mydemo_MainActivity_checkPrime),直接换包名的话,新项目的Java类调用Native函数时会找不到对应方法——因为JNI是通过这个硬编码的函数名来匹配的。
解决方法有两种:
- 方法一:在新项目里创建和原项目完全一致的包名+类名来调用.so,比如原项目是
com.example.mydemo.MainActivity,新项目也创建这个路径的类,就能匹配上静态注册的函数名。 - 方法二:修改原项目的JNI代码,改用动态注册的方式,这样Native函数的名字就不用依赖Java类的包名和类名了,新项目里可以随便用自己的包名和类名调用。动态注册的核心是在
JNI_OnLoad函数里注册Java方法和Native函数的映射关系,示例代码大概是这样:
#include <jni.h> #include <string> // 你的质数判断逻辑 jboolean checkPrime(JNIEnv* env, jobject thiz, jint num) { if (num <= 1) return JNI_FALSE; for (int i = 2; i * i <= num; i++) { if (num % i == 0) return JNI_FALSE; } return JNI_TRUE; } static const JNINativeMethod methods[] = { {"checkPrime", "(I)Z", (void*)checkPrime} }; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = nullptr; if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) { return -1; } // 替换成新项目中调用Native方法的类的全限定名 jclass cls = env->FindClass("com/your/new/package/YourActivity"); env->RegisterNatives(cls, methods, sizeof(methods)/sizeof(methods[0])); return JNI_VERSION_1_6; }
修改后重新编译出的.so,就能在新项目里自由指定包名和类名调用了。
内容的提问来源于stack exchange,提问作者PPD




