你好,JNI

324 阅读2分钟

第一天

1、为什么要学习JNI

本人之前是做flutter开发的。在flutter开发中免不了与android和ios底层接触,于是后面后学习了部分andorid和ios。在android第三方插件的接入时发现有很多插件内是有jni库的调用的。想要深入学习android打开jni的学习必不可少。于是开始研究jni的开发。

2、学习的准备工作

安装java环境 eclipse ,visual studio(2019)eclipse用于创建java项目 vs2019用于创建jni dll 特别说明,单纯开发android的jni so库是用不到下载这么多软件的。一个android studio全部搞定,不仅开发效率高,还有很强的代码补全功能。但是为了学的更深入我从开发jni 的dll开始。

java开发环境安装自行百度,需要配置环境变量方便后面直接在控制台进行java命令。

3、简单的尝试,实现java调用jni的native方法获取一个字符串

1. 创建java项目 image.png

2. 创建一个package,包名不要带'_' image.png image.png

3. 在包下面建立一个class 取名Study1(随便) 并创建一个native方法 public native String getSign();

4. 控制台进如src项目src目录 并执行java指令生成.h头文件

image.png

image.png

image.png

5. 用VS创建一个C++控制台项目(NdkJni)把NdkJni.cpp改成.c文件。然后把com_sohubill_ndkstudy_Study1.h文件复进这个项目文件夹下面,并且在项目的头文件内添加。此时会有下面错误

image.png 6. 把jni.h和jni_md.h文件复制紧VS项目内。这两个文件在JAVA环境文件夹的include和include\win32内。并且com_sohubill_ndkstudy_Study1.h内的#include <jni.h>改成#include "jni.h"引号是引入本地头文件,<>是引入配置的系统头文件

7.vs中选择调试-》NdkJin调试属性-》常规-》配置类型-》动态库dll 8. 选择生成-》配置管理器-》选择合适自己的活动解决方案平台,这边再windows下面所以选择X64 下面是头文件内容

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_sohubill_ndkstudy_Study1 */

#ifndef _Included_com_sohubill_ndkstudy_Study1
#define _Included_com_sohubill_ndkstudy_Study1
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_sohubill_ndkstudy_Study1
 * Method:    getSign
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_sohubill_ndkstudy_Study1_getSign
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

下面是NdkJni.c文件的内容

#include "com_sohubill_ndkstudy_Study1.h"

JNIEXPORT jstring JNICALL Java_com_sohubill_ndkstudy_Study1_getSign
(JNIEnv* env, jobject jobj) {

	return (*env)->NewStringUTF(env, "12345678");
}

生成解决方案 9. 在java项目中添加dll的加载整体代码如下。执行

package com.sohubill.ndkstudy;

public class Study1 {
	static {
		System.load("G:\\NDKProjcet\\NdkJni\\x64\\Debug\\NdkJni.dll");
	}
	
	public static void main(String[] args) {
		Study1 study=new Study1();
		String sign = study.getSign();
		System.out.println(sign);
	}
	public native String getSign();
}

输出结果为12345678


特别注意:mac下vs studio无法执行c生成动态库,用vs code 编写代码,并用命令行 gcc -dynamiclib -I /Library/Java/JavaVirtualMachines 类名.c -o 动态库名.jnilib 来生成动态库