JNI极简使用

JNI不必多说,是Java与Native的桥梁,也许不经常使用,但必须会使用。

流程也是一致的:

  1. 创建带有native方法的Java类
  2. 使用javah编译上面的类,得到.h文件
  3. 拷贝头文件部分内容,写成.c文件
  4. 制定makefile
  5. 使用ndk编译.c得到.so文件
  6. 使用System.loadLibary等方法加载so文件调用

接下来我们就…
稍等,为了不去终端敲那些javah/ndk之类的命令,先去建个快捷脚本吧。当然不是使用py,而是在Idea的tools中添加。

准备工作

Tools
Idea系列的IDE应该都有这个选项,然后添加,这里主要添加javah和ndk build就行了。

先生成javah相关的工具:
在这里插入图片描述
所有环境变量和项目变量都可以在右侧选择。

javah的三项应该可以填:

$JDKPath$\bin\javah.exe
-classpath . -jni -d $ModuleFileDir$\src\main\jni $FileClass$
$ModuleFileDir$\src\main\java

看一下javah的大概参数,就可以明白中间参数的意义,整个工具的意义就是编译当前Java文件的class文件,在\src\main\jni目录生成.h头文件
javah

再生成ndk相关的工具:
ndk
ndk这边比较简单,直接找到ndk-build.cmd所在位置就行了。

D:\ANDROID\android-sdk-windows\ndk-bundle\ndk-build.cmd
$ModuleFileDir$\src\main\java

另外,还有makefile,不过这个文件有固定模板,目前不需要深究。这个文件命名为—Android.mk,最好和c文件或cpp文件在同一目录。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=device-b-jni
LOCAL_SRC_FILES :=device_b.c
include $(BUILD_SHARED_LIBRARY)

理论上,只需要更改LOCAL_MODULE 与LOCAL_SRC_FILES 两个值就行了。

生成so

准备工作完成,现在可以按流程来了。
第一步,创建带native的Java类;

public class Chain {
	public static native int getLength(String content);
}

第二步,使用javah编译,这里可以使用之前准备的javah Tools,控制台会打印相关信息;

"C:\Program Files\Java\jdk1.8.0_60\bin\javah.exe" -classpath . -jni -d E:\Projects\SmartBccaStreamGateway\app\src\main\jni com.jinxin.smartbccastreamgateway.Chain

这一步完成后就会在jni目录生成一个.h文件:

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

#ifndef _Included_com_jinxin_smartbccastreamgateway_Chain
#define _Included_com_jinxin_smartbccastreamgateway_Chain
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jinxin_smartbccastreamgateway_Chain
 * Method:    getLength
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_jinxin_smartbccastreamgateway_Chain_getLength
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

第三步,复制上面的.h文件的部分内容,写成.c文件;

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <com_jinxin_smartbccastreamgateway_Chain.h>
/*
 * Class:     com_jinxin_smartbccastreamgateway_Chain
 * Method:    getLength
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_jinxin_smartbccastreamgateway_Chain_getLength
  (JNIEnv *env, jobject obj, jstring str){
    return (*env)->GetStringUTFLength(env,str);
  }

可以看到,主要步骤是替换头文件标示,删除除函数之外的代码,以及实现函数内容。
第四步,制定makefile,有模板,修改要编译的c文件路径即可,命名为----Android.mk;

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=chain-jni
LOCAL_SRC_FILES :=chain.c
include $(BUILD_SHARED_LIBRARY)

第五步,使用ndk编译,会在控制台显示相关信息;

D:\ANDROID\android-sdk-windows\ndk-bundle\ndk-build.cmd
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.    
Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in E:/Projects/SmartBccaStreamGateway/app/src/main/AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.    
[arm64-v8a] Compile        : chain-jni <= chain.c
[arm64-v8a] SharedLibrary  : libchain-jni.so
[arm64-v8a] Install        : libchain-jni.so => libs/arm64-v8a/libchain-jni.so
[armeabi-v7a] Compile thumb  : chain-jni <= chain.c
[armeabi-v7a] SharedLibrary  : libchain-jni.so
[armeabi-v7a] Install        : libchain-jni.so => libs/armeabi-v7a/libchain-jni.so
[x86] Compile        : chain-jni <= chain.c
[x86] SharedLibrary  : libchain-jni.so
[x86] Install        : libchain-jni.so => libs/x86/libchain-jni.so
[x86_64] Compile        : chain-jni <= chain.c
[x86_64] SharedLibrary  : libchain-jni.so
[x86_64] Install        : libchain-jni.so => libs/x86_64/libchain-jni.so

最终会生成so文件:
so文件

第六步,加载so文件,调试方法;把上面生成的so文件放到项目的jniLibs目录下,然后加载so文件;

public class Chain {
	static{
        System.loadLibrary("chain-jni");
	}

	public static native int getLength(String content);
}

我这里就在这个类里面加载了,然后在其他地方调用:

    System.out.println(Chain.getLength("I'm fine."));

最终输出:

07-12 10:56:28.355  I/System.out: 9

成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值