android jni教程简书,Android端学习JNI入门篇(附demo)

这篇内容适合哪些人:

1、Android研发有一定的安卓基础并且想要学习JNI编程的人员

文章最后附Demo

工程目录结构:

b756ab456cd5

image.png

本章内容概要

1、基于CMake ,NDK

2、配置CMake

3、定义JNI 接口类(用于交互jni)

4、编写JNI层的被调用方法

5、JNI 生成 so 库

6、编译运行

一、CMake 下载:

b756ab456cd5

image.png

二、CMake配置

1、在build.gradle 文件下指定CMakeLists.txt 的路径

//指定你的CMakeLists文件的位置

externalNativeBuild {

cmake {

path "CMakeLists.txt"

}

}

2、指定生成的so库类型(按需配置)

externalNativeBuild {

cmake {

cppFlags ""

abiFilters 'armeabi-v7a'

}

}

三、定义JNI 接口类(用于交互jni)

b756ab456cd5

jni接口类定义

四、编写JNI层的被调用方法

目标:实现一个简单的jni函数sum(int a, int b),返回a+b的结果。一个稍微复杂点的jni函数twoSum(int nums[], int target),实现的是leetcode上的一个题目TwoSum,内容是给定数组及目标数字,返回符合目标数字的2个数的下标(数组类型)

1、首先建立一个demo.h

该文件作为c++的头文件,声明要实现的函数

#ifndef JNIDEMO_DEMO_H

#define JNIDEMO_DEMO_H

#endif //JNIDEMO_DEMO_H

class Demo{

public:

Demo();

int sum(int a,int b);

int *twoSum(int nums[],int target);

};

2、建立demo.cpp文件实现算法。

该文件实现头文件声明的函数。

#include

#include "demo.h"

Demo::Demo() {

}

int Demo::sum(int a, int b) {

return a + b;

}

int* Demo::twoSum(int nums[], int target) {

int length = sizeof(nums);

if (length < 2){

return nullptr;

}

int *result = nullptr;

for (int i = 0; i < length; i++){

for (int j = i + 1; j < length; j++){

if (nums[i] + nums[j] == target){

result = new int[2];

result[0] = i;

result[1] = j;

break;

}

}

}

return result;

}

3、创建demo-lib.cpp文件

这个文件里面放的是我们的jni代码,暂时还不用写先,因为现在不想手动写jni函数名,至于为什么叫demo-lib(.cpp文件名加-lib),一句话,官方推荐命名格式以及样例也是这样命名的。

4、修改CMakeLists.txt

跟之前native-lib文件一样,新加的库使用add_library指令。我们直接复制native-lib的add_library添加到下面,将native-lib改成我们的demo-lib.cpp(即第3点创建的jni代码文件)。

a、先添加库,用add_library(...)

b756ab456cd5

添加自定义库

b、将我们新增的库依赖进去

b756ab456cd5

增加依赖

c、配置一个so库输出的路径

在CMakeLists.txt内

#设置生成的so动态库最后输出的路径

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI})

至此,CMakeLists.txt的修改就完成了,下面我们来编写jni层的代码。

在demo.cpp文件内编写被调用的方法:

注意点:

1、jni方法的命名

2、c++中的twoSum函数需要传递一个数组,而java的数组是不能直接作为参数传递给c++函数的,因此需要Jni作一层转换

最终实现:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

#include

#include

#include "demo.cpp"

/* Header for class com_albert_demo_util_NativeMethodSum */

#ifndef _Included_com_albert_demo_util_NativeMethodSum

#define _Included_com_albert_demo_util_NativeMethodSum

#ifdef __cplusplus

extern "C" {

#endif

/****

*

* 将Java数组转化成C++ 指针数组

*/

jint * getIntArrayFromJava(JNIEnv *env,jintArray j_array){

jint *c_array;

jint arr_len;

arr_len = (*env).GetArrayLength(j_array);

c_array = (jint*)malloc(sizeof(jint) * arr_len);

//初始化

memset(c_array,0,sizeof(jint)*arr_len);

//获取数组

c_array = (*env).GetIntArrayElements(j_array,NULL);

return c_array;

}

/*

* Class: com_albert_demo_util_NativeMethodSum

* Method: sum

* Signature: (II)I

*/

JNIEXPORT jint JNICALL Java_com_albert_demo_util_NativeMethodSum_sum

(JNIEnv *, jclass, jint a, jint b){

Demo demo = Demo();

jint result = demo.sum(a,b);

return result;

}

/*

* Class: com_albert_demo_util_NativeMethodSum

* Method: twoSum

* Signature: ([II)I

*/

JNIEXPORT jintArray JNICALL Java_com_albert_demo_util_NativeMethodSum_twoSum

(JNIEnv *env, jobject, jintArray nums, jint target){

Demo demo = Demo();

jint *result = demo.twoSum(getIntArrayFromJava(env,nums),target);

if (result == nullptr){

return nullptr;

}

// C++返回的数组为指针形式,也不能直接返回给java,所以通过Jni复制一个jintArray数组返回给java

jintArray array = (*env).NewIntArray(2);

(*env).SetIntArrayRegion(array,0,2,result);

return array;

}

#ifdef __cplusplus

}

#endif

#endif

五、JNI 生成 so 库

工程clean、build 即可生成so库

六、编译运行

b756ab456cd5

编译运行方法使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值