序章:
1.本篇是JNI入门教程的第四篇,完整教程连接如下:
2.本篇主要考察的是各种数据类型的转换,要完成的需求如下:
在java中传入一个对象,JNI中修改这个对象的属性值,然后返回到安卓中展示该对象的属性值。
一。流程步骤
安卓中调用jni主要包含以下几个步骤:
1.在java中声明引用。
2.在jni中创建对应的h文件和cpp文件。
3.在CMakeLists中进行声明,声明之后jni中的方法才能被java外部调用。
4.java层中构造各种数据类型,然后传给JNI进行调用。
二。在java中创建声明类
1.JAVA中生命好JNI调用方法。
package com.xt.client.jni;
import com.xt.client.model.JavaModel;
public class CalculationJNITest {
static {
System.loadLibrary("Calculation");
}
/**
* JNI修改属性值
* @param javaModel
* @return
*/
public native Object updateObjectValue(JavaModel javaModel);
}
2.创建JAVA类,这个类传入到JNI中,然后在JNI中修改属性值。
public class JavaModel {
public String name;
public int age;
public String moblie;
public void printJavaLog() {
Log.i("lxltest", "java log");
}
public String getMoblie() {
return moblie;
}
public void setMoblie(String moblie) {
this.moblie = moblie;
}
}
三。在jni中创建h和cpp文件
1,2流程和上一篇文章中流程是一样的,就不详细介绍了。
1.创建com_xt_client_jni_CalculationJNITest.h文件
2.创建CalculationNative.cpp文件
3.h文件中进行方法的声明
h中声明方法:
JNIEXPORT jobject JNICALL Java_com_xt_client_jni_CalculationJNITest_updateObjectValue
(JNIEnv *, jobject, jobject);
4.CalculationNative.cpp中创建具体实现方法:
方法如下:
JNICALL jobject
Java_com_xt_client_jni_CalculationJNITest_updateObjectValue(JNIEnv *env, jobject instance,
jobject model) {
//1
jclass cls = env->GetObjectClass(model);
//2
jfieldID fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
//3.
jstring jstr = static_cast<jstring>(env->GetObjectField(model, fid));
const char *str = env->GetStringUTFChars(jstr, NULL);
//4
env->ReleaseStringUTFChars(jstr, str);
//5
jstr = env->NewStringUTF("lll");
//6
env->SetObjectField(model, fid, jstr);
//7
jmethodID id = env->GetMethodID(cls, "printJavaLog", "()V");
//8
env->CallVoidMethod(model, id);
//9
id = env->GetMethodID(cls, "setMoblie", "(Ljava/lang/String;)V");
//10
jstring mobile = env->NewStringUTF("187000000");
//11
env->CallVoidMethod(model, id, mobile);
//12
id = env->GetMethodID(cls, "getMoblie", "()Ljava/lang/String;");
//13
auto moblie2 = (env->CallObjectMethod(model, id));
LOGI("getMoblie:%s", env->GetStringUTFChars(static_cast<jstring>(moblie2), 0));//
return model;
}
这里我们主要做了如下几步:
1.通过JNIEnv提供的方法,获取传过来对象的class类。
2.通过JNIEnv提供的方法,获取class中name的属性ID。
3.获取model中name的属性值。
4.释放name的属性值字符串。
5.jstr字符串赋值为lll
6.通过JNIEnv提供的方法,把jstr赋值类model对象的name属性。这里是通过JNI直接修改对象属性值。
7.获取cls类的printJavaLog方法的ID,
8.根据上一步获取的ID,调用printJavaLog方法
9.获取JavaModel方法中的setMoblie方法的方法ID
10.构造jstring类型的字符串moblie
11.调用setMoblie方法,传入上一步构造的字符串。这里就是通过jni调用java的方法进行赋值。
12.获取getMoblie方法的方法ID
13.JNI中调用getMoblie方法获取返回值,然后在JNI中进行打印。
四。CMakeLists中做好声明
和上一篇中都是一样的。
1.创建文件Cmake文件:
src同级目录下,创建CMakeLists.txt文件,内容如下:逻辑和上一篇文章是一样的。
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library(
Calculation
SHARED
src/main/jni/CalculationNative.cpp)
2.CMakeLists中创建log的连接
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library. 指定连接的目标库
Calculation
# Links the target library to the log library
# included in the NDK.
${log-lib})
3.gradle中做好声明
app的build.gradle文件中,在android{}模块下,添加如下声明:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
// version "3.10.2"
}
}
五。验证效果
1.java中写好测试以及调用代码
if (position == 2) {
try {
var calculationJNITest = CalculationJNITest()
val javaModel = JavaModel()
javaModel.age = 10
javaModel.moblie = "17863333333"
javaModel.name = "lxl"
val calculationSum = calculationJNITest.updateObjectValue(javaModel)
mResult.text = javaModel.moblie
} catch (e: Exception) {
e.printStackTrace()
}
return
}
2.这时候我们通过mResult这个textView输出属性值,发现moblie已经从17863333333改成了18700000了。
六。项目源码链接:
调用入口类:
android_all_demo/JNIActivity.kt at master · aa5279aa/android_all_demo · GitHub