cocos2d-x 通过JNI实现c/c++和Android的java层函数交互

1.JNI


       JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。


JNI实现流程:


cocos2d-x 通过JNI实现c/c++和Android的java层函数交互


2.C++与java交互流程图:

cocos2d-x 通过JNI实现c/c++和Android的java层函数交互


       注:对于跨平台的 cocos2d-x 来说,除非必要,否则可不必深究其理,比如想要使用 Android 平台固有的特性等,那就需要更多的了解 Jni 使用方法,以及 Android 操作系统的更多细节。


3.实例:


       实现功能:

              (1)通过Android sdk的API得到应用程序的包名(PackageName),然后传递给c++层函数。
              (2)通过c++函数调用Android的java层函数,显示一个对话框,点击按钮退出程序。


4.实现步骤:


4.1 使用cocos2d-x创建工程DialogBox及搭配android环境


       android环境,如图:


                           cocos2d-x 通过JNI实现c/c++和Android的java层函数交互


4.2 c++部分


先到win32环境,编写提供android调用c++接口:

JniTest.h

#ifndef JNI_TEST_H
#define JNI_TEST_H

#include "cocos2d.h"

using namespace cocos2d;

void setPackageName(const char *packageName)
{
	CCLog("packageName: %s", packageName);	
}

void exitApp()
{
	CCDirector::sharedDirector()->end();
}
#endif

调用android API接口:

HelloWorldScene.cpp

#include "HelloWorldScene.h"
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "../proj.android/jni/hellocpp/test.h"
#endif
USING_NS_CC;

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	showTipDialog("exit", "alexzhou,really go?");
#endif

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	exit(0);
#endif
}

       注:只需要更改下HelloWorldScene就OK了。


接着转到android平台,编写jni层代码:

test.h

#ifndef TEST_H
#define TEST_H

extern "C"
{
void showTipDialog(const char *title, const char *msg);
}
#endif
test.cpp

#include "cocos2d.h"
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include "test.h"
#include "JniTest.h"

#define CLASS_NAME "com/DialogBox/org/JniTestHelper"

using namespace cocos2d;

extern "C"
{
void showTipDialog(const char *title, const char *msg)
{
	JniMethodInfo t;
	if(JniHelper::getStaticMethodInfo(t, CLASS_NAME, "showTipDialog", "(Ljava/lang/String;Ljava/lang/String;)V"))
	{
		jstring jTitle = t.env->NewStringUTF(title);
		jstring jMsg = t.env->NewStringUTF(msg);
		t.env->CallStaticVoidMethod(t.classID, t.methodID, jTitle, jMsg);
		t.env->DeleteLocalRef(jTitle);
		t.env->DeleteLocalRef(jMsg);
	}
}

void Java_com_DialogBox_org_JniTestHelper_setPackageName(JNIEnv *env, jobject thiz, jstring packageName)
{
	const char *pkgName = env->GetStringUTFChars(packageName, NULL);
	setPackageName(pkgName);
	env->ReleaseStringUTFChars(packageName, pkgName);
}

void Java_com_DialogBox_org_JniTestHelper_exitApp(JNIEnv *env, jobject thiz)
{
	exitApp();
}

}

注:这里必须加上extern “C”,声明以c语言的方式进行编译,因为c++和c在编译时生成的函数签名不一样,可以在网上查找相关资料,不然运行的时候会出现链接错误。


4.3  Java部分:

c++函数调用java层函数,显示一个对话框:

JniTestHelper.java

package com.DialogBox.org;

import org.cocos2dx.lib.Cocos2dxHandler.DialogMessage;

import android.os.Handler;
import android.os.Message;

public class JniTestHelper {
	private static Handler mHandler;
	public static void init(Handler handler)
	{
		JniTestHelper.mHandler = handler;
	}
	
	public static native void setPackageName(String packageName);
	
	public static native void exitApp();
	//c++函数调用java层函数,显示一个对话框
	private static void showTipDialog(final String title, final String text)  
	{
		Message msg = mHandler.obtainMessage();  
	    msg.what = DialogBox.SHOW_DIALOG;  
	    DialogMessage dm = new DialogMessage(title, text);  
	    msg.obj = dm;  
	    msg.sendToTarget();  
	}
	
}
创建一个DialogMessage.java,封装dialog要显示的数据:

package com.DialogBox.org;

public class DialogMessage {
	public String title;
	public String msg;
}
修改主程序DialogBox.java

public class DialogBox extends Cocos2dxActivity{
	
	public static final int SHOW_DIALOG = 0x0001;
	
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);	
		JniTestHelper.init(mHandler);
		JniTestHelper.setPackageName(this.getPackageName());
	}

    public Cocos2dxGLSurfaceView onCreateView() {
    	Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
    	// GuideLayer should create stencil buffer
    	glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);
    	
    	return glSurfaceView;
    }

    static {
        System.loadLibrary("cocos2dcpp");
    }    
    
    //显示对话框的函数
    private Handler mHandler = new Handler()
    {
		@Override
		public void handleMessage(Message msg) {
			switch(msg.what)
			{
			case SHOW_DIALOG:
				DialogMessage dm = (DialogMessage)msg.obj;
				new AlertDialog.Builder(DialogBox.this)
				.setTitle(dm.titile)
				.setMessage(dm.message).setNegativeButton("cancle", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
					}
				})
				.setPositiveButton("Ok", 
						new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
						JniTestHelper.exitApp();
					}
				})
				.create().show();
				break;
			}
		}
    };
}

编译运行,效果如下:


cocos2d-x 通过JNI实现c/c++和Android的java层函数交互


       引用博文:http://codingnow.cn/cocos2d-x/992.html

cocos2d-x 通过JNI实现c/c++和Android的java层函数交互,布布扣,bubuko.com

cocos2d-x 通过JNI实现c/c++和Android的java层函数交互

上一篇:clickhouse 类型错误、聚合函数错误——字段别名的注意事项


下一篇:微信公众号开发之群发消息