01.JNIEnv 的实现原理
知识点:
-> 调用的情况下必须是一级指针 *取值
env->GetXXFieldID
:获取字段的IDenv->GetXXField
:获取字段上的值,返回XX类型env->GetMethodID
:获取方法的IDenv->CallXXMethod
:调用方法。返回XX类型
1. JNI 的一般开发流程:
- 定义好本地的 native 方法,生成
.class
文件。 - 在存放
原文件 .java
的包名文件夹的最前面(src
文件夹下)使用javah 命令生成 .h 头文件javah -d jni -jni com.east.NdkSample
用法: javah [options] <classes> 其中, [options] 包括: -o <file> 输出文件 (只能使用 -d 或 -o 之一) -d <dir> 输出目录 -v -verbose 启用详细输出 -h --help -? 输出此消息 -version 输出版本信息 -jni 生成 JNI 样式的标头文件 (默认值) -force 始终写入输出文件 -classpath <path> 从中加载类的路径 -cp <path> 从中加载类的路径 -bootclasspath <path> 从中加载引导类的路径 <classes> 是使用其全限定名称指定的 (例如, java.lang.Object)。
- 拷贝
xxx.h
、jni_md.h
、jni.h
到 VS 的工程目录并添加依赖进来。(jni_md.h和jni.h在java安装目录下搜索即可查找到) - 实现我们头文件中的 native 方法
- VS生成解决方案即可生成
.dll 动态库
,java 引入 dll 动态库运行即可
java 中加载动态库:
System.loadLibrary
:android 加载apk中的libs目录下 .so 库System.load
: 加载一个具体路径上的 .so 库,去服务器上下载再进行加载(data/data)
2. 详解 .h 文件和实现文件
com_east_NdkSample.h:
#include "jni.h"
/* Header for class com_east_NdkSample */
// 用来打一个标记, c 在编译的时候会把头文件 copy 到你引入的地方,不管是重复引用还是相互引用都只会 copy 一次
#ifndef _Included_com_east_jni07_NdkSample
#define _Included_com_east_jni07_NdkSample
#ifdef __cplusplus // 相当于 if 语句 c++
// 不管是 c 还是 c++ 统一都是采用 c 的编译方法,因为在 c 里面是不允许函数重载的,但是在 c++ 里面可以
extern "C" {
#endif
/*
* Class: com_east_jni07_NdkSample
* Method: getSingnaturePassword
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_east_jni07_NdkSample_getSingnaturePassword
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
Simple.c:
// 实现我们的 native 方法
#include "com_east_NdkSample.h"
// JNIEXPORT: JNI 一个关键字,不能少(编译能通过),标记为该方法可以被外部调用
// jstring:代表 java 中的 String
// JNIC