本文主要实现两个功能:
(1)通过Android sdk的API得到应用程序的包名(PackageName),然后传递给c++层函数。
(2)通过c++函数调用Android的java层函数,显示一个对话框,点击按钮退出程序。
cocos2d-x引擎对jni的操作进行了封装,提供了一个非常好用的类:JniHelper,定义了一些常用的接口,该文件位于cocos2dx/platform/android/jni目录下。
下面来解释JniHelper的两个常用函数: (1)getStaticMethodInfo 用来判断Java的类静态函数是否存在,并初始化结构体JniMethodInfo,该结构体封装了JNIEnv*和java.lang.Class对象、函数ID。这样就可以使用JNIEnv*调用 CallStaticXXXMethod(jclass clazz,jmethodID methodID,…)和 CallXXXMethod(jobject obj,…)等常用函数(XXX替换为函数返回值类型,如:Void,Int等)。 第一个参数为JniMethodInfo,第二个参数是类的绝对路径,第三个参数是函数名,第四个参数是函数签名(参数和返回类型),示例代码如下:
1
2
3
4
|
if
(JniHelper::getStaticMethodInfo(t,CLASS_NAME,
"showTipDialog"
,monospace!important; font-size:1em!important; padding:0px!important; color:blue!important; border:0px!important; bottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; min-height:auto!important; background:none!important">"(Ljava/lang/String;Ljava/lang/String;)V"
))
{
}
|
关于类型签名,请对照下图:
(2)getMethodInfo 该函数与getStaticMethodInfo类似,用于Java类的非静态函数。
2. 下面开始实现文章开头所述的两个功能,本文是在cocos2d-x 2.0版本 自适应屏幕分辨率demo的基础上添加的。 (1)利用cocos2d-x创建一个Android工程,名为JniTest,包名为com.alexzhou.jni,此时该包下会自动生成一个JniTest.java文件。 (2)首先来实现把应用程序的包名传递给c++函数,在包下创建JniTestHelper.java,该类封装了给c++调用的函数,添加如下代码:
4
5
6
7
8
|
private
static
Handler mHandler;
public
static
void
init(Handler handler)
{
JniTestHelper.mHandler = handler;
}
native
setPackageName(String packageName);
|
(3)打开JniTest.java,在onCreate函数中添加下面的代码:
5
protected
onCreate(Bundle savedInstanceState){
super
.onCreate(savedInstanceState);
JniTestHelper.init(mHandler);
JniTestHelper.setPackageName(
this
.getPackageName());
}
|
(4)java层的代码已经完成了,下面来编写jni层代码,在/jni/hellocpp/下创建test.h和test.cpp文件,test.h文件暂时不添加任何函数,代码如下: test.h
4
#ifndef TEST_H
#define TEST_H
#endif
|
test.cpp
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "cocos2d.h"
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include "test.h"
#include "JniTest.h"
#define CLASS_NAME "com/alexzhou/jni/JniTestHelper"
using
namespace
cocos2d;
extern
"C"
{
void
Java_com_alexzhou_jni_JniTestHelper_setPackageName(JNIEnv *env,jobject thiz,jstring packageName)
{
const
char
*pkgName = env->GetStringUTFChars(packageName,NULL);
setPackageName(pkgName);
env->ReleaseStringUTFChars(packageName,pkgName);
}
必须加上extern “C”,声明以c语言的方式进行编译,因为c++和c在编译时生成的函数签名不一样,可以在网上查找相关资料,不然运行的时候会出现链接错误。 (5)现在编写c++函数,在Classes目录下创建JniTest.h,代码如下:
13
#ifndef JNI_TEST_H
#define JNI_TEST_H
#include "cocos2d.h"
cocos2d;
setPackageName(
*packageName)
{
CCLog(
"packageName: %s"
,packageName);
}
(6)修改jni/Android.mk文件的LOCAL_SRC_FILES值 ,内容如下:
2
LOCAL_SRC_FILES := hellocpp
/main
.cpp
hellocpp
/test
.cpp
|
(7)编译运行
运行结果: (8)现在来实现通过c++函数调用java层函数,显示一个对话框。在JniTestHelper.java添加如下代码:
12
exitApp();
showTipDialog(
final
String title,
String text)
Message msg = mHandler.obtainMessage();
msg.what = JniTest.SHOW_DIALOG;
DialogMessage dm =
new
DialogMessage();
dm.title = title;
dm.msg = text;
msg.obj = dm;
msg.sendToTarget();
(9)创建一个DialogMessage.java,封装dialog要显示的数据。
11
/**
author:alexzhou
email :zhoujiangbohai@163.com
date :2012-12-14
**/
class
DialogMessage {
public
String title;
String msg;
(10) 修改JniTest.java,添加显示对话框的函数:
21
22
23
24
25
26
27
28
29
30
31
32
33
final
int
SHOW_DIALOG =
0x0001
;
private
Handler mHandler =
Handler()
@Override
handleMessage(Message msg) {
switch
(msg.what)
{
case
SHOW_DIALOG:
DialogMessage dm = (DialogMessage)msg.obj;
AlertDialog.Builder(JniTest.
)
.setTitle(dm.title)
.setMessage(dm.msg).setNegativeButton(
"cancle"
DialogInterface.OnClickListener() {
@Override
onClick(DialogInterface dialog,monospace!important; font-size:1em!important; padding:0px!important; border:0px!important; bottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; min-height:auto!important; background:none!important">which) {
dialog.dismiss();
}
})
.setPositiveButton(
"Ok"
DialogInterface.OnClickListener() {
@Override
which) {
dialog.dismiss();
JniTestHelper.exitApp();
}
})
.create().show();
break
;
}
}
};
|
(11)在test.h和test.cpp中添加显示对话框的接口: test.h
"C"
{
showTipDialog(
*title,
*msg);
28
*msg)
{
JniMethodInfo t;
(JniHelper::getStaticMethodInfo(t,monospace!important; font-size:1em!important; padding:0px!important; border:0px!important; bottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; min-height:auto!important; background:none!important">))
{
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);
}
}
{
setPackageName(pkgName);
}
Java_com_alexzhou_jni_JniTestHelper_exitApp(JNIEnv *env,jobject thiz)
{
exitApp();
}
(12) 修改Classes目录下的JniTest.h,添加代码:
exitApp()
{
CCDirector::sharedDirector()->end();
(13)到此为止,所有代码都已经完成了,代码比较简单就不详细解释了,现在编译运行,效果如下:
源码下载地址:http://download.csdn.net/detail/zhoujianghai/4890792 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
| | | | | |