0%

安卓jni相关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
1️⃣ 什么是 JNI

JNI(Java Native Interface)是 Java 调用 C/C++ 代码 的接口。
在 Android 上,JNI 通常用于:

大量数学运算、图像处理、音视频编解码、机器学习推理等 视频滤镜、OpenCV 图像处理
比如操作蓝牙、摄像头底层驱动、DSP 加速等

调用现有 C/C++ 库

访问底层硬件或系统 API(超出 Java 层能力)

Android 本身用 Java 访问底层功能不方便,或者第三方库只提供 C 接口。
典型例子:BaiduMap、腾讯 IM、游戏引擎。


2️⃣ JNI 的基本流程
步骤 1:创建 native 方法

在 Java/Kotlin 中声明一个 native 方法:

public class NativeLib {
static {
System.loadLibrary("mylib"); // 加载 .so
}

// 声明 native 方法
public native int addNumbers(int a, int b);
}

步骤 2:生成 C/C++ 函数签名

JNI 方法在 C/C++ 层定义时,需要 特定签名:

#include <jni.h>

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_myapp_NativeLib_addNumbers(JNIEnv *env, jobject thiz, jint a, jint b) {
return a + b;
}


JNIEXPORT 和 JNICALL 是宏,确保函数正确导出

JNIEnv* 是 JNI 环境指针,用于调用 Java 方法或访问对象

jobject thiz 对应 Java 的实例对象(非静态方法)

参数类型对应 jint, jstring, jobject 等 JNI 类型

步骤 3:构建 .so 库

使用 CMake 或 ndk-build:

CMake 示例(CMakeLists.txt):

cmake_minimum_required(VERSION 3.4.1)

add_library(mylib SHARED native-lib.cpp)

find_library(log-lib log)

target_link_libraries(mylib ${log-lib})


然后在 build.gradle 中集成:

externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}

步骤 4:调用
NativeLib lib = new NativeLib();
int sum = lib.addNumbers(3, 5);
Log.d("JNI", "sum = " + sum);

3️⃣ 常用 JNI 类型映射
Java 类型 JNI 类型
int jint
long jlong
float jfloat
double jdouble
boolean jboolean
byte[] jbyteArray
String jstring
Object jobject
int[] jintArray
4️⃣ JNI 常用函数

字符串转换

const char* str = env->GetStringUTFChars(jstringObj, 0);
// 使用完释放
env->ReleaseStringUTFChars(jstringObj, str);


数组操作

jint *arr = env->GetIntArrayElements(jintArrayObj, 0);
// 操作数组
env->ReleaseIntArrayElements(jintArrayObj, arr, 0);


调用 Java 方法

jclass cls = env->GetObjectClass(obj);
jmethodID mid = env->GetMethodID(cls, "callback", "(I)V");
env->CallVoidMethod(obj, mid, 100);