原理

原理其实很简单
首先用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()
		{
            //用了会崩溃,不知道为什么
			//setText(button, "be clicked");
			__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()));
	}
}

效果图

在这里插入图片描述

Logo

智屏生态联盟致力于大屏生态发展,利用大屏快应用技术降低开发者开发、发布大屏应用门槛

更多推荐