You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android新项目使用.so文件是否需沿用原包名?多设备.so生成与使用疑问

关于生成多架构.so文件及复用.so包名问题的解答

嘿,针对你遇到的两个问题,我给你梳理下实际开发里的解决方案:

一、生成适配多设备的不同架构.so文件

你之前从APK里只解压出一个.so,大概率是因为原项目只配置编译了一种CPU架构。要生成多架构的.so,你需要在Module级的build.gradle文件里做如下配置:

  1. 找到android块下的defaultConfig,添加ndk配置,指定要支持的ABI架构:
android {
    defaultConfig {
        // 其他原有配置...
        ndk {
            // 按需选择,主流推荐这几个覆盖绝大多数设备
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }
}
  1. 重新编译项目(点击Android Studio的Build -> Make Project),编译完成后,你可以在项目的build/intermediates/ndkBuild/debug/obj/local/目录下找到对应每个架构的文件夹,里面就有各自的.so文件。

现在安卓设备主流是arm架构:armeabi-v7a适配32位arm设备,arm64-v8a适配64位arm设备;x86x86_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

火山引擎 最新活动