本文将讲述下列三种C代码回调java方法
1、c代码回调java空方法
2、c代码回调java int类型参数方法
3、c代码回调javaString类型参数方法
方法都差不多,先看c代码回调java空方法,其他两种类似:
① 找到字节码对象
//jclass (*FindClass)(JNIEnv*, const char*);
//第二个参数 要回调的java方法所在的类的路径 "com/itheima/callbackjava/JNI"
② 通过字节码对象找到方法对象
//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
第二个参数 字节码对象 第三个参数 要反射调用的java方法名 第四个参数 要反射调用的java方法签名
javap -s 要获取方法签名的类的全类名 项目/bin/classes 运行javap
③ 通过字节码创建 java对象(可选) 如果本地方法和要回调的java方法在同一个类里可以直接用 jni传过来的java对象 调用创建的Method
jobject obj =(*env)->AllocObject(env,claz);
当回调的方法跟本地方法不在一个类里 需要通过刚创建的字节码对象手动创建一个java对象
再通过这个对象来回调java的方法
需要注意的是 如果创建的是一个activity对象 回调的方法还包含上下文 这个方法行不通!!!回报空指针异常
④ 反射调用java方法
//void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
第二个参数 调用java方法的对象 第三个参数 要调用的jmethodID对象 可选的参数 调用方法时接收的参数
接下来实战项目实现
新建项目,布局如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="callbackvoid" android:text="回调null方法" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="callbackint" android:text="回调int参数方法" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="callbackString" android:text="回调String参数方法" /> </LinearLayout>
新建JNI.java
package com.wuyudong.callbackjava; public class JNI { static{ System.loadLibrary("callback"); } public native void callbackvoidmethod(); public native void callbackintmethod(); public native void callbackStringmethod(); // C调用java空方法 public void helloFromJava() { System.out.println("hello from java"); } // C调用Java中的带两个int参数的方法 public int add(int x, int y) { return x + y; } // C调用java中参数为String的方法 public void printString(String s) { System.out.println(s); } }
MainActivity.java
package com.wuyudong.callbackjava; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { JNI jni; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); jni = new JNI(); } public void callbackvoid(View v) { jni.callbackvoidmethod(); } public void callbackint(View v) { jni.callbackintmethod(); } public void callbackString(View v) { jni.callbackStringmethod(); } }
callback.c
#include <jni.h> #include <android/log.h> #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__) JNIEXPORT void JNICALL Java_com_wuyudong_callbackjava_JNI_callbackvoidmethod( JNIEnv * env, jobject clazz) { //1、获取字节码对象 jclass (*FindClass)(JNIEnv*, const char*); jclass claz = (*env)->FindClass(env, "com/wuyudong/callbackjava/JNI"); //2、获取Method对象 jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); jmethodID methodID = (*env)->GetMethodID(env, claz, "helloFromJava", "()V"); //3、通过字节码对象创建一个Object(即是clazz) //4、通过对象调用方法 (*env)->CallVoidMethod(env, clazz, methodID); } JNIEXPORT void JNICALL Java_com_wuyudong_callbackjava_JNI_callbackintmethod( JNIEnv * env, jobject clazz) { //1、获取字节码对象 jclass (*FindClass)(JNIEnv*, const char*); jclass claz = (*env)->FindClass(env, "com/wuyudong/callbackjava/JNI"); //2、获取Method对象 jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); jmethodID methodID = (*env)->GetMethodID(env, claz, "add", "(II)I"); //3、通过字节码对象创建一个Object(即是clazz) //4、通过对象调用方法 int result = (*env)->CallIntMethod(env, clazz, methodID, 3, 5); LOGD("result = %d", result); } JNIEXPORT void JNICALL Java_com_wuyudong_callbackjava_JNI_callbackStringmethod( JNIEnv * env, jobject clazz) { //1、获取字节码对象 jclass (*FindClass)(JNIEnv*, const char*); jclass claz = (*env)->FindClass(env, "com/wuyudong/callbackjava/JNI"); //2、获取Method对象 jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); jmethodID methodID = (*env)->GetMethodID(env, claz, "printString", "(Ljava/lang/String;)V"); //3、通过字节码对象创建一个Object(即是clazz) //4、通过对象调用方法 //char* str = "hello from c!"; jstring result = (*env)->NewStringUTF(env, "hello from c"); (*env)->CallVoidMethod(env, clazz, methodID, result); }
获取更多C语言与算法相关知识,关注公众号:“csuanfa”