Liping Zou bio photo

Liping Zou

An Android Developer

Email Twitter Instagram Github

Overview

###创建一个Java类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.hellojni;

public class Test {

	public native void callC();
	
	public void print(String msg){
		System.out.println(msg);
	}
	
	public int add(int x, int y){
		return x + y;
	}
}

###生成头文件

进入project/bin/classes目录,执行javah com.example.hellojni.Test,生成com_example_hellojni_Test.h,记得拷贝到jni目录下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_hellojni_Test */

#ifndef _Included_com_example_hellojni_Test
#define _Included_com_example_hellojni_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_hellojni_Test
 * Method:    callC
 * Signature: ()V
 */
		
JNIEXPORT void JNICALL Java_com_example_hellojni_Test_callC(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

###生成方法签名

在project/bin/classes目录,执行javap -s com.example.hellojni.Test,生成各个方法的签名。签名说明了方法的参数和返回值类型。

	Compiled from "Test.java"
	public class com.example.hellojni.Test extends java.lang.Object{
	public com.example.hellojni.Test();
  			Signature: ()V
	public native void callC();
  			Signature: ()V
	public void print(java.lang.String);
  			Signature: (Ljava/lang/String;)V
	public int add(int, int);
  			Signature: (II)I
	}

生成的签名,括号里的代表参数,括号外的内容表示返回值。()V代表参数为空,返回值为void。(II)I代表参数为两个int,返回值为int。

###实现native方法

在C文件中:

  • 添加头文件* #include "com_example_hellojni_Test.h"
  • 添加native方法的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
JNIEXPORT void JNICALL Java_com_example_hellojni_Test_callC(JNIEnv *env, jobject thiz) {
	LOGE("start");
	char* name = "com/example/hellojni/Test";

	// 根据包名获取类
	jclass test = (*env)->FindClass(env, name);

	// 获取要调用的方法,第三个参数是方法名,第四个参数是方法签名
	jmethodID method = (*env)->GetMethodID(env, test, "print", "(Ljava/lang/String;)V");

	LOGE("before call");
	(*env)->CallVoidMethod(env, thiz, method, (*env)->NewStringUTF(env, "hello jni"));
	LOGE("after call");
}