【进阶解密】JNI初学篇(二)-动态注册
2020-05-21 本文已影响0人
南山村靓仔
上一篇,我们讲到了JNI的静态注册,没看过的,按需查看
【进阶解密】JNI初学篇(一)-静态注册 https://www.jianshu.com/p/993c8f2d6857
今天我们讲下动态注册
主要步骤为:
1、java中定义Native方法
2、编写C/C++文件,实现jni接口方法,以及JNI_OnLoad方法
3、编译so库
4、java加载so库,调用native方法
1、新建java类,定义Native方法getHello
package jni.com.cj.constom.jnitest;
/*
* 动态注册方式
* */
public class JNITest2 {
static {
System.loadLibrary("mgjnitest2");
}
public static native String getHello();
}
2、新建文件jni_com_cj_constom_jnitest_JNITest.c ,实现jni接口方法,以及JNI_OnLoad方法
注意:C语言和C++的实现存在一些差异,GetEnv、FindClass、RegisterNatives方法参数有差异,若要用C++实现,就自行搜索下其他文章哈,文章很多~
下面是C语言的实现方式
#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
JNIEXPORT jstring JNICALL get_Hello(JNIEnv *env, jclass type) {
return (*env)->NewStringUTF(env, "Hello from JNI 动态注册测试!");
}
static JNINativeMethod g_methods[] = {
{"getHello",//java定义的native方法名
"()Ljava/lang/String;", //()表示无参数;Ljava/lang/String表示返回String类型
(void *) get_Hello //JNI中实现的方法名
}
};
JNIEXPORT int JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void **)&env,JNI_VERSION_1_6) != JNI_OK) {
return JNI_FALSE;
}
const char *class_path = "jni/com/cj/constom/jnitest/JNITest2";//这里对应native的java类
jclass javaClass = (*env)->FindClass(env,class_path);
if (javaClass == NULL) {
return JNI_FALSE;
}
int method_count = sizeof(g_methods) / sizeof(g_methods[0]);
if ((*env)->RegisterNatives(env,javaClass, g_methods, method_count) < 0) {
return JNI_FALSE;
}
return JNI_VERSION_1_6;
}
3、分别创建Android.mk、Application.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mgjnitest2
LOCAL_SRC_FILES := jni_com_cj_constom_jnitest_JNITest.c
include $(BUILD_SHARED_LIBRARY)
#APP_ABI := armeabi armeabi-v7a arm64-v8a x86
APP_ABI := all
APP_OPTIM := release
## 引用静态库
APP_STL := stlport_static
#NDK_TOOLCHAIN_VERSION=4.8
#APP_PLATFORM := android-14
APP_PLATFORM := android-16
APP_ALLOW_MISSING_DEPS=true
4、主项目点击事件代码:
public void getJNIValue2(View view) {
String test = JNITest2.getHello();
Toast.makeText(getApplicationContext(), "value=" + test, Toast.LENGTH_SHORT).show();
}