char* classname = "wjy/geridge/com/testndk/jni/JniUtils";
jclass dpclazz = (*env)->FindClass(env, classname);
//参数介绍 : 第二个参数是Class对象, 第三个参数是方法名,第四个参数是方法的签名, 获取到调用的method
jmethodID methodID = (*env)->GetMethodID(env, dpclazz,"add", "(II)I");
Java类型 | 类型签名 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | J |
float | F |
double | D |
类 | L全限定类名 |
数组 | [元素类型签名 |
jmethodID methodID = (*env)->GetStaticMethodID(env, dpclazz,"add", "(II)I");
可以看到获取静态方法需要调用
GetStaticMethodID方法,参数与GetMethodID相同
jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
jmethodID methodID2 = (*env)->GetStaticMethodID(env, dpclazz,"callNullModth", "()V");
//C中调用Java的String参数方法
jmethodID methodID3 = (*env)->GetStaticMethodID(env, dpclazz,"callStringMethod", "(Ljava/lang/String;)Ljava/lang/String;");
//添加一个参数
jstring param = (*env)->NewStringUTF(env, "C中调用Java的String参数方法");
jstring result = (*env)->CallStaticObjectMethod(env,clazz,methodID3,param);
//jstring转char*(UTF-8格式)
char *str = (*env)->GetStringUTFChars(env, result,0);
LOGI("callStringMethod=%s",str);
上面例子的参数和返回值都是String,GetStringUTFChars方法是在jni.h中声明可以顺便查看下其他相关方法
package wjy.geridge.com.testndk.jni;
import android.util.Log;
/**
* Created by zzq on 2017/3/22 0022.
*/
public class JniUtils {
public static native int getStringFormc(int x, int y);
public static native int[] getArray(int[] arr);
/**
* 调用带参的Java方法
* @param x
* @param y
* @return
*/
public static int add(int x,int y){
return x + y;
}
/**
* 调用JAVA空参数 void返回值的方法
*/
public static void callNullMethod(){
Log.e("TAG","C中调用JAVA的void返回值,空参数方法");
}
/**
* 调用JAVA中String参数和返回值的的方法
*/
public static String callStringMethod(String str){
return str+"->调用成功";
}
}
在Activity中调用:
package wjy.geridge.com.testndk;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import wjy.geridge.com.testndk.jni.JniUtils;
public class MainActivity extends AppCompatActivity {
private TextView textView;
static {
System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textview);
textView.setText(JniUtils.getStringFormc(8,9)+"");
JniUtils.getArray(new int[]{1,2,3,4,15});
}
}
#include "string.h"
#include "wjy_geridge_com_testndk_jni_JniUtils.h"
#include
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
/*
* Class: Java_wjy_geridge_com_testndk_jni_JniUtils
* Method: getStringFormc
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jint JNICALL Java_wjy_geridge_com_testndk_jni_JniUtils_getStringFormc
(JNIEnv *env, jobject clazz,jint x,jint y){
char* classname = "wjy/geridge/com/testndk/jni/JniUtils";
jclass dpclazz = (*env)->FindClass(env, classname);
//这里实现了互相调用,Java中调用了C的getStringFormc方法传递了x,y参数,这里C又调用了Java的add方法将x,y回传回去求和;
jmethodID methodID = (*env)->GetStaticMethodID(env, dpclazz,"add", "(II)I");
LOGI("调用ADD方法的结果count=%d",(*env)->CallStaticIntMethod(env,clazz,methodID,x,y));
//C中调用Java的空返回值方法
jmethodID methodID2 = (*env)->GetStaticMethodID(env, dpclazz,"callNullMethod", "()V");
(*env)->CallStaticVoidMethod(env,clazz,methodID2);
//C中调用Java的String参数方法
jmethodID methodID3 = (*env)->GetStaticMethodID(env, dpclazz,"callStringMethod", "(Ljava/lang/String;)Ljava/lang/String;");
//添加一个参数
jstring param = (*env)->NewStringUTF(env, "C中调用Java的String参数方法");
jstring result = (*env)->CallStaticObjectMethod(env,clazz,methodID3,param);
//jstring转char*
char *str = (*env)->GetStringUTFChars(env, result,0);
LOGI("callStringMethod=%s",str);
return x+y;
}
/**
打印一个数组
*/
jintArray Java_wjy_geridge_com_testndk_jni_JniUtils_getArray
(JNIEnv *env, jobject clazz,jintArray arr){
int len = (*env)->GetArrayLength(env,arr);
//在LogCat中打印出arr的大小
LOGI("the length of array is %d", len);
//如果长度为0, 返回arr
if(len == 0){
return arr;
}
//如果长度大于0, 那么获取数组中的每个元素
jint* p = (*env)->GetIntArrayElements(env, arr, 0);
//打印出数组中每个元素的值
for(int i = 0; i < len; i ++)
{
LOGI("arr[%d] = %d", i, *(p + i));
}
return arr;
}
运行结果:
#include
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
android {
defaultConfig {
ndk {
moduleName "NdkJniDemo" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库,目前可有可无。
ldLibs "log", "z", "m"
}
}