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

如何在Android Studio中生成.so文件并在其他Android应用中调用

嘿,作为刚入坑Android NDK的新手,你已经搞定了带C++支持的项目,这步超棒!接下来我一步步带你搞定生成.so文件,再在其他应用里调用它:

第一步:生成.so文件

你的项目是用Android Studio 3.0.1创建的带C++支持的项目,默认应该用CMake构建,咱们从配置到编译一步步来:

  • 确认NDK路径配置
    先打开Android Studio的File > Project Structure > SDK Location,检查Android NDK location是否已经设置。如果没装NDK,直接点旁边的Download按钮,选适配你Studio版本的NDK(比如r16b,和3.0.1兼容性较好)下载安装即可。

  • 检查CMakeLists.txt配置
    打开app模块下的CMakeLists.txt,确保里面有生成动态库的配置,核心是SHARED关键字(生成动态库.so,静态库是STATIC),示例配置如下:

cmake_minimum_required(VERSION 3.4.1)

# 定义你的C++库名称(比如叫prime-checker),指定为SHARED动态库
add_library(
        prime-checker
        SHARED
        src/main/cpp/your_prime_check_file.cpp) # 替换成你实际的C++文件路径

# 链接Android系统的log库(如果你的C++代码里用到log的话)
find_library(
        log-lib
        log)

# 把你的库和系统库链接起来
target_link_libraries(
        prime-checker
        ${log-lib})
  • 编译生成.so文件
    点击Android Studio右上角的Build > Make Project(或者直接点工具栏的Make图标),等待编译完成。
    编译后的.so文件会存放在app/build/intermediates/cmake/debug/obj/目录下,不同CPU架构(比如armeabi-v7a、arm64-v8a、x86)对应不同的子文件夹,每个文件夹里都有libprime-checker.so文件。
    如果需要生成release版本的.so,先切换到release变体(Build Variants面板),再执行Make Project,或者用Build > Generate Signed Bundle/APK生成签名包,对应的release版.so在app/build/intermediates/cmake/release/obj/目录下。
第二步:在其他Android应用中调用.so文件

拿到.so文件后,咱们在新应用里集成调用:

  • 复制.so文件到新项目
    在你的新Android项目中,创建src/main/jniLibs目录(如果没有的话),然后把刚才生成的各个架构的文件夹(比如armeabi-v7a)整个复制到jniLibs目录下,最终结构应该是:

    src/main/jniLibs/
        armeabi-v7a/libprime-checker.so
        arm64-v8a/libprime-checker.so
        x86/libprime-checker.so
    

    如果你只需要适配特定架构,只复制对应的文件夹就行,能减小APK体积。

  • 创建JNI接口类
    在新项目里创建一个Java类,用来声明native方法,注意要加载.so库,并且方法签名要和C++里的JNI方法完全匹配:

package com.yournewapp.package; // 换成你新项目的包名

public class PrimeChecker {
    // 加载.so库,库名是CMake里定义的"prime-checker",去掉前缀lib和后缀.so
    static {
        System.loadLibrary("prime-checker");
    }

    // 声明native方法,参数和返回值要和C++里的方法一致
    public native boolean isPrime(int number);
}
  • 在Activity中调用native方法
    现在就可以像调用普通Java方法一样使用这个native方法了,示例代码:
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText inputEt = findViewById(R.id.input_number);
        Button checkBtn = findViewById(R.id.check_btn);
        TextView resultTv = findViewById(R.id.result_tv);

        checkBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    int num = Integer.parseInt(inputEt.getText().toString());
                    PrimeChecker checker = new PrimeChecker();
                    boolean result = checker.isPrime(num);
                    resultTv.setText(result ? num + "是质数" : num + "不是质数");
                } catch (NumberFormatException e) {
                    resultTv.setText("请输入有效数字");
                }
            }
        });
    }
}
  • 关键注意点
    • 方法签名必须完全匹配:C里的JNI方法名格式是Java_包名_类名_方法名,包名里的.要换成_。比如你把native方法放在刚才的PrimeChecker类里,C里的方法应该是:
#include <jni.h>

extern "C" JNIEXPORT jboolean JNICALL
Java_com_yournewapp_package_PrimeChecker_isPrime(JNIEnv* env, jobject thiz, jint number) {
    // 你的质数判断逻辑,和原项目里的一致
    if (number <= 1) return JNI_FALSE;
    for (int i = 2; i * i <= number; ++i) {
        if (number % i == 0) return JNI_FALSE;
    }
    return JNI_TRUE;
}
  • 确保新项目的minSdkVersion和原项目兼容,不然可能出现加载库失败的情况。
  • 如果运行时出现UnsatisfiedLinkError,先检查库名是否正确、方法签名是否匹配、.so文件的架构是否和测试设备匹配。

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

火山引擎 最新活动