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[] |
热门推荐
茶树品种改良与茶叶品质提升种植环境监测
河南医学类大学专业深度解析:录取分数线、就业前景与薪资水平全览
装修小白看过来,板材分类及环保级别大解析,看完不踩坑
“水上春耕”大幕开启|冰城“兴虾匠人”水里捞金
揭秘脑白质病变:病因、症状与预防全攻略
李清照南渡:词中才女的流离岁月
UFC轻量级十年:十年水流东,十年水流西
焊工职业指南:从入门到高级的全面解析
如何选择合适的境外公司注册地址:全方位指南
微单相机怎么选?一文读懂,解锁你的摄影新世界!
吐蕃与唐朝:交织的和平与冲突
体癣和湿疹的区别与治疗方法
矩阵数据分析法在商业决策中的应用与优势
掌握运营成功的关键:用户需求、目标设定与策略执行全解析
全面解析CVT无级变速箱,为何CVT技术成为现代汽车新宠?
中国新增6处世界地质公园 总数达47处居全球首位
揭秘眼皮抽搐跳动的原因与应对方法
玫瑰花茶——美容补气血养颜
狗狗误食药物怎么办?及时处理与应急措施指南
SQL Server数据库表操作完全指南:创建、修改、删除与数据处理
2025中国足球职业联赛纪律准则发布:明确禁止各种歧视行为
河北,省会频繁变更数十次,直到周总理批示才真正固定下来
C++20 中位移位运算符的统一行为:深入解析与实践指南
Excel表格中的中文汉字变成乱码的原因及解决方法
理赔排除责任:详细解析保险理赔中的除外责任
探索被你点赞的朋友圈,揭秘点赞行为背后的社交密码与情感联结
工伤八级伤残赔偿标准
鸡肉与鸭肉营养大比拼:哪种肉更适合自己?
杨博光:中国1月CPI数据反弹,如何影响后市投资思路?
股票风险评估:方法与局限性