1. 使用
/**
*
*/
package com.magc.jni;
/**
* @author magc
*
*/
public class HelloWorld {
static {
System.loadLibrary("Hello");
}
public native void DisplayHello();
/**
* @param args
*/
public static void main(String[] args) {
new HelloWorld().DisplayHello();
}
}
2. 如何实现
方案一:Old Style方法
javac ./com/magc/jni/HelloWorld.java
javah -jni com.magc.jni.HelloWorld
在当前目录下生成com_magc_jni_HelloWorld.h头文件,此文件供C、C++程序来引用并实现其中的函数
写一个文件src/jni_helloworldImpl.cpp,用来实现函数
JNIEXPORT void JNICALL Java_com_magc_jni_HelloWorld_DisplayHello
(JNIEnv *env, jobject obj)
{
printf("From jni_helloworldImpl.cpp :");
printf("Hello world ! \n");
return;
}
Then,编译cpp生成so库
方案二:注册native方法
1. 以前在jni中写本地方法时,都会写成 Java_com_example_hellojni_HelloJni_stringFromJNI的形式,函数名很长,而且当类名变了的时候,函数名必须一个一个的改,麻烦。
现在好了有了RegisterNatives,现在一片顶过去五片,蓝瓶的好喝的!
2. hello-jni.c中
- #include <string.h>
- #include <jni.h>
- #include <android/log.h>
- #define TAG "HELLO"
- #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG, __VA_ARGS__)
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__)
- #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , TAG, __VA_ARGS__)
- #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , TAG, __VA_ARGS__)
- # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
- jstring native_stringFromJNI( JNIEnv* env, jobject thiz )
- {
- return (*env)->NewStringUTF(env, "Hello from JNI !");
- }
- static const char *classPathName = "com/example/hellojni/HelloJni";
- static JNINativeMethod methods[] = {
- {"stringFromJNI", "()Ljava/lang/String;", (void*)native_stringFromJNI},
- };
- jint JNI_OnLoad(JavaVM* vm, void* reserved)
- {
- JNIEnv* env = NULL;
- jclass clazz;
- //获取JNI环境对象
- if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- LOGE("ERROR: GetEnv failed\n");
- return JNI_ERR;
- }
- //注册本地方法.Load 目标类
- clazz = (*env)->FindClass(env,classPathName);
- if (clazz == NULL)
- {
- LOGE("Native registration unable to find class '%s'", classPathName);
- return JNI_ERR;
- }
- //注册本地native方法
- if((*env)->RegisterNatives(env, clazz, methods, NELEM(methods)) < 0)
- {
- LOGE("ERROR: MediaPlayer native registration failed\n");
- return JNI_ERR;
- }
- /* success -- return valid version number */
- return JNI_VERSION_1_4;
- }
a. System.loadLibrary("hello-jni"); 时会调用 JNI_OnLoad
b. RegisterNatives的第二个参数clazz包含了类的路径
c. 定义JNINativeMethod时,第二个参数
()中的字符表示参数,后面表示返回值,
"()V"----> void func()
"(II)V"----> void func(int, int)