一、需求:
项目为cocos2d-X开发的游戏,需要为android版本添加微信分享, 具体是在游戏界面中添加一个分享按钮,点击该按钮即可分享。
最终考虑通过jni,在C/C++层通过jni调用微信AnroidSDK。
在分享成功后,在java层调用C++层使角色复活.
二、本地(native)调用java代码:
分享按钮应该是在游戏中,也就是C/C++的本地层,android分享SDK则是在java层,所以这里用本地函数调用java方法。
先贴native代码:MyJni.h和MyJni.cpp
#ifndef __SkiSim__MyJni__
#define __SkiSim__MyJni__
#include <string.h>
#include <jni.h>
void openUmengShareJni(int score);
#include "MyJni.h"
#include "platform/android/jni/JniHelper.h"
#include "cocos2d.h"
#include "MainLayer.h"
using namespace cocos2d;
extern JNIEnv* jniEnv;
jclass TestProvider;
jmethodID openUmengShare;
void openUmengShareJni(int score) {
JniMethodInfo methodInfo;
if (TestProvider == NULL || openUmengShare == NULL) {
return;
} else {
jniEnv->CallStaticObjectMethod(TestProvider, openUmengShare, score);
}
}
int InitProvider() {
__android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin 1");
if (jniEnv == NULL) {
return 0;
}
if (TestProvider == NULL) {
TestProvider = jniEnv->FindClass(
"com/andrew/game/Flappy");
if (TestProvider == NULL) {
return -1;
}
}
if (openUmengShare == NULL) {
openUmengShare = jniEnv->GetStaticMethodID(TestProvider,
"openShareBoard", "(I)V");
if (openUmengShare == NULL) {
jniEnv->DeleteLocalRef(TestProvider);
return -2;
}
}
}
注意extern JNIEnv* jniEnv;这个变量,由于在cocos2dx项目中,都会有一个main.cpp源文件,打开即可看到
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit函数,我们在这个函数中初始化jniEnv变量:
先声明jniEnv:
JNIEnv* jniEnv;
在
Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit函数中:
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env,
jobject thiz, jint w, jint h) {
if(jniEnv == NULL){
jniEnv = env;
}
if (!CCDirector::sharedDirector()->getOpenGLView()) {
CCEGLView *view = CCEGLView::sharedOpenGLView();
view->setFrameSize(w, h);
AppDelegate *pAppDelegate = new AppDelegate();
CCApplication::sharedApplication()->run();
}
}
可以看到,我们定义了void openUmengShareJni(int score) 这个函数,最关键的代码在于:
创建TestProvider这个jclass对象
TestProvider = jniEnv->FindClass("com/andrew/game/Flappy");
以及函数openUmengShare这个jmethodId对象
openUmengShare = jniEnv->GetStaticMethodID(TestProvider,"openShareBoard", "(I)V");
调用java方法:
jniEnv->CallStaticObjectMethod(TestProvider, openUmengShare, score);
然后上java代码:
com.andrew.game.Flappy:
static void openShareBoard(int score){
//分享代码
}
最后,在任何需要调用分享代码的地方,include "MyJni.h"并调用openUmengShareJni(int score)即可实现分享功能。
有几个容易出错的地方,第一是java函数的签名不要弄错,在创建TestProvider时的参数:"com/andrew/game/Flappy"即java包名和类名:com.andrew.game.Flappy,
jniEnv->GetStaticMethodID(TestProvider,"openShareBoard", "(I)V");表示方法名为openShareBoard,参数"(I)V"即返回值为void,参数为int,
jniEnv->GetStaticMethodID表示该方法有static修饰。大家可以对比java代码即可发现。
三、java调用本地代码:
显然,角色复活是游戏中的事件,而分享成功后的回调仍在java层,所以这里要用java调用本地函数。
先上java代码:
com.andrew.game.Flappy:
public native static int revival();
本地代码:
在MyJni.h中添加jni接口:
extern "C"{
JNIEXPORT jint Java_com_andrew_game_Flappy_revival(JNIEnv* env,jobject thiz);
}
在MyJni.cpp中添加实现:
extern "C" {
JNIEXPORT jint Java_
com_andrew_game_Flappy
_revival(JNIEnv* env,jobject thiz) {/**CCDirector *director = CCDirector::sharedDirector();if (director->getOpenGLView()) {
CCScene *scene = director->getRunningScene();
MainLayer *layer = (MainLayer*) scene->getChildByTag(2222);
layer->revival();
}
*/
}
被注释的代码是该游戏中的角色复活代码。可以在此添加任何你需要实现的任务.需要注意的地方仍是包名、类名和方法名.
JNIEXPORT jint Java_com_andrew_game_Flappy_revival(JNIEnv* env,jobject thiz)
//返回值是int,对应包名cn.andrew.game,类名Flappy,方法为static static int revival();