Cocos2d-x从C++端调用Android端的非静态函数接口

来源:互联网 发布:pdf.js如何使用 编辑:程序博客网 时间:2024/05/01 01:37

当我们游戏开发好要移植到Android后,在我们的游戏中,可能有打开跳转谷歌市场和添加用户反馈的功能。这些功能的一个特点就是:我在C++端(也就是我的游戏中)的特定地方调用,在Android端实现。也就是说,我要在C++端调用Android中跳转谷歌市场和添加用户反馈的函数接口。那么,如何在C++端调用Android中的函数接口呢?请看正文。

正文:

要在C++端调用Android中的函数接口,需要用到Jni。

C++端的实现,如下:

在cocos2dx\platform\android\jni 中有这么一个类JniHelp.cpp。而我们需要用到里面的这一个函数:

static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);

第一个参数是jni函数信息的结构体,如下:

typedef struct JniMethodInfo_ {     JNIEnv *    env;     jclass      classID;     jmethodID   methodID; } JniMethodInfo;

结构体中的第一个成员是jni固有函数的一个特殊自变量,通过它可以对jni函数进行调用,第二个成员是类的名称(包名+类名),第三个成员是方法名称

第二个参数是类的名称(包名+类名),第三个参数是方法名称,第四个参数是函数参数和函数返回值类型

具体的调用代码如下:

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判断当前是否为Android平台         JniMethodInfo minfo;//定义Jni函数信息结构体         //getStaticMethodInfo 次函数返回一个bool值表示是否找到此函数         bool isHave = JniHelper::getStaticMethodInfo(minfo,"com/tysci/cocos2dx/MonsterMustDieAnd","rate", "()V");                                                                                                                                                             if (!isHave) {             CCLog("jni:此函数不存在");         }else{             CCLog("jni:此函数存在");             //调用此函数             minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID);         }         CCLog("jni-java函数执行完毕"); #endif                                                                                                                                                    #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判断当前是否为Android平台         JniMethodInfo minfo;//定义Jni函数信息结构体         //getStaticMethodInfo 次函数返回一个bool值表示是否找到此函数         bool isHave = JniHelper::getStaticMethodInfo(minfo,"com/tysci/cocos2dx/MonsterMustDieAnd","feedBack", "()V");                                                                                                                                                             if (!isHave) {             CCLog("jni:此函数不存在");         }else{             CCLog("jni:此函数存在");             //调用此函数             minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID);         }         CCLog("jni-java函数执行完毕"); #endif

JniHelp::getStaticMethodInfo(参数。。。)这个函数的作用其实就是配置我们声明的minfo这个对象的信息,之后

minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID)这句就是调用的Jni函数,达到了从C++到Android的跨平台的调用。

这里再补充说明一点,"()V"的意义:()的意思是该函数无参,若有参数V的意思是该函数返回值为void。这里给出参数、返回值的样式对照表,如下:


若是所用到的类型不在这里面,可以仿照这个方法引用:(Ljava/lang/String;Ljava/lang/String;)V",L加上路径名,多个参数中间用分号隔开。

C++中代码实现完了,这边我们调用的是Android中的com/tysci/cocos2dx这个包里面的MonsterMustDieAnd这个类的rate()和feedBack()这两个函数。

Android端的实现,如下:

首先,通过getStaticMethodInfo我们知道要调用的Android端的函数必须的静态的!

于是,一开始有了如下代码:

public static void rate(){                                                                                                                Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("market://details?id=" + getPackageName())); startActivity(intent); }

这段代码,一看就是不能通过编译的。先不提getPackageName(),以为我们可以直接换成项目包名。startActivity(intent);这句的错误就是:静态函数中不能调用非静态方法。

这就纠结了,C++端要求我们要调用Android中的静态函数(其实JniHelp这个类中还有一个getMethodInfo()的方法,从字面上的意思它是要调用非静态的函数,但是我不知道这是否可行,或者说我不知道如何正确的使用这个函数。据我同事实验用这个函数直接调用Android中的非静态函数是会报错的),而我们想调用的是一个非静态函数,明显的冲突了。

想过了挺多的方法,比如在Android中建立一个单例对象,通过getInstance()这个函数来获取单例对象,然后通过这个单例对象再调用这个单例类里面的非静态函数,结果失败了,可能是我的用法有问题吧。

最后,我的解决方法是通过Android中的Handler。这类似一个间接调用,或者说一个代理。我在C++端调用一个Android中的静态方法,这个方法中有Message,然后用Handler来sendMessage。而在我Android中的主线程,我实例化了一个handler的对象,它时刻的在等待handleMessage,捕获消息。只要我C++端一调用,静态方法中发送消息,主线程中的handler捕获消息,这实现了间接的调用非静态方法。在这里我们不难理解handler的作用,它充当的就是一个第三方的角色,C++不方便和Android的非静态方法沟通(或者说没有权限),就告诉Handler要调用Android的非静态方法,而Handler有权限调用,自然而然就可以了。

下面给出具体的代码,如下:

        private static Handler handler;         private final static int HANDLER_GOTO_GOOGLE = 1;         private final static int HANDLER_GOTO_UMENG = 2;                                       // 对接C++的静态方法,发送消息到主线程,该方法用于谷歌市场跳转     public static void rate() {         Message msg = new Message();         msg.what = HANDLER_GOTO_GOOGLE;         handler.sendMessage(msg);     }                                           // 对接C++的静态方法,发送消息到主线程,该方法用于用户反馈界面跳转     public static void feedBack() {         Message msg = new Message();         msg.what = HANDLER_GOTO_UMENG;         handler.sendMessage(msg);     }                                       // 主线程中接收消息,加到onCreate()里         handler = new Handler() {             public void handleMessage(Message msg) {                 switch (msg.what) {                 // 谷歌市场跳转                 case HANDLER_GOTO_GOOGLE:                         Intent intent = new Intent(Intent.ACTION_VIEW);                     intent.setData(Uri.parse("market://details?id="                            + getPackageName()));                     startActivity(intent);                     break;                 // 友盟反馈---用户反馈界面跳转                 case HANDLER_GOTO_UMENG:                     UMFeedbackService.openUmengFeedbackSDK(MonsterMustDieAnd.this);                     break;                 }             }         };

总结:总的一句话来说,就是通过Handler来间接调用Android中的非静态方法。

0 0
原创粉丝点击