Android JNI入门:概念、应用场景及实战Demo
创作时间:
作者:
@小白创作中心
Android JNI入门:概念、应用场景及实战Demo
引用
CSDN
1.
https://blog.csdn.net/wenzhi20102321/article/details/136291126
JNI(Java Native Interface)是Android开发中的一个重要技术,它允许Java代码调用C/C++代码,从而实现更高效、更底层的功能。本文将详细介绍JNI的基本概念、应用场景,并通过一个简单的Demo展示如何在Android项目中使用JNI。
JNI的简单介绍
JNI
JNI全称Java Native Interface,即Java本地方法接口。它提供了一种Java字节码调用C/C++的解决方案。这里的"本地"指的是C/C++,因此JNI可以理解为Java调用C/C++的方案技术。
NDK
NDK(Native Development Kit)是Android的本地开发工具集。它允许开发者将C或C++代码编译成Android可识别的格式。NDK描述的是工具集,其主要功能是将C/C++代码编译成Java可以识别的模块。
Jni的开发背景
JNI的主要应用场景包括:
- 需要调用Java语言不支持的依赖于操作系统平台特性的一些功能
- 在程序对时间敏感或对性能要求特别高的情况下,使用更底层的语言来提高运行效率
- 音视频开发涉及到的音视频编解码需要更快的处理速度
- 整合一些以前的非Java语言开发的系统
- 使用早期实现的C/C++语言开发的一些功能或系统
JNI在Android开发里的主要应用场景
JNI在Android开发中主要应用于以下场景:
- 音视频开发
- 热修复
- 插件化
- 逆向开发
JNI的简单Demo
1. Demo主要界面和效果展示
在Android Studio中新建一个JNI项目,完成后即可创建一个最简单的JNI项目。可以直接点击运行在模拟器上或者连接的Android设备,即调用了CPP文件返回字符串并在Android界面显示Hello World,项目代码就包含了一个最基本的jni架构代码。
本文Jni 示例Demo实现加减乘除运算,以及字符串拼接,如下图所示:
2. CMake编译加载文件
CMakeLists.txt 大致内容如下:
cmake_minimum_required(VERSION 3.18.1) //版本
project("jnidemo") //加载的项目
//至少三个参数,参数直接没有标点符号哦,用换行隔开
第一个参数表示加载的库文件(动态.so/静态.a)
第二个参数表示库加载的方式,有动态SHARED,有静态STATIC(极少用)
后面的参数可以N个,表示要加载的CPP文件,也可以用集合指向
add_library(
jnidemo
SHARED
native-lib.cpp
TestCPlus.cpp
)
//下面两个是关联的,简单示例中不写也是可以正常运行的
find_library(
log-libxx
log)
target_link_libraries(
jnidemo
${log-libxx})
3. MainActivity.java
public class MainActivity extends AppCompatActivity {
//加载so库名称的代码
// Used to load the 'jnidemo' library on application startup.
static {
System.loadLibrary("jnidemo");
}
//界面显示代码省略
//jni方法,加减乘除,最后一个参数是操作类型的字节数据类型
public native float operationNumberFromJNI(float parameter1, float parameter2, char type);
//jni方法,字符串拼接
public native String addStringFromCPlusJNI(String parameter1, String parameter2);
}
4. native-lib.cpp
#include <jni.h>
#include <string>
//创建Jni工程最简单的方法,返回一个字符串
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jnidemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "简易计算器";
return env->NewStringUTF(hello.c_str());
}
//Jni增删改查的实现,因为float是基本数据类型,所以不需要转换就可以直接操作
extern "C"
JNIEXPORT jfloat JNICALL
Java_com_example_jnidemo_MainActivity_operationNumberFromJNI(JNIEnv *env, jobject thiz, jfloat parameter1,
jfloat parameter2,jchar type) {
switch (type) {
case '+':
return parameter1 + parameter2;
case '-':
return parameter1 - parameter2;
case '*':
return parameter1 * parameter2;
case '/':
return parameter1 / parameter2;
}
return parameter1 + parameter2;
}
//字符串的拼接,方法有N种,String不是基本数据类型,需要进行类型转换后才能进行操作
extern "C" JNIEXPORT _jstring * JNICALL
Java_com_example_jnidemo_MainActivity_addStringFromCPlusJNI(JNIEnv *env, jobject thiz,
jstring parameter1,
jstring parameter2) {
char *c1 = (char *) (env->GetStringUTFChars(parameter1, JNI_FALSE));
char *c2 = (char *) (env->GetStringUTFChars(parameter2, JNI_FALSE));
char *res = strcat(c1, c2); //拼接两个字符串
//释放c1和c2
delete(c1);
delete(c2);
return env->NewStringUTF(res);
}
其他
1. Jni基础的几点内容
- 记住编写关键流程
- 类的静态方法中loadLibrary
- 类中定义native方法
- 类的使用中调用jni方法
- cpp文件中编写jni实现
- CMakeList.txt 的基本规则
- jni.cpp文件中的方法命名
- Java到jni.cpp文件中类型转换
- 有一定的c/c++语言基础
2. java数据类型与jni类型映射表
Java 类型 | JNI本地类型 | 描述 |
|---|---|---|
boolean | jboolean | C/C++8位整型 |
byte | jbyte | C/C++带符号的8位整型 |
char | jchar | C/C++无符号的16位整型 |
short | jshort | C/C++带符号的16位整型 |
int | jint | C/C++带符号的32位整型 |
long | jlong | C/C++带符号的64位整型e |
float | jfloat | C/C++32位浮点型 |
double | jdouble | C/C++64位浮点型 |
Object | jobject | 任何Java对象,或者没有对应java类型的对象 |
Class | jclass | Class对象 |
String | jstring | 字符串对象 |
Object[] | jobjectArray | 任何对象的数组 |
boolean[] | jbooleanArray | 布尔型数组 |
byte[] | jbyteArray | 比特型数组 |
char[] | jcharArray | 字符型数组 |
short[] | jshortArray | 短整型数组 |
int[] | jintArray | 整型数组 |
long[] | jlongArray | 长整型数组 |
float[] | jfloatArray | 浮点型数组 |
double[] | jdoubleArray | 双浮点型数组 |
3. Java签名类型 常用的数据类型及对应字符
Java 类型 | Jni中表示的符号 | 备注 |
|---|---|---|
boolean | Z | 不是类型首字母大写 |
byte | B | |
char | C | |
short | S | |
int | I | |
long | L | |
float | F | |
double | D | |
void | V | |
objects对象 | Lfully-qualified-class-name;L全类名; | 记得最后是有分号的 |
Arrays数组 | [array-type [数组类型 | |
methods方法 | (argument-types)return-type(参数类型)返回类型 |
4. JNI类型api调用表格
方法、变量修饰类型表格
函数描述 | 描述 |
|---|---|
GetFieldID | 得到一个实例的域的ID |
GetStaticFieldID | 得到一个静态的域的ID |
GetMethodID | 得到一个实例的方法的ID |
GetStaticMethodID | 得到一个静态方法的ID |
数组对应变量类型api表格
函数描述 | nativie数据对象 | nativie类型 | Java数据类型 |
|---|---|---|---|
GetBooleanArrayElements | jbooleanArray | jboolean | boolean[] |
GetByteArrayElements | jbyteArray | jbyte | byte[] |
GetCharArrayElements | jcharArray | jchar | char[] |
GetShortArrayElements | jshortArray | jshort | short[] |
GetIntArrayElements | jintArray | jint | int[] |
GetLongArrayElements | jlongArray | jlong | long[] |
GetFloatArrayElements | jfloatArray | jfloat | float[] |
GetDoubleArrayElements | jdoubleArray | jdouble | double[] |
热门推荐
日本过境签证申请条件要求,日本过境签证有效期多少天?
中国假期制度75年变迁:单休改双休用了45年,除夕重回法定假期
期望与现实:职场心态调整策略
智慧茶园环境数据监测系统:功能、技术与应用全解析
深交所公告:调入!一度大涨超90%!
中国内地女演员陈芳彤
砒霜治疗白血病:一段亟待还原的当代医学史
《红楼梦》中林黛玉的人物形象分析
考研数学三学习方法:从基础到实战的全方位备考指南
超详细的雅思备考攻略!附全科学习建议
考研英语作文的备考提分技巧
180余位留学人员齐聚北京 共话人工智能未来趋势
Hive 与 TiDB 在大数据解析场景中的对比分析
园林专业十大就业方向:从景观设计到公务员
建筑常用规范及验收规范:确保工程质量与安全
梅超风的悲剧:从师门背叛到疯狂之路
梅超风的悲剧:爱情与背叛的疯狂旋律
国产车迅猛崛起:政策支持与技术创新击败日系车的秘密
中国汽车芯片国产化率达15%,业界:不可低估竞争力
《怪物猎人 荒野》发售首日情况与多平台表现分析!
追寻传统文化瑰宝:探索民间故事与传说的奥秘
加强腹斜肌和核心肌群的日常锻炼
确认气胸症状的方法有哪些
刑事模拟法庭案例:探索司法实践与法学教育的深度融合
新时代教师师德师风的挑战与应对
怀孕高血糖会增加哪些健康风险?
半导体激光器的分类及其应用
如何从粗铱中提取高纯度的铱金
凤冠霞帔中的“霞帔”是什么
肝下垂是什么原因