Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Cocos2d-x 3.0中集成社交分享ShareSDK的詳細步驟和常見問題解決

Cocos2d-x 3.0中集成社交分享ShareSDK的詳細步驟和常見問題解決

編輯:關於Android編程

給自己的手機游戲增加些社交分享功能,有助於游戲宣傳和提升知名度,是一種不錯的社交營銷手段。國內這方面的第三方插件有不少,比如ShareSDK、友 盟分享組件、Baidu分享組件等,之前在研究2.2.2版本時,集成了ShareSDK這個組件,這次遷移到Cocos2d-x 3.0rc2依舊選擇集成ShareSDK,這裡就來說說集成的過程,遇到的一些問題以及解決方法。這裡僅以Android平台游戲集成為例。


一、功能描述、SDK版本和帳號准備

功能大致是這樣的:在游戲中設置一個按鈕,點擊這個按鈕,彈出知名社交平台的分享圖標集窗口,用戶選擇分享目標後,相關信息分享到對應的社交平台。分享結果通知通過Toast顯示在屏幕的下方。

這次依舊使用ShareSDK for Android 2.3.7版本(ShareSDK-Android-2.3.7),Cocos2d-x的版本為3.0rc2。

集成前,你需要有一個基於Cocos2d-x 3.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-x 2.2.2引擎中采用的是專用組件集成的方式,該組件(C2DXShareSDKSample)可以在這裡下載(https://github.com/ShareSDKPlatform/C2DXShareSDKSample,該組件近期已經fix了我之前發現的bug)。

1.jar包集成

這次我們主要做微博、微信的社交分享,因此只需要微博、微信相關jar包。在C2DXShareSDKSample/proj.android/libs下,我們找到以下幾個jar包:
復制代碼 代碼如下:
  -rw-rw-r– 1 tonybai tonybai  97K  4月  8 18:10 mframework.jar
  -rw-rw-r– 1 tonybai tonybai 112K  4月  8 17:39 ShareSDK-Core-2.3.7.jar
  -rw-rw-r– 1 tonybai tonybai  19K  4月  8 17:39 ShareSDK-SinaWeibo-2.3.7.jar
  -rw-rw-r– 1 tonybai tonybai 4.3K  4月  8 17:39 ShareSDK-Wechat-2.3.7.jar
  -rw-rw-r– 1 tonybai tonybai  29K  4月  8 17:39 ShareSDK-Wechat-Core-2.3.7.jar
  -rw-rw-r– 1 tonybai tonybai 4.6K  4月  8 17:39 ShareSDK-Wechat-Favorite-2.3.7.jar
  -rw-rw-r– 1 tonybai tonybai 4.4K  4月  8 17:39 ShareSDK-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-x 3.0rc2的類命名發生了變化,我們需要對C2DXShareSDK中使用到的引擎中的類名以及方法名進行修改。但實際上Cocos2d-x 3.0rc2考慮到了一些兼容性的問題,大部分名字通過cocos2d/cocos/deprecated/CCDeprecated.h中定義的typedef得以保留,雖然這些名字已經被建議deprecated了。rc2中CCObject被改名為Ref了,這個我們需要手工在C2DXShareSDK進行修改。

另外ShareSDK組件在實現時大量使用了CCDictionary、CCArray和CCString,而這三個類在Cocos2d-x 3.0rc2中均被deprecated了,但我們依然可以使用,所以我們可以不做修改。但以後隨著cocos2d-x版本的演進,這些類很可能被徹底移除出引擎,我們就需要重新使用其替代品進行實現了。

此外我們還需要手工修改一下C2DXShareSDK/Android/JSON/CCJSONConverter.cpp文件中的getObjJson方 法,因為rc2中CCDictionary、CCString、CCArray這些類的真實名稱都已經換成了__Dictionary、__String 和__Array,CCDictionary、CCString、CCArray只是些typedef,因此要像下面這樣做些修改(如果你是集成 cocos2d-x 2.x.x版本,則無需做下面修改):
復制代碼 代碼如下:
cJSON * CCJSONConverter::getObjJson(Ref * obj)
{
    std::string s = typeid(*obj).name();
    if(s.find("__Dictionary")!=std::string::npos){
        cJSON * json = cJSON_CreateObject();
        convertDictionaryToJson((CCDictionary *)obj, json);
        return json;
    }else if(s.find("__Array")!=std::string::npos){
        cJSON * json = cJSON_CreateArray();
        convertArrayToJson((CCArray *)obj, json);
        return json;
    }else if(s.find("__String")!=std::string::npos){
        CCString * s = (CCString *)obj;
        cJSON * json = cJSON_CreateString(s->getCString());
        return json;
    }else if(s.find("CCNumber")!=std::string::npos){
        CCNumber * n = (CCNumber *)obj;
        cJSON * json = cJSON_CreateNumber(n->getDoubleValue());
        return json;
    }else if(s.find("CCNull")!=std::string::npos){
        cJSON * json = cJSON_CreateNull();
        return json;
    }
    CCLog("CCJSONConverter encountered an unrecognized type");
    return NULL;
}

CCNumber和CCNull是ShareSDK組件自己實現的類名,這裡無需修改。

接下來我們需要在AppDelegate.cpp中對ShareSDK做初始化了:
復制代碼 代碼如下:
bool AppDelegate::applicationDidFinishLaunching() {
    … …
    initShareSDK();
    … ..
}

void AppDelegate::initShareSDK()
{
    // sina weibo
    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的接口進行社交平台分享:
復制代碼 代碼如下:
void GameScene::menuShareCallback(Ref* sender)
{
    Dictionary *content = Dictionary::create();

    content->setObject(String::create("ShareSDK for Cocos2d-x 3.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("Tony Bai"), "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);
}

void shareResultHandler(C2DXResponseState state,
                        C2DXPlatType platType,
                        Dictionary *shareInfo,
                        Dictionary *error)
{
    AppDelegate *app = (AppDelegate*)Application::getInstance();
    switch (state) {
        case C2DXResponseStateSuccess:
            CCLog("Share Ok");
            app->showShareResultToast("分享成功");
            break;
        case C2DXResponseStateFail:
            app->showShareResultToast("分享失敗");
            CCLog("Share Failed");
            break;
        default:
            break;
    }
}

showShareResultToast實現如下:
復制代碼 代碼如下:
void AppDelegate::showShareResultToast(const char *msg)
{
    JniMethodInfo t;
    if (JniHelper::getStaticMethodInfo(t, "YOUR_ACTIVITY_NAME",
        "showShareResultToast", "(Ljava/lang/String;)V")) {
        jstring jmsg = 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.java Copy到GameDemo/proj.android/src/cn/sharesdk下面。

將ShareSDK-Android-2.3.7.zip解壓後的ShareSDK for Android/Src/wxapi Copy到GameDemo/proj.android/src/com.tonybai.game/下。

修改GameDemo/proj.android/src/com.tonybai.game/GameDemoActivity.java文件:
復制代碼 代碼如下:
import android.widget.Toast;
import cn.sharesdk.ShareSDKUtils;

public class GameDemoActivity extends Cocos2dxActivity {

    private static Context context;

    private static Handler notifyHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    String message = (String) msg.obj;
                    Toast.makeText(context, message,
                      Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = this;
        ShareSDKUtils.prepare();
        ShareSDKUtils.initSDK("YOUR_SHARESDK_APPKEY", true);
    }

    public static void showShareResultToast(String result) {
        Message msg = new Message();
        msg.what = 1;
        msg.obj = result;
        notifyHandler.sendMessage(msg);
    }

    @Override
    public void onDestroy() {
        ShareSDKUtils.stopSDK();
        super.onDestroy();
    }
}

三、問題與解決方法

按照上面的集成方法修改後,通過cocos編譯app,在模擬器運行GameDemo,點擊Share,理論上屏幕下方會出現ShareSDK的分享窗口,選擇“新浪微博”圖標,會打開“圖文分享”內容窗口,點擊窗口右上角的“分享”即可。

【問題1】“圖文分享”窗口內容可編輯,並且總是彈出軟鍵盤,影響體驗。

 期望:內容不可編輯,默認不彈出軟鍵盤
 解決方法:
      打開proj.android/src/cn/sharesdk/onekeyshare/EditPage.java,做如下修改:

      將窗口的軟輸入方式默認改為SOFT_INPUT_STATE_HIDDEN。
復制代碼 代碼如下:
      public void setActivity(Activity activity) {
        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)。讓窗口內容無法修改。
復制代碼 代碼如下:    private void initPageView() {
         … …
        // 文字輸入區域
        etContent = new EditText(getContext());
        etContent.setGravity(Gravity.LEFT | Gravity.TOP);
        etContent.setBackgroundDrawable(null);
        etContent.setText(String.valueOf(reqData.get("text")));
        etContent.setKeyListener(null);//make the edittext uneditable
        etContent.setLayoutParams(lpEt);
        … …
    }

【問題2】向微博分享,點擊“分享”後,過一會程序異常停止。

 原因分析:
        通過調試觀察,發現ShareSDK在解析從Weibo收到的Json包時出現內存違法訪問。具體位置是在解析一個數組對象時出現的問題。 ShareSDK用CCArray來存儲Json中的數組對象。該問題在cocos2d-x 2.2.2版本中不會出現,但在cocos2d-x 3.0rc2版本中會出現。經代碼對比發現,3.0rc2版本中的CCArray的實現與2.2.2 CCArray實現有很大不同,似乎是做了較大重構,暫不能確定是否是3.0rc2版本中CCArray實現的bug。

 解決方法:由於後續的分享結果通知成功與否只需要根據分享的狀態來決定,因此我們只需解析出"status"、“action”和“platform” 這三個CCNumber類型字段的值即可。CCArray類型的對象我們並不需要,因此我們只需繞過對Array類型字段的解析和存儲即可,修改如下:
復制代碼 代碼如下:
// Classes/C2DXShareSDK/Android/JSON/CCJSONConverter.cpp

void CCJSONConverter::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) 微信分享窗口只有在手機聯網狀態下才能打開。如果手機無法聯網,那微信好友、朋友圈和收藏分享將無法打開分享窗口,也不會有什麼提示。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved