原理
原理其实很简单 首先用FindClass()查找java类,然后用GetMethodID()得到构造函数 构造函数的函数名是“< init >”,返回类型为"V"(void) 最后直接用NewObject()创建一个按钮 回调部分受到了别人文章和快写代码的启发,把回调类的地址传递到java中,java类接收到事件后用地址作为参数调用本地方法,本地方法把地址转换为c++回调类,调用方法
代码
MainActivity.java
package com.Diamond.ndk;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.content.Context;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context context = MainActivity.this;
LinearLayout mainLayout = new LinearLayout(this);
mainLayout.setOrientation(1);
setContentView(mainLayout);
onCreate(context,mainLayout);
}
@Override
protected void onDestroy() {
onActivityDestroy();
super.onDestroy();
}
public native void onActivityDestroy();
public native void onCreate(Context context,LinearLayout mainLayout);
static {
System.loadLibrary("jni");
}
}
MyOnClickListener.java
package com.Diamond.ndk;
import android.view.View;
import android.util.Log;
public class MyOnClickListener implements View.OnClickListener {
public int address;
public MyOnClickListener(int ar) {
address = ar;
}
@Override
public void onClick(View p1) {
callOnClick(address);
Log.d("address","" + address);
}
public native void callOnClick(long address);
static {
System.loadLibrary("jni");
}
}
main.cpp
#include <sstream>
#include <jni.h>
#include <android/log.h>
using namespace std;
extern "C"
{
class OnClickListener
{
public:
virtual void onClick() = 0;
};
JNIEnv *Env = NULL;
jobject button = NULL;
const string linearlayout_package = "android/widget/LinearLayout";
const string context_package = "android/content/Context";
const string button_package = "android/widget/Button";
const string view_package = "android/view/View";
const string charsequence_package = "java/lang/CharSequence";
const string myonclicklistener_package = "com/Diamond/ndk/MyOnClickListener";
const string onclicklistener_package = "android/view/View$OnClickListener";
jclass LinearLayout = NULL;
jclass Context = NULL;
jclass Button = NULL;
jclass View = NULL;
jclass MyOnClickListener = NULL;
jmethodID init_button = NULL;
jmethodID init_myonclicklistener = NULL;
jmethodID addView_linearlayout = NULL;
jmethodID setText_button = NULL;
jclass getClass(string package);
void setText(jobject button, string text);
class MyListener : public OnClickListener
{
public:
virtual void onClick()
{
__android_log_print(ANDROID_LOG_INFO, "test", "test");
}
};
MyListener *listener = NULL;
JNIEXPORT void JNICALL Java_com_Diamond_ndk_MainActivity_onCreate(JNIEnv * env, jobject thiz,
jobject context,
jobject mainLayout)
{
Env = env;
LinearLayout = getClass(linearlayout_package);
Context = getClass(context_package);
Button = getClass(button_package);
View = getClass(view_package);
MyOnClickListener = getClass(myonclicklistener_package);
setText_button =
Env->GetMethodID(Button, "setText", ("(L" + charsequence_package + ";)V").data());
init_button = env->GetMethodID(Button, "<init>", ("(L" + context_package + ";)V").data());
button = env->NewObject(Button, init_button, context);
setText(button, "JNI Button");
listener = new MyListener();
jmethodID setOnClickListener_button = env->GetMethodID(Button, "setOnClickListener",
("(L" + onclicklistener_package +
";)V").data());
init_myonclicklistener = env->GetMethodID(MyOnClickListener, "<init>", "(I)V");
jobject myonclicklistener =
env->NewObject(MyOnClickListener, init_myonclicklistener, jint(listener));
env->CallVoidMethod(button, setOnClickListener_button, myonclicklistener);
addView_linearlayout =
env->GetMethodID(LinearLayout, "addView", ("(L" + view_package + ";)V").data());
env->CallVoidMethod(mainLayout, addView_linearlayout, button);
}
JNIEXPORT void JNICALL Java_com_Diamond_ndk_MainActivity_onActivityDestroy(JNIEnv * env,
jobject thiz)
{
delete listener;
}
JNIEXPORT void JNICALL Java_com_Diamond_ndk_MyOnClickListener_callOnClick(JNIEnv * env,
jobject thiz,
jint address)
{
OnClickListener *listener = (OnClickListener *) address;
listener->onClick();
}
jclass getClass(string package)
{
return Env->FindClass(package.data());
}
void setText(jobject button, string text)
{
Env->CallVoidMethod(button, setText_button, Env->NewStringUTF(text.data()));
}
}
效果图
|