android JNI学习五

来源:互联网 发布:java snmp4j 编辑:程序博客网 时间:2024/06/07 02:12

这次尝试 jni 回调,就是 C或C++ 调用 java 方法。主要是使用 jni 的 CallXXXMethod 函数。由于我尝试的例子是 void 型,所以 jni 函数是 CallVoidMethod 。

在前面的例子里做修改尝试,先在 MainActivity.java 里删除掉获取图片和显示的代码,添加一个 jni 回调的无参数无返回值方法 answerjnicallback 代码如下:

package com.example.jnicall;

import java.nio.ByteBuffer;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mb1;
mb1 = (Button)findViewById(R.id.button1);
mb1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
add(1,2);
}
});
}

static {
System.load("/system/jni/libjnicall.so");
}
public native int add(int add1, int add2);

public void answerjnicallback()
{
Log.d("jni_call","APK -- answerjnicallback");
}
}

answerjnicallback 里只执行一个 log 输出。

前面的工程 jni_call.cpp 文件删除系统注册的代码,修改如下:

#include "tools.h"
#include <jni.h>
#include "JNIHelp.h"
#include <android/log.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "jni_call", __VA_ARGS__)

#ifdef __cplusplus
extern "C" {
#endif
void callback(JNIEnv* env, jobject thiz)
{
LOGD("callback -- begin");
jclass clsListener = NULL;
jmethodID mid = NULL;
if((clsListener = env->GetObjectClass(thiz)) == NULL)
    {
        LOGD("Can't find thiz class");
        return ;
    }
if((mid = env->GetMethodID(clsListener, "answerjnicallback", "()V")) == NULL)
    {
        LOGD("Cant find method");
        return ;
    }
env->CallVoidMethod(thiz, mid, NULL);
LOGD("callback -- end");
    return ;
}

jint Java_com_example_jnicall_MainActivity_add(JNIEnv* env, jobject thiz, jint add1, jint add2){
LOGD("add = %d",add(add1, add2));
callback(env,thiz);
    return add(add1, add2);
}
#ifdef __cplusplus
} // extern "C"
#endif

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv *env;
if ( (vm->GetEnv( (void**) &env, JNI_VERSION_1_4)) != JNI_OK) {
return -1;
}
    return JNI_VERSION_1_4;
}

在 add 函数里添加一个 callback 函数,注意函数要写在调用的函数 add 之前。callback 函数里就是执行 jni 回调 java 的实现。
先是定义 jclass clsListener 通过调用嗯 env->GetObjectClass(thiz) 获取java 的 class,需要参数 jobject thiz,各位也可以百度一下 FindClass 也可以获取 java 的 class。

然后定义 jmethodID mid 通过 env->GetMethodID(clsListener, "answerjnicallback", "()V") 来保存 java 的 jmethodID。第二个参数是 java 里的方法名,第三个参数是该方法的返回值类型和参数,由于是无返回无参数,所以是 ()V,可参考前面涉及到的JNINativeMethod 结构体里的参数定义

保存编译 so 库文件 push 进 /system/jni/ 路径下,运行 MainActivity 工程,打印 log 信息如下:

D/jni_call( 3206): add = 3
D/jni_call( 3206): callback -- begin
D/jni_call( 3206): APK -- answerjnicallback
D/jni_call( 3206): callback -- end

就说明 jni 回调成功了。

如果 jni 涉及到线程间回调 java,可以使用 AttachCurrentThread 这个函数,具体怎么用,可自行百度。


代码实例:http://download.csdn.net/detail/u013820413/7000501

0 0
原创粉丝点击