序章:
1.本篇是JNI入门教程的第二篇,偏基础功能的实现。完整教程连接如下:
2.本篇要完成的需求如下:
从JNI方法中返回一个字符串,然后在安卓中展示。
一。流程步骤
安卓中调用jni主要包含以下几个步骤:
1.在java中声明引用。
2.在jni中创建对应的h文件和cpp文件。
3.在CMakeLists中进行声明,声明之后jni中的方法才能被java外部调用。
二。在java中创建声明类
这里我们创建一个java类,叫Java2CJNI,
我这里创建的java类的包名是:com.xt.client.jni,后面会用到。
里面主要做以下两件事:
public class Java2CJNI {
//加载so库
static {
System.loadLibrary("Java2C");
}
//native方法
public native String java2C();
}
1.static静态方法块中加载so库。
这里加载的库名叫Java2C,后面CMakeLists和JNI中是需要和这个名称对应的。
2.对native方法进行声明。
这里声明的方法是java2C,返回类型是String,没有传入参数。
这个和库名并不存在绑定的关系。但是需要和后面的CMakeLists和JNI的方法名进行绑定。
三。在jni中创建h和cpp文件
我在工程目录下创建一个jni文件夹,和java同级。然后分别创建
com_xt_client_jni_Java2CJNI.h和Java2C.cpp两个文件
1.创建com_xt_client_jni_Java2CJNI.h文件:
这里的文件名是需要和java类的包名对应的,
com_xt_client_jni这里对应的是包名,
Java2CJNI对应的是JAVA中的类名。
文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xt_client_jni_Java2CJNI */
#ifndef _Included_com_xt_client_jni_Java2CJNI
#define _Included_com_xt_client_jni_Java2CJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_xt_client_jni_Java2CJNI
* Method: java2C
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_xt_client_jni_Java2CJNI_java2C
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
这里主要就是声明一个方法:
Java_com_xt_client_jni_Java2CJNI_java2C
方法名字构成规则是:JAVA+包名+类型+方法名,JNIEnv和jobject是默认传入参数,返回类型是jstring,对应的就是java中的string类型。
其中JNIEnv是jni环境,我们使用JN I中的方法,基本都是靠调用JNIEnv实现的。
jobject指的是调用native方法的对象。
2.创建Java2C.cpp文件:
#include <jni.h>
#include "com_xt_client_jni_Java2CJNI.h"
#include<android/log.h>
JNIEXPORT jstring JNICALL Java_com_xt_client_jni_Java2CJNI_java2C(JNIEnv* env, jobject instance)
{
return (env)->NewStringUTF("I am From Native C");
}
这里cpp的文件名可以随便起的,并不需要和h文件对应。我们这里实现逻辑比较简单,直接返回一个字符串。
这里需要注意的时,C中字符串是char类型的,是不能直接返回给java的,所以我们要调用env中NewStringUTF方法,把char转化为jstring类型,然后在返回。
四。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( # Sets the name of the library. 设置生成so文件名
Java2C
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s). 要编译的C/C++文件
src/main/jni/Java2C.cpp)
这里Java2C对应的就是第二章中声明的so库名。
src/main/jni/Java2C.cpp对应的是我们cpp文件的完整路径。
2.gradle中做好声明
app的build.gradle文件中,在android{}模块下,添加如下声明:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
// version "3.10.2"
}
}
五。验证效果
准备工作全部做好了,我们就可以开始验证了。
我的调用方法如下:
override fun clickItem(position: Int) {
if (position == 0) {
var java2CJNI = Java2CJNI()
val result = java2CJNI.java2C()
mResult.text = result
return
}
...
}
这时候,我们可以看到页面上显示出了来自JNI层的字符串:
六。项目源码链接:
调用入口类: