cocos2dx3.15接入微信SDK实现登录和分享android studio2.3.3,首先开始呢,我必须得吐槽一下网上的教程以及微信开放平台官网,网上的教程主要是太老了代码虽然都能用但是不完整有的东西已经改了,官网就不用说了,文档垃圾,是很垃圾。参考作用几乎等于没有,唯一作用就是查看返回值以及一些参数有什么用。嗯对的。没话说。
现在开始教程:
第一步:
准备好你的APP_ID这个东西不解释了。如果不知道请先去[微信开放平台](https://open.weixin.qq.com/) 查看一下注册你的应用程序。然后登录功能是收费的,分享是免费的 下面是注册应用程序的步骤: 打开微信开放平台官网:
点击创建应用,按照提示输入好之后点击下一步。:
填写完了之后就提交审核,一般的话审核可能1-3天就好了
以安卓为例子,签名和包名必须要和你要接入的cocos项目的包名和签名一致,对于签名的获取请看下图:
打开 Android资源下载之后在右边下滑找到:
下载安装到手机上,我这里用的模拟器,然后把你们要接入的cocos项目也打包好安装的手机上之后打开之前安装的签名生成工具:
打开工具之后输入你的包名:
这个就是签名的获取
应用注册审核通过之后开始下一步
第二步:
将你的cocos项目导入到android studio2.3.3,其他环境参照相应的教程导入项目,但是推荐用android studio方便,导入方法如下:
项目导入之后配置一下微信SDK的环境只需要一句话就可以了,但是前提是你电脑能够联网下载微信SDK:
把这一句话加上就行了:'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
接下来就可以开始写代码了,首先是Java端的代码,代码比较简单,我也不是很了解Java所以我就不逐行解释了,基本上直接复制就可以使用了。
首先打开这个文件:
下面是java端的代码:
package org.cocos2dx.cpp; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import com.qt.NiuBuTing.R; import com.qt.NiuBuTing.wxapi.WXEntryActivity; import com.tencent.mm.opensdk.modelmsg.SendAuth; import com.tencent.mm.opensdk.modelmsg.SendMessageToWX; import com.tencent.mm.opensdk.modelmsg.WXMediaMessage; import com.tencent.mm.opensdk.modelmsg.WXWebpageObject; import com.tencent.mm.opensdk.openapi.IWXAPI; import com.tencent.mm.opensdk.openapi.WXAPIFactory; import org.cocos2dx.lib.Cocos2dxActivity; import java.io.ByteArrayOutputStream; public class AppActivity extends Cocos2dxActivity { public static final String TAG = "NiuBuTing_Weixin_SDK"; public static final String APP_ID = "这里填写你的Appid"; public static IWXAPI api; private static AppActivity instance = null; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); instance = this; // 注册到微信 regToWx(); } //注册到微信 private void regToWx() { //工厂模式创建微信api api = WXAPIFactory.createWXAPI(this, APP_ID, false); //注册程序 api.registerApp(APP_ID); } //启动微信 private static boolean LaunchWX() { boolean ret = false; if (!api.isWXAppInstalled()) {//判断是否安装微信 Toast.makeText(instance, "没有安装微信,请先安装微信!", Toast.LENGTH_LONG).show(); return ret; } if (api.openWXApp()) {//判断打开微信是否成功 Log.d(TAG, "微信打开成功!"); ret = true; } else { Log.d(TAG, "微信打开失败!"); ret = false; } return ret; } //将图片解析成一个二进制数组 private byte[] bmpToByteArrar(final Bitmap bitmap, final boolean isRecycle){ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); if (isRecycle) { bitmap.recycle(); } byte[] result = outputStream.toByteArray(); try { outputStream.close(); } catch (Exception e) { e.printStackTrace(); } return result; } //微信登录 public static void WXLogin(){ Log.d(TAG, "login-------------"); WXEntryActivity.ReqState = 0; final SendAuth.Req req = new SendAuth.Req(); req.scope = "snsapi_userinfo"; //这里不能改 req.state = "QTNiuBuTing"; //这里改成你自己的数据 api.sendReq(req); } //分享到聊天窗口 public static void WXShareMsgToFriends(final String userNickName, final String roomNum, final String inningsNum, final String peopleNum, final int playType){ //这里的参数是看你自己你需要的话就行,但是在cocos里面调用这个方法的你也传递数值过来 String strPlayType = "轮庄牛牛"; if (playType == 1) //2为轮庄 { strPlayType = "抢庄牛牛"; } WXEntryActivity.ReqState = 1; //封装一个链接,点击跳转到指定网址 WXWebpageObject webpag = new WXWebpageObject(); webpag.webpageUrl = "http://www.0791youxi.com/"; //封装游戏图标 Bitmap bitmap = BitmapFactory.decodeResource(instance.getResources(), R.mipmap.icon); Bitmap thumb = Bitmap.createScaledBitmap(bitmap, 108, 108, true); bitmap.recycle(); //封装分享内容 WXMediaMessage msg = new WXMediaMessage(webpag); msg.thumbData = instance.bmpToByteArrar(thumb, true); msg.title = "我是 " + userNickName; //这个是标题 msg.description = "[" + strPlayType + "]" //这个是描述 + " 房间号:" + roomNum + "。" + " 局数:" + inningsNum + "。" + " 人数:" + peopleNum + "人。" + "约么? 我在QT牛不停创建了房间,一起来玩一玩吧!"; //封装请求 SendMessageToWX.Req req = new SendMessageToWX.Req(); req.transaction = buildTransaction("webpag"); req.message = msg; req.scene = SendMessageToWX.Req.WXSceneSession; //发送请求 api.sendReq(req); } //生成一个微信唯一请求标识符 private static String buildTransaction(final String type) { return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis(); } }
微信登录请求和分享请求发送后还需要创建一个类提供给微信SDK回调,现在你需要新建一个包,包名必须为wxapi,而且这个包必须要在cocos包名的目录下,比如你包名是com.csn.cocosNew 那么新建的这包就是com.csn.cocosNew.wxapi,然后在这个包下面新建一个WXEntryActivity类,类名也是必须这样,没办法微信的要求,下面是创建的方法:
首先是创建包:
包名输你自己的别输我演示的这个,然后点击OK
接下来是创建类:
类创建的时候在你刚才新建的包名目录下右键单击就可以了
记得类名必须是WXEntryActivity!!! 其他的默认就行了
全部创建好之后文件结构是这样的:
然后双击打开,开始写回调:
下面是WXEntryActivity类里面的完整代码:
package 你的项目包名.wxapi; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import com.tencent.mm.opensdk.modelbase.BaseReq; import com.tencent.mm.opensdk.modelbase.BaseResp; import com.tencent.mm.opensdk.modelmsg.SendAuth; import com.tencent.mm.opensdk.openapi.IWXAPI; import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler; import org.cocos2dx.cpp.AppActivity; import org.cocos2dx.cpp.tools.JniHelper; /** * Created by Administrator on 2017/6/5. */ public class WXEntryActivity extends Activity implements IWXAPIEventHandler { private final String TAG = "NiuBuTing_Weixin_SDK"; public static int ReqState = -1; //0为登录, 1为分享 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AppActivity.api.handleIntent(this.getIntent(), this); //如果没回调onResp,八成是这句没有写 } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); AppActivity.api.handleIntent(intent, this); } // 微信发送请求到第三方应用时,会回调到该方法 @Override public void onReq(BaseReq req) { finish(); } @Override public void onResp(BaseResp resp) { Log.d(TAG, "onResp:"); switch (resp.errCode) { case BaseResp.ErrCode.ERR_OK: Log.d(TAG, "请求成功"); if (ReqState == 0) //这个是自己加用于判断是登录还是分享,你们可以去掉判断只要里面的代码就行了 { SendAuth.Resp sendResp = (SendAuth.Resp) resp; JniHelper.onResp(sendResp.code); //这个登录了之后用于回调cocos端函数的映射代码 Log.d(TAG, sendResp.code); } break; case BaseResp.ErrCode.ERR_USER_CANCEL: //发送取消 Toast.makeText(this, "请求取消", Toast.LENGTH_LONG).show(); break; case BaseResp.ErrCode.ERR_AUTH_DENIED: //发送被拒绝 Toast.makeText(this, "请求被拒绝", Toast.LENGTH_LONG).show(); break; default: //发送返回 Toast.makeText(this, "请求返回", Toast.LENGTH_LONG).show(); break; } ReqState = -1; finish(); } }
这里是JniHelper这个类里面的代码。这里面你们要自己创建一个,创建在那个包下面都无所谓:
我是创建在这儿:
下面是代码
package org.cocos2dx.cpp.tools; /** * Created by Administrator on 2017/6/5. */ public class JniHelper { public static native void onResp(String code); }
做完这些之后还需要添加相应的权限,在AndroidMainfest.xml文件里面添加,下面附上我的文件,你们根据要求自己更改:
以上步骤完成了之后就可以还可以在cocos里面使用了。
下面开始说cocos里面的使用,我的使用方法是新建一个类专门用访问微信的是一个单例:
下面附上完整代码,首先是.h文件
#ifndef __WXAPIMANAGER_H__ #define __WXAPIMANAGER_H__ #include "cocos2d.h" #include "network/HttpClient.h" USING_NS_CC; using namespace network; typedef std::functionLastCallBack; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判断是不是安卓环境 #include "platform/android/jni/JniHelper.h" #endif typedef enum { REQ_ERROR = 0, REQ_SUCCESS, CMD_ACCESS_TOKEN, CMD_USER_INFO, DEFAULT }reqTag; class WXAPIManager : Ref { public: static WXAPIManager *getInstance(); //分享到好友 void sendToFriend(const char *userNickName, const char *roomNum, const char *inningsNum, const char *peopleNum, const int playType); //微信登录 void loginWX(); public: static WXAPIManager *_instance; //http请求 void WX_RequestHttp(const char *url, const std::string &data); //请求的回调 void onResponse(HttpClient *client, HttpResponse *response); //最终回调 void onTheEndResponse(std::string &data); private: WXAPIManager(); ~WXAPIManager(); reqTag lastTag; }; #endif // __WXAPIMANAGER_H__
接下来是.cpp的代码:
#include "WXAPIManager.h" WXAPIManager *WXAPIManager::_instance = nullptr; WXAPIManager::WXAPIManager() :lastTag(reqTag::CMD_ACCESS_TOKEN) { } WXAPIManager::~WXAPIManager() { } WXAPIManager *WXAPIManager::getInstance() { if (_instance == nullptr) { _instance = new(std::nothrow) WXAPIManager(); _instance->autorelease(); _instance->retain(); } return _instance; } //分享给好友 void WXAPIManager::sendToFriend(const char *userNickName, const char *roomNum, const char *inningsNum, const char *peopleNum, const int playType) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判断是不是Android环境 JniMethodInfo minfo; //调用java端的静态函数 bool isHave = JniHelper::getStaticMethodInfo(minfo, "org/cocos2dx/cpp/AppActivity", //这个是固定的 "WXShareMsgToFriends", //这个是你要调用的java端的函数名 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V"); //后面跟的是java那边需要接收的参数 if (!isHave) { log("jni:WXShareImgToFriends is null"); } else { //这里需要把参数转换为java格式 jstring jUserNickName = minfo.env->NewStringUTF(userNickName); jstring jRoomNum = minfo.env->NewStringUTF(roomNum); jstring jInnings = minfo.env->NewStringUTF(inningsNum); jstring jpeopleNum = minfo.env->NewStringUTF(peopleNum); jint jPlayType = playType; minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, jUserNickName, jRoomNum, jInnings, jpeopleNum, jPlayType); //开始调用函数 //删除参数 minfo.env->DeleteLocalRef(jUserNickName); minfo.env->DeleteLocalRef(jRoomNum); minfo.env->DeleteLocalRef(jInnings); minfo.env->DeleteLocalRef(jpeopleNum); } #endif } //微信登录 void WXAPIManager::loginWX() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo minfo; bool isHave = JniHelper::getStaticMethodInfo(minfo, "org/cocos2dx/cpp/AppActivity", "WXLogin", "()V"); //没有参数 if (!isHave) { log("jni:WXLogin is null"); } else { minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID); } #endif } //http请求 void WXAPIManager::WX_RequestHttp(const char *url, const std::string &data) { log("WXAPIManager----------------WX_RequestHttp:"); HttpRequest* request = new HttpRequest(); //设置请求类型 request->setRequestType(HttpRequest::Type::GET); request->setUrl(url); //设置回调函数 request->setResponseCallback(CC_CALLBACK_2(WXAPIManager::onResponse, this)); request->setRequestData(data.c_str(), data.size()); HttpClient* httpClient = HttpClient::getInstance(); void onResponse(HttpClient *client, HttpResponse *response); //设置超时时间 httpClient->setTimeoutForConnect(10); httpClient->setTimeoutForRead(10); httpClient->send(request); request->release(); } //请求回调 void WXAPIManager::onResponse(HttpClient *client, HttpResponse *response) { log("WXAPIManager----------------onResponse:"); if (!response) { CCLOG("Log:response =null,plase check it."); return; } //请求失败 if (!response->isSucceed()) { CCLOG("ERROR BUFFER:%s", response->getErrorBuffer()); return; } int codeIndex = response->getResponseCode(); const char* tag = response->getHttpRequest()->getTag(); //请求成功 std::vector* buffer = response->getResponseData(); std::string temp(buffer->begin(), buffer->end()); log("temp OpenID = %s", temp.c_str()); if (lastTag == reqTag::CMD_ACCESS_TOKEN) { //拿到access_token之后还需要继续请求,最终才能拿到用户信息,这点官网上有解释 LastCallBack callback = CC_CALLBACK_1(WXAPIManager::onTheEndResponse, this); callback(temp); } else if(lastTag == reqTag::CMD_USER_INFO) { //这里代表拿到用户信息,你就可以开始做你自己的处理了 } } //最终回调 void WXAPIManager::onTheEndResponse(std::string &data) { log("data = %s", data.c_str()); if (data == "") { return; } const char *WX_USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token="; const char *WX_USER_OPEN_ID = "&openid="; char url[512]; strcpy(url, WX_USER_INFO_URL); strcat(url, access_token); //上一步拿到的access_token strcat(url, WX_USER_OPEN_ID); strcat(url, openid); //上一步拿到的openid CCLOG("%s", url); lastTag = reqTag::CMD_USER_INFO; //继续请求用户信息 WXAPIManager::WX_RequestHttp(url, ""); } #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //必须是C语言的函数,因为C++的函数会有不同的符号生成规则 //1.Java_:是格式,必须加的 //2.org_cocos2dx_cpp_tools_JniHelper:是包名+类名 //3.onResp:是Andriod工程中声明的名字 //4.中间需要_分开 extern "C" { //给android调用的native代码,微信回调后会调用这个函数 //这个代码是给安卓调用,那边传了一个code过来直接转换之后使用就行了 /* 微信的登录的流程: 1、拉起微信登录界面,用户确认之后就回调java端的回调。 2、Java端的回调执行之后根据代码在调用这个函数。 3、接下来的步骤有cocos基础的基本都知道怎么执行了 所以在cocos端首先执行的就是这里的代码。 */ JNIEXPORT void Java_org_cocos2dx_cpp_tools_JniHelper_onResp(JNIEnv *env, jobject thiz, jstring code) { const char *szCode = env->GetStringUTFChars(code, NULL); const char *WX_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="; const char *WX_APP_ID = "这里是你的APPID"; const char *WX_SECRET = "&secret=官网查询你的AppSecret"; //没有获取过的就点旁边的生成就可以了 const char *WX_CODE = "&code="; const char *WX_GRANT_TYPE = "&grant_type=authorization_code"; char url[512]; strcpy(url, WX_ACCESS_TOKEN_URL); strcat(url, WX_APP_ID); strcat(url, WX_SECRET); strcat(url, WX_CODE); strcat(url, szCode); strcat(url, WX_GRANT_TYPE); CCLOG("JniHelper_onResp url = %s", url); CCLOG("szCode = %s", szCode); WXAPIManager *_twm = WXAPIManager::getInstance(); _twm->WX_RequestHttp(url, ""); env->ReleaseStringUTFChars(code, szCode); } } #endif
代码完成之后,自己修改好就可以开始调试了。不要被我的代码影响,只是给你一个参考和告诉你执行流程而已。cocos端的知道流程之后更多的就看你自己的基础了。
还有两点有的人可能看了别人教程之后才看到我的,用的也是别人的代码,有部分代码是有BUG的,比如你发现分享之后选择回到自己的游戏的时候,回不去被卡在那儿了。这种情况主要是你在 ”分享“的这个函数的最后加入一个finish();函数。遇到这个问题的可以把这个函数删了再试试。