文章目录
1. jni的注册以及编译
1.1 静态注册jni
1.1.1 使用Android Studio创建NDK开发工程
使用Android Studio直接创建jni接口比较简单,集成开发工具为我们做了大量工作,且默认为静态注册,下面首先简单梳理一下使用最新版本Android Studio(4.0.1)创建NDK开发工程的方法:
-
首先新建工程,选择C++工程;
-
填写工程信息后选择C++可支持的版本以及编译选项,这里暂时选择默认的toolchain;
-
完成后即可看到AS为我们自动生成NDK开发的c++目录,对应的CMakeLists.txt以及cpp源文件示例。接下来只需要在cpp目录下创建需要的其他c++源文件即可。在Android Studio自动配置的静态注册中,Java文件新定义任何接口都可以自动在cpp文件中生成对应的接口声明。
Android Studio自动生成的c++接口声明示例:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jnitest_jniutil_JniManager_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_jnitest_jniutil_JniManager_getIDFromJni(JNIEnv *env, jobject thiz) {
// TODO: implement getIDFromJni()
return 0;
}
1.1.2 手动创建jni源文件
由于IDE为我们完成了过多工作使我们无法看清jni在创建过程中具体做了什么,因此这里简单尝试一下手动进行静态注册jni的过程,稍微降低对IDE的依赖。
创建jni主要需要三个步骤:创建必要的源文件、添加CMakeLists.txt、配置gradle。
1) 创建相关源文件:在原有的普通Android工程中,创建需要调用Native方法的java源文件,如:
package com.example.myappdemo.nativeManager;
public class NativeManager {
public native String getName(int id); // 本地方法声明
}
然后针对这个Java文件创建cpp的头文件,可以使用jdk指令:
step1: javac NativeManage.java // 生成class文件
step2: javah -jni com.example.jnitest2.nativeManager.NativeManager // 生成jni头文件
但是实验发现以上命令无法再适用于jdk10以上了,jdk10以后javah被包含在javac中,因此以上命令可以合并为:
javac -h -jni NativeManager.java // 直接在当前目录下创建jni目录并生成头文件,根据项目不同要求,可以将路径更改为c++目录下
生成的头文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_myappdemo_nativeManager_NativeManager */
#ifndef _Included_com_example_myappdemo_nativeManager_NativeManager
#define _Included_com_example_myappdemo_nativeManager_NativeManager
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_myappdemo_nativeManager_NativeManager
* Method: getName
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_myappdemo_nativeManager_NativeManager_getName
(JNIEnv *, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif
注意到h文件方法的名字结构是比较规则的,是以Java_包名_类名_方法名的结构出现,这也是静态注册的特点之一。
然后创建同名的cpp文件(与h文件同名方便识别),如下:
#include "com_example_myappdemo_nativeManager_NativeManager.h"
JNIEXPORT jstring JNICALL Java_com_example_myappdemo_nativeManager_NativeManager_getName
(JNIEnv *env, jobject obj, jint id) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
- 创建CMakeLists.txt
CMakeLists.txt是用来生成makefile(或者project文件)的工具,用于编译c++文件。具体CMakeLists的细节不在这里介绍,这里主要介绍基本的CMakeLists.txt如何创建和实现。
首先创建CMakeLists.txt文件,然后列出编译基本规则,如下:
// 这里是要求的最低cmake版本,但不是指定版本,指定版本在gradle中说明
cmake_minimum_requ