今天试验了通过JNI,让native回调java层的方法。
试验的代码很简单,让native回调java层的方法,让java层的方法想主线程发送消息更新UI。
下面是project的目录结构:
MainActivity.java的code
package com.example.jnicallback;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView mStopWatch;
private MessageExt mMessageExt;
private MessageExt.TimeListener mListener = new MessageExt.TimeListener() {
@Override
public void updateTime(String timer) {
mStopWatch.setText(timer);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStopWatch = (TextView) findViewById(R.id.stop_watch);
mMessageExt = new MessageExt(mListener, this.getMainLooper());
mMessageExt.process();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
逻辑很简单,通过MessageExt回调updateTime() method更新UI。
MessageExt.java的code
package com.example.jnicallback;
import java.lang.ref.WeakReference;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
public class MessageExt {
private MainHanlder mMainHandler;
private static final int UPDATE_TIMER = 1;
private TimeListener mListener;
public interface TimeListener {
public void updateTime(String time);
}
public MessageExt(TimeListener listener, Looper looper) {
mListener = listener;
mMainHandler = new MainHanlder(looper);
nativeSetup(new WeakReference<MessageExt>(this));
}
private class MainHanlder extends Handler {
public MainHanlder(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case UPDATE_TIMER:
String time = "2013";
mListener.updateTime(time);
}
}
}
private static void callbackFromNative(Object messageExt) {
MessageExt msgExt = (MessageExt)((WeakReference)messageExt).get();
if (msgExt.mMainHandler != null) {
msgExt.mMainHandler.sendEmptyMessage(UPDATE_TIMER);
}
}
public void process() {
nativeProcess();
}
static {
System.loadLibrary("test_jni");
}
private native void nativeSetup(Object messageExt);
private native void nativeProcess();
}
callbackFromNative()方法就是native要回调的方法。主要定义为static类型,为class所拥有。之所以要用static修饰是为了避免在runing的时候会有
can't call callbackFromNative on instance of Ljava/lang/Class;
接下来看JNI下的jni_MessageExt.cpp的code
注意的地方如果是.cpp文件,extern "C"{}, JNIEXPORT, JNICALL这些关键词是必要的,或者runing的时候会报找不到native的方法。好像.c文件就不需要这样。#include <jni.h> extern "C" { jobject mMsgExtJObjectWeak; jmethodID mCallbackJmethodId; jclass mMsgExtClass; /* * Class: com_example_jnicallback_MessageExt * Method: setup * Signature: (Ljava/lang/Object;)V */ JNIEXPORT void JNICALL Java_com_example_jnicallback_MessageExt_nativeSetup(JNIEnv *env, jobject thiz, jobject weak_this) { jclass clazz = env->GetObjectClass(thiz); mMsgExtJObjectWeak = env->NewGlobalRef(weak_this); mMsgExtClass = (jclass)env->NewGlobalRef(clazz); mCallbackJmethodId = env->GetStaticMethodID(clazz, "callbackFromNative", "(Ljava/lang/Object;)V"); } /* * Class: com_example_jnicallback_MessageExt * Method: process * Signature: ()V */ JNIEXPORT void JNICALL Java_com_example_jnicallback_MessageExt_nativeProcess(JNIEnv *env, jobject thiz) { env->CallStaticVoidMethod(mMsgExtClass, mCallbackJmethodId, mMsgExtJObjectWeak); } }
不知道你注意到了没GetStaticMethodID(), CallStaticVoidMethod()这些方法没,那和java层的callbackFromNative用static修饰是关系的。
好吧,demo很简单,希望你们实验成功,在windows上配置NDK,可以参考下面的这边文章http://blog.csdn.net/yangchang999/article/details/11880771