Android 如何生成 so 库

前言

Android 开发中难免会使用到 jni,实践中虽然简单,但也还是有不少坑点,本文将十分详细介绍在生成 so 库过程中细节。

步骤

创建 Native C++ 项目

这里新建了一个名为 SoTest 的项目,包名为 com.me.sotest,这里强调一下包名,因为大部分的坑点都出在包名上了。

系统为我们自动生成了一个 MainActivity.java 类。并在该类里加载了 sotest 库,然后调用了 stringFromJNI() 方法。

java 复制代码
package com.me.sotest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

import com.me.sotest.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'sotest' library on application startup.
    static {
        System.loadLibrary("sotest");
    }

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // Example of a call to a native method
        TextView tv = binding.sampleText;
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'sotest' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

该 native 方法是定义在 native-lib.cpp 中的。

C++ 复制代码
#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_me_sotest_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

构建得到 so 文件

当 build 后,会在SoTest\app\build\intermediates\merged_native_libs\debug\mergeDebugNativeLibs\out\lib\arm64-v8a 路径下生成一个 libsotest.so 文件,注意这里的 cpu 架构是 arm64-v8a。

目前看起来一切都很完美,成功的获得了 so 文件。但我们仔细看看这个 jni 方法的签名 Java_com_me_sotest_MainActivity_stringFromJNIcom_me_sotest 对应的是我们的包名(com.me.sotest),MainActivity 显然是对应类名。

当调用方使用我们的 jni 方法时,为了与我们的方法签名对应,就只能在包为 com.me.sotest 且类名为 MainActivity 的类里使用,这就不太科学,MainActivity 是有特殊含义的,我们不如把 jni 方法专门放到另外的类里去。

新增 JniMethod 类

现在我们新增一个 java 类叫做 JniMethod。

java 复制代码
package com.me.sotest;

public class JniMethod {
    // Used to load the 'sotest' library on application startup.
    static {
        System.loadLibrary("sotest");
    }

    public static native String stringFromJNI();
}

然后可以让 Android Studio 帮我们生成 jni 函数的声明,我们再补全定义即可,此时函数的签名变为了 Java_com_me_sotest_JniMethod_stringFromJNI,看起来似乎更合适。

C++ 复制代码
#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_me_sotest_JniMethod_stringFromJNI(JNIEnv *env, jclass clazz) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

对应的 MainActivity 中的调用改动如下,跑了一下没问题,且也得到了一个 libsotest.so

java 复制代码
TextView tv = binding.sampleText;
tv.setText(JniMethod.stringFromJNI());

至此,so 文件的生成过程就结束了,下一节我们将测试我们的 so 文件能否正常被使用。

Android 如何使用 so 库 - 掘金 (juejin.cn)

相关推荐
pengyu19 分钟前
【Kotlin 协程修仙录 · 大乘境 · 初阶】 | 跳出三界:协程在 KMP 与后端开发中的跨平台之道
android·kotlin
XiaoLeisj24 分钟前
Android Memory Profiler:堆内存指标、内存抖动与泄漏定位
android·性能优化·内存抖动·内存泄露·memory profiler
未来猫咪花26 分钟前
Everything is ViewModel:让状态管理回到对象世界
android·flutter·ios
古法安卓32 分钟前
Android-重启流程源码解析
android·java·android studio
协议的旁观者2 小时前
Android 高级逆向实战(一):对抗 360 企业加固,Native 抽取还原与 Activity 生命周期重建
android
mmsx4 小时前
osmdroid 屏幕坐标与测量坐标互转:中心点+比例尺仿射换算
android·源码·地图·osmdroid
00后程序员张4 小时前
Android证书绑定抓包失败?Android SSL Pinning绕过实战指南
android·网络协议·计算机网络·网络安全·adb·https·ssl
杉氧4 小时前
页面栈与路由:React Navigation 与 Expo Router 深度实践
android·前端·react native
XiaoLeisj5 小时前
Jetpack Compose 知识点
android·kotlin·android jetpack·compose
又见情义6 小时前
RK3568 Android 13开机时间优化-系统应用裁剪实践
android