JNI系列——C文件中的方法调用Java中方法

1.创建xxx.jni包并在该包下实现一些Java的方法,和要调用的本地方法

2.实现MainActivity中的按钮点击事件—即点击按钮调用本地的方法

3.在C文件中的方法中回调Java的方法

  3.1:通过env获取字节码对象—>jclass   (*FindClass)(JNIEnv*, const char*)

    第二个参数为要回调Java方法所在类的全路径如:jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/jni/JNI");

  3.2:通过字节码对象获取方法ID—>jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);

    第二个参数是由3.1获取的字节码对象,第三个对象是要回调的Java方法名,第四个参数该Java方法签名,因为Java中有重载,需要此参数确定具体是哪个方法如:jmethodID methodId = (*env)->GetMethodID(env, claz, "helloFromJava", "()V")

    注:对应方法签名,需要到工程目录下的bin/classes目录下执行:javap -s com.rocky.jniccallbackdemo.jni.JNI(该方法所在类的全类名)

  3.3:通过字节码对象创建Java对象—>jobject (*AllocObject)(JNIEnv*, jclass);
    如:jobject obj = (*env)->AllocObject(env, claz);

注:如果本地方法和要回调的Java方法在同一个类中,则第二参数就是本地方法传过来的第二个参数,即第三步可以可以省略。

  3.4:通过Java对象回调Java方法

  调用Java的无返回值方法:void  (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...),如: (*env)->CallVoidMethod(env, clazz, methodId);

 

DEMO:

JNI.java

public class JNI
{
    static {
        System.loadLibrary("callback");
    }
    private Context mContext = null;
    public JNI(Context context)
    {
        this.mContext = context;
    }
    public void helloFromJava()
    {
        System.out.println("Hello From Java");
    }
    public void printString(String str)
    {
        System.out.println(str);
    }
    public void showToast(String str)
    {
        Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show();
    }
    public native void callbackVoidMethod();
    public native void callbackStringMethod();
    public native void callbackIntMethod();
    public native void callbackShowToastMethod();
}

MainActivity.java

public class MainActivity extends Activity implements OnClickListener
{
    Context mContext = null;
    Button bt_callback_void = null;
    Button bt_callback_string = null;
    Button bt_callback_int = null;
    Button bt_callback_toast = null;
    JNI jni = null;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        jni = new JNI(mContext);
        bt_callback_void = (Button) findViewById(R.id.bt_callback_void);
        bt_callback_void.setOnClickListener(this);
        bt_callback_int = (Button) findViewById(R.id.bt_callback_int);
        bt_callback_int.setOnClickListener(this);
        bt_callback_string = (Button) findViewById(R.id.bt_callback_string);
        bt_callback_string.setOnClickListener(this);
        bt_callback_toast = (Button) findViewById(R.id.bt_callback_toast);
        bt_callback_toast.setOnClickListener(this);
    }
    public int add(int x, int y)
    {
        return x + y;
    }
    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
        case R.id.bt_callback_void:
            jni.callbackVoidMethod();
            break;
        case R.id.bt_callback_int:
            jni.callbackIntMethod();
            break;
        case R.id.bt_callback_string:
            jni.callbackStringMethod();
            break;
        case R.id.bt_callback_toast:
            jni.callbackShowToastMethod();
            break;

        default:
            break;
        }
    }
}

callback.c

#include <jni.h>
#include <android/log.h>
#define LOG_TAG "rocky"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_rocky_jniccallbackdemo_jni_JNI_callbackVoidMethod
  (JNIEnv *env, jobject clazz)
{
    //1.获取字节码对象  jclass      (*FindClass)(JNIEnv*, const char*);
    jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/jni/JNI");
    //2.通过字节码对象获取方法ID    jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    jmethodID methodId = (*env)->GetMethodID(env, claz, "helloFromJava", "()V");
    //3.通过字节码对象创建Java对象(此处因为本地方法和回调方法在同一个类中,可以省略)
    //4.通过Java对象回调Java方法  void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    (*env)->CallVoidMethod(env, clazz, methodId);
}
/*
 * Class:     com_rocky_jniccallbackdemo_jni_JNI
 * Method:    callbackIntMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_rocky_jniccallbackdemo_jni_JNI_callbackIntMethod
  (JNIEnv *env, jobject clazz)
{
    jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/MainActivity");
    jmethodID methodId = (*env)->GetMethodID(env, claz, "add", "(II)I");
    //3.通过字节码对象创建Java对象(此处为MainActivity对象)  jobject     (*AllocObject)(JNIEnv*, jclass);
    //    jobject obj = (*env)->AllocObject(env, claz);
        //4.通过Java对象回调Java方法  void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    jobject obj = (*env)->AllocObject(env, claz);
    jint res = (*env)->CallIntMethod(env, obj, methodId, 8, 9);
    LOGI("res = %d\n", res);
}
JNIEXPORT void JNICALL Java_com_rocky_jniccallbackdemo_jni_JNI_callbackStringMethod
  (JNIEnv *env, jobject clazz)
{
    jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/jni/JNI");
    jmethodID methodId = (*env)->GetMethodID(env, claz, "printString", "(Ljava/lang/String;)V");
    jstring result = (*env)->NewStringUTF(env, "cccccccccccccc");
    (*env)->CallVoidMethod(env, clazz, methodId, result);
}
JNIEXPORT void JNICALL Java_com_rocky_jniccallbackdemo_jni_JNI_callbackShowToastMethod
  (JNIEnv *env, jobject clazz)
{
    jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/jni/JNI");
    jmethodID methodId = (*env)->GetMethodID(env, claz, "showToast", "(Ljava/lang/String;)V");
    jstring result = (*env)->NewStringUTF(env, "rocky--------rocky");
    (*env)->CallVoidMethod(env, clazz, methodId, result);
}

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := callback
LOCAL_SRC_FILES := callback.c

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

 

转载于:https://www.cnblogs.com/doitbyyourself/p/6212689.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值