Cocos2d-x3.0中集成社交分享ShareSDK的详细步骤和常见问题解决
给自己的手机游戏增加些社交分享功能,有助于游戏宣传和提升知名度,是一种不错的社交营销手段。国内这方面的第三方插件有不少,比如ShareSDK、友盟分享组件、Baidu分享组件等,之前在研究2.2.2版本时,集成了ShareSDK这个组件,这次迁移到Cocos2d-x3.0rc2依旧选择集成ShareSDK,这里就来说说集成的过程,遇到的一些问题以及解决方法。这里仅以Android平台游戏集成为例。
一、功能描述、SDK版本和帐号准备
功能大致是这样的:在游戏中设置一个按钮,点击这个按钮,弹出知名社交平台的分享图标集窗口,用户选择分享目标后,相关信息分享到对应的社交平台。分享结果通知通过Toast显示在屏幕的下方。
这次依旧使用ShareSDKforAndroid2.3.7版本(ShareSDK-Android-2.3.7),Cocos2d-x的版本为3.0rc2。
集成前,你需要有一个基于Cocos2d-x3.0rc2的可运行的Android平台游戏project,我们的集成就基于该project,这里我们的project名为GameDemo,GameDemo的源码结构大致是:
GameDemo/
?Classes/
?proj.android/
?Resources/
?cocos2d/
?CMakeLists.txt
?……
使用ShareSDK前,你需要在各大主流社交平台(微信、微博)申请开发者帐号以及游戏接入权限(app_key、app_secret)等,当然在ShareSDK站点也应该有自己的帐号和应用AppKey,这些申请的审核需要几个工作日,甚至更长。
二、ShareSDK集成步骤
按照ShareSDK官方manual说法,Cocos2d-x集成ShareSDK有三种方式,之前在Cocos2d-x2.2.2引擎中采用的是专用组件集成的方式,该组件(C2DXShareSDKSample)可以在这里下载(https://github.com/ShareSDKPlatform/C2DXShareSDKSample,该组件近期已经fix了我之前发现的bug)。
1.jar包集成
这次我们主要做微博、微信的社交分享,因此只需要微博、微信相关jar包。在C2DXShareSDKSample/proj.android/libs下,我们找到以下几个jar包:
-rw-rw-r?1tonybaitonybai 97K 4月 818:10mframework.jar
-rw-rw-r?1tonybaitonybai112K 4月 817:39ShareSDK-Core-2.3.7.jar
-rw-rw-r?1tonybaitonybai 19K 4月 817:39ShareSDK-SinaWeibo-2.3.7.jar
-rw-rw-r?1tonybaitonybai4.3K 4月 817:39ShareSDK-Wechat-2.3.7.jar
-rw-rw-r?1tonybaitonybai 29K 4月 817:39ShareSDK-Wechat-Core-2.3.7.jar
-rw-rw-r?1tonybaitonybai4.6K 4月 817:39ShareSDK-Wechat-Favorite-2.3.7.jar
-rw-rw-r?1tonybaitonybai4.4K 4月 817:39ShareSDK-Wechat-Moments-2.3.7.jar
把这些jar包文件Copy到GameDemo/proj.android/libs下。
2.配置文件与资源部分集成
修改GameDemo/proj.android/AndroidManifest.xml文件,在application标签下,添加如下Activity标签:
<activity
android:name="cn.sharesdk.framework.ShareSDKUIShell"
android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:windowSoftInputMode="stateHidden|adjustResize">
</activity>
<activity
android:name=".wxapi.WXEntryActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:exported="true"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
将C2DXShareSDKSample/proj.android/res下的如下目录中的文件复制到GameDemo/proj.android/res下:
drawable-hdpi/ drawable-ldpi/ drawable-mdpi/
drawable-xhdpi/ layout/ values/ values-en/
注意,类似icon.png这种文件就不要复制了,自己做一下判断就好。
3.C++部分代码集成
将C2DXShareSDKSample/Classes下的C2DXShareSDK文件夹Copy到GameDemo/Classes下面。
由于Cocos2d-x3.0rc2的类命名发生了变化,我们需要对C2DXShareSDK中使用到的引擎中的类名以及方法名进行修改。但实际上Cocos2d-x3.0rc2考虑到了一些兼容性的问题,大部分名字通过cocos2d/cocos/deprecated/CCDeprecated.h中定义的typedef得以保留,虽然这些名字已经被建议deprecated了。rc2中CCObject被改名为Ref了,这个我们需要手工在C2DXShareSDK进行修改。
另外ShareSDK组件在实现时大量使用了CCDictionary、CCArray和CCString,而这三个类在Cocos2d-x3.0rc2中均被deprecated了,但我们依然可以使用,所以我们可以不做修改。但以后随着cocos2d-x版本的演进,这些类很可能被彻底移除出引擎,我们就需要重新使用其替代品进行实现了。
此外我们还需要手工修改一下C2DXShareSDK/Android/JSON/CCJSONConverter.cpp文件中的getObjJson方法,因为rc2中CCDictionary、CCString、CCArray这些类的真实名称都已经换成了__Dictionary、__String和__Array,CCDictionary、CCString、CCArray只是些typedef,因此要像下面这样做些修改(如果你是集成cocos2d-x2.x.x版本,则无需做下面修改):
cJSON*CCJSONConverter::getObjJson(Ref*obj)
{
std::strings=typeid(*obj).name();
if(s.find("__Dictionary")!=std::string::npos){
cJSON*json=cJSON_CreateObject();
convertDictionaryToJson((CCDictionary*)obj,json);
returnjson;
}elseif(s.find("__Array")!=std::string::npos){
cJSON*json=cJSON_CreateArray();
convertArrayToJson((CCArray*)obj,json);
returnjson;
}elseif(s.find("__String")!=std::string::npos){
CCString*s=(CCString*)obj;
cJSON*json=cJSON_CreateString(s->getCString());
returnjson;
}elseif(s.find("CCNumber")!=std::string::npos){
CCNumber*n=(CCNumber*)obj;
cJSON*json=cJSON_CreateNumber(n->getDoubleValue());
returnjson;
}elseif(s.find("CCNull")!=std::string::npos){
cJSON*json=cJSON_CreateNull();
returnjson;
}
CCLog("CCJSONConverterencounteredanunrecognizedtype");
returnNULL;
}
CCNumber和CCNull是ShareSDK组件自己实现的类名,这里无需修改。
接下来我们需要在AppDelegate.cpp中对ShareSDK做初始化了:
boolAppDelegate::applicationDidFinishLaunching(){
……
initShareSDK();
…..
}
voidAppDelegate::initShareSDK()
{
//sinaweibo
CCDictionary*sinaConfigDict=CCDictionary::create();
sinaConfigDict->setObject(CCString::create("YOUR_WEIBO_APPKEY"),"app_key");
sinaConfigDict->setObject(CCString::create("YOUR_WEBIO_APPSECRET"),"app_secret");
sinaConfigDict->setObject(CCString::create("http://www.sharesdk.cn"),"redirect_uri");
C2DXShareSDK::setPlatformConfig(C2DXPlatTypeSinaWeibo,sinaConfigDict);
//wechat
CCDictionary*wcConfigDict=CCDictionary::create();
wcConfigDict->setObject(CCString::create("YOUR_WECHAT_APPID"),"app_id");
C2DXShareSDK::setPlatformConfig(C2DXPlatTypeWeixiSession,wcConfigDict);
C2DXShareSDK::setPlatformConfig(C2DXPlatTypeWeixiTimeline,wcConfigDict);
C2DXShareSDK::setPlatformConfig(C2DXPlatTypeWeixiFav,wcConfigDict);
C2DXShareSDK::open(CCString::create("YOUR_SHARESDK_APPKEY"),false);
}
在Share按钮的事件回调函数中调用ShareSDK的接口进行社交平台分享:
voidGameScene::menuShareCallback(Ref*sender)
{
Dictionary*content=Dictionary::create();
content->setObject(String::create("ShareSDKforCocos2d-x3.0rc2社交分享测试。")
,"content");
content->setObject(String::create("ShareSDK分享测试"),"title");
content->setObject(String::create("http://tonybai.com"),"titleUrl");
content->setObject(String::create("http://tonybai.com"),"url");
content->setObject(String::create("TonyBai"),"site");
content->setObject(String::create("http://tonybai.com"),"siteUrl");
content->setObject(String::createWithFormat("%s",YOUR_LOCAL_IMAGE_PATH)
,"image");
content->setObject(String::createWithFormat("%d",C2DXContentTypeNews)
,"type");
C2DXShareSDK::showShareMenu(NULL,content,CCPointMake(100,100),
C2DXMenuArrowDirectionLeft,shareResultHandler);
}
voidshareResultHandler(C2DXResponseStatestate,
C2DXPlatTypeplatType,
Dictionary*shareInfo,
Dictionary*error)
{
AppDelegate*app=(AppDelegate*)Application::getInstance();
switch(state){
caseC2DXResponseStateSuccess:
CCLog("ShareOk");
app->showShareResultToast("分享成功");
break;
caseC2DXResponseStateFail:
app->showShareResultToast("分享失败");
CCLog("ShareFailed");
break;
default:
break;
}
}
showShareResultToast实现如下:
voidAppDelegate::showShareResultToast(constchar*msg)
{
JniMethodInfot;
if(JniHelper::getStaticMethodInfo(t,"YOUR_ACTIVITY_NAME",
"showShareResultToast","(Ljava/lang/String;)V")){
jstringjmsg=t.env->NewStringUTF(msg);
t.env->CallStaticVoidMethod(t.classID,t.methodID,jmsg);
if(t.env->ExceptionOccurred()){
t.env->ExceptionDescribe();
t.env->ExceptionClear();
return;
}
t.env->DeleteLocalRef(t.classID);
}
}
4.Java部分代码集成
在GameDemo/proj.android/src下面建立cn/sharesdk路径,将C2DXShareSDKSample/proj.android/src/cn/sharesdk下的onekeyshare和ShareSDKUtils.javaCopy到GameDemo/proj.android/src/cn/sharesdk下面。
将ShareSDK-Android-2.3.7.zip解压后的ShareSDKforAndroid/Src/wxapiCopy到GameDemo/proj.android/src/com.tonybai.game/下。
修改GameDemo/proj.android/src/com.tonybai.game/GameDemoActivity.java文件:
importandroid.widget.Toast;
importcn.sharesdk.ShareSDKUtils;
…
publicclassGameDemoActivityextendsCocos2dxActivity{
privatestaticContextcontext;
privatestaticHandlernotifyHandler=newHandler(){
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
case1:
Stringmessage=(String)msg.obj;
Toast.makeText(context,message,
Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
};
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
context=this;
ShareSDKUtils.prepare();
ShareSDKUtils.initSDK("YOUR_SHARESDK_APPKEY",true);
}
publicstaticvoidshowShareResultToast(Stringresult){
Messagemsg=newMessage();
msg.what=1;
msg.obj=result;
notifyHandler.sendMessage(msg);
}
@Override
publicvoidonDestroy(){
ShareSDKUtils.stopSDK();
super.onDestroy();
}
}
三、问题与解决方法
按照上面的集成方法修改后,通过cocos编译app,在模拟器运行GameDemo,点击Share,理论上屏幕下方会出现ShareSDK的分享窗口,选择“新浪微博”图标,会打开“图文分享”内容窗口,点击窗口右上角的“分享”即可。
【问题1】“图文分享”窗口内容可编辑,并且总是弹出软键盘,影响体验。
期望:内容不可编辑,默认不弹出软键盘
解决方法:
打开proj.android/src/cn/sharesdk/onekeyshare/EditPage.java,做如下修改:
将窗口的软输入方式默认改为SOFT_INPUT_STATE_HIDDEN。
publicvoidsetActivity(Activityactivity){
super.setActivity(activity);
if(dialogMode){
activity.setTheme(android.R.style.Theme_Dialog);
activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
activity.getWindow().setSoftInputMode(
//WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);//default:hidden
}
在initPageView中增加一行:etContent.setKeyListener(null)。让窗口内容无法修改。
……
//文字输入区域
etContent=newEditText(getContext());
etContent.setGravity(Gravity.LEFT|Gravity.TOP);
etContent.setBackgroundDrawable(null);
etContent.setText(String.valueOf(reqData.get("text")));
etContent.setKeyListener(null);//maketheedittextuneditable
etContent.setLayoutParams(lpEt);
……
}
【问题2】向微博分享,点击“分享”后,过一会程序异常停止。
原因分析:
通过调试观察,发现ShareSDK在解析从Weibo收到的Json包时出现内存违法访问。具体位置是在解析一个数组对象时出现的问题。ShareSDK用CCArray来存储Json中的数组对象。该问题在cocos2d-x2.2.2版本中不会出现,但在cocos2d-x3.0rc2版本中会出现。经代码对比发现,3.0rc2版本中的CCArray的实现与2.2.2CCArray实现有很大不同,似乎是做了较大重构,暂不能确定是否是3.0rc2版本中CCArray实现的bug。
解决方法:由于后续的分享结果通知成功与否只需要根据分享的状态来决定,因此我们只需解析出"status"、“action”和“platform”这三个CCNumber类型字段的值即可。CCArray类型的对象我们并不需要,因此我们只需绕过对Array类型字段的解析和存储即可,修改如下:
//Classes/C2DXShareSDK/Android/JSON/CCJSONConverter.cpp
voidCCJSONConverter::convertJsonToDictionary(cJSON*json,CCDictionary*dictionary)
{
dictionary->removeAllObjects();
cJSON*j=json->child;
while(j){
if(j->type==cJSON_Number){
Ref*obj=getJsonObj(j);
dictionary->setObject(obj,j->string);
}
j=j->next;
}
}
四、其他
在使用ShareSDK做社交分享时,注意下面两个现象:
1)第一次进行微博或微信分享时,会打开授权页面,授权后才能分享成功;
2)微信分享窗口只有在手机联网状态下才能打开。如果手机无法联网,那微信好友、朋友圈和收藏分享将无法打开分享窗口,也不会有什么提示。
相关文章
- EasyNVR集成iframe后,视频无法播放如何解决?
- springboot集成mybatisplus分页_mybatis分页查询原理
- 微服务架构开发实战:如何集成Zuul和实现API网关?
- Spring cloud集成Zipkin链路追踪
- Android JetPack~ DataBinding(数据绑定)(一) 集成与使用
- EasyCVR配置https证书后,取流集成至播放器无法播放的情况排查与解决
- 直播预告 | 姚班校友李远志:理解深度学习中的集成、知识蒸馏和自蒸馏
- IntelliJ IDEA 2023 for Mac 完美兼容版:最智能的 Java 集成开发环境
- android 集成百度地图详解手机开发
- 开发环境Linux下实现PHP的全功能集成开发环境(linuxphp集成)
- Panos Panay预告Windows 11与Spotify流媒体音乐服务的新集成
- MySQL与微服务架构的无缝集成:优化数据处理与提升业务效率的新策略(mysql微服务)
- PHP5.0深度集成MSSQL架构实现技术(php5.0 mssql)
- SSM框架集成Redis实现快速缓存优化(ssm框架集成redis)
- 解决系统性能问题Redis集成解决方案(redis集成解决方案)
- 解决VR内身份识别和支付,七鑫易维推出集成虹膜识别技术的眼球追踪解决方案
- 没有sa密码无法集成windows身份验证登录的解决方法