1、编写native方法(java2c)和非native方法(c2java):
package com.example.provider; public class CallbackJava { // C调用java空方法 public void helloFromJava() { System.out.println("hello from java"); } // C调用java中的带两个int参数的方法 public int Add(int x, int y) { int result = x + y; System.out.println("java result=" + result); return result; } // C调用java中参数为string的方法 public void printString(String s) { System.out.println("java " + s); } //静态方法 public static void printStaticStr(String s) { System.out.println("java static-> " + s); } // 让c代码调用对应的java代码 public native void callHelloFromJava(); public native void callAdd(); public native void callPrintString(); // 调用一个静态的c代码 public native void callPrintStaticStr(); }
2、通过javah命令生成签名,通过javap命令生产native方法签名:
3、c代码
FindClass:找到java中的类文件
GetMethodID:根据类和方法签名找到要调用的方法。
#include <stdio.h> #include <jni.h> #include <malloc.h> #include "com_example_provider_CallbackJava.h"; #include "com_example_jni_MainActivity.h"; #include <android/log.h> #define LOG_TAG "System.out.c" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) jmethodID getMethodId(JNIEnv * env, char* methodname, char* signname) { jclass jclazz = (*env)->FindClass(env, "com/example/provider/CallbackJava"); if (jclazz == 0) { LOGD("class not find "); return; } //2、找class中方法的id,第三个参数方法名称,第四个参数该方法对应的签名 jmethodID methodid = (*env)->GetMethodID(env, jclazz, methodname, signname); if (methodid == 0) { LOGD("method not find "); return; } return methodid; } JNIEXPORT void JNICALL Java_com_example_provider_CallbackJava_callHelloFromJava (JNIEnv * env, jobject obj) { //1、 找java中的class文件 //第二个参数是类名的(包名) jclass jclazz = (*env)->FindClass(env,"com/example/provider/CallbackJava"); if(jclazz==0) { LOGD("class not find "); return; } //2、找class中方法的id,第三个参数方法名称,第四个参数该方法对应的签名 jmethodID methodid = (*env)->GetMethodID(env, jclazz,"helloFromJava","()V"); if(methodid==0) { LOGD("helloFromJava method not find "); return; } //3、调用方法 //void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); (*env)->CallVoidMethod(env,obj,methodid); } JNIEXPORT void JNICALL Java_com_example_provider_CallbackJava_callAdd (JNIEnv *env, jobject obj) { jmethodID mid = getMethodId(env,"Add","(II)I"); int result = (*env)->CallIntMethod(env, obj, mid,3,6); LOGD("c to java add: d%",result); } JNIEXPORT void JNICALL Java_com_example_provider_CallbackJava_callPrintString (JNIEnv *env, jobject obj) { LOGD("c to java callPrintString start "); jmethodID mid = getMethodId(env,"printString","(Ljava/lang/String;)V"); (*env)->CallVoidMethod(env, obj, mid,(*env)->NewStringUTF(env," call printString finish")); LOGD("c to java callPrintString finish "); } JNIEXPORT void JNICALL Java_com_example_provider_CallbackJava_callPrintStaticStr (JNIEnv *env, jobject obj) { jclass jclazz = (*env)->FindClass(env, "com/example/provider/CallbackJava"); if (jclazz == 0) { LOGD("class not find "); return; } //静态方法调用GetStaticMethodID 和 CallStaticXXXMethod jmethodID methodid = (*env)->GetStaticMethodID(env, jclazz, "printStaticStr", "(Ljava/lang/String;)V"); if (methodid == 0) { LOGD("printStaticStr method not find "); return; } (*env)->CallStaticVoidMethod(env, jclazz, methodid,(*env)->NewStringUTF(env,"static hello java")); } JNIEXPORT void JNICALL Java_com_example_jni_MainActivity_callProvider (JNIEnv *env, jobject obj){ jclass jclazz = (*env)->FindClass(env,"com/example/provider/CallbackJava"); if(jclazz==0) { LOGD("class not find "); return; } jmethodID methodid = (*env)->GetMethodID(env, jclazz,"helloFromJava","()V"); if(methodid==0) { LOGD("helloFromJava method not find "); return; } //创建一个CallbackJava对象 jobject jobj =(*env)->AllocObject(env, jclazz); (*env)->CallVoidMethod(env,jobj,methodid); }
4、编译多个c文件可以用空格分开
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE :=Hello #LOCAL_SRC_FILES :=Hello.c LOCAL_SRC_FILES :=CallbackJava.c Hello.c LOCAL_LDLIBS += -llog include $(BUILD_SHARED_LIBRARY)