【分享】cocoscreator 集成微信 native sdk 登录和分享

最近在研究cocoscreator创建的游戏接入微信登录和分享功能。开始想用anysdk,但是anysdk用起来比较繁琐,所以就采用手动接入微信sdk的方法来接入。基本思想是用js来调用android函数的方式。cocoscreator工程打包成android工程。注意一定要修改包名为你在微信平台注册的包名com.xxx.xxx,打包成release版本。然后打开build目录下的安卓屎丢丢工程,可看到org.cocos2dx.javascript的目录下面有AppActivity和SDKWrapper俩个文件,AppActivity就是游戏对应到android的主活动。要使用微信登录,先去微信开放平台注册获取Appid和appSecret这些请自行百度。本文只写重要步骤。

1 导入微信sdk libammsdk.jar和open_sdk_r5509_lite.jar

2 新建一个pakage,名字是你的包名com.xxx.xxx.wxapi,然后在里面新建WxEntryActivity这个类,内容如下:

public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
    //private IWXAPI wxApi;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_wxentry);
        //wxApi = WXAPIFactory.createWXAPI(this, Define.WX_APPID, false);
        //如果分享的时候,该界面没有开启,那么微信开始这个activity时,会调用onCreate,所以这里要处理微信的返回结果
        //wxApi.handleIntent(getIntent(), this);
        AppActivity.wxApi.handleIntent(this.getIntent(), this);

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        //如果分享的时候,该已经开启,那么微信开始这个activity时,会调用onNewIntent,所以这里要处理微信的返回结果
        setIntent(intent);
        //wxApi.handleIntent(intent, this);
        AppActivity.wxApi.handleIntent(intent, this);
//		finish();
    }

    // 微信发送请求到第三方应用时,会回调到该方法
    @Override
    public void onReq(BaseReq baseReq) {

    }

    // 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
    @Override
    public void onResp(BaseResp baseResp) {
        //关于数值的类型,微信官方文档里有写:发送OpenAPI Auth验证的数值为:1;分享消息到微信的数值为2
        if (baseResp.getType() == 2) {
            //转态码和授权的一样
            String result = "";
            switch (baseResp.errCode) {
                //同意授权
                case BaseResp.ErrCode.ERR_OK:
                    result = "分享成功";
                    break;
                case BaseResp.ErrCode.ERR_USER_CANCEL:
                    result = "分享取消";
                    break;
                case BaseResp.ErrCode.ERR_AUTH_DENIED:
                    result = "分享被拒绝";
                    break;
                default:
                    result = "分享返回";
                    break;
            }
//			Toast.makeText(this, result, Toast.LENGTH_LONG).show();
            finish();
        }
        if (baseResp.getType() == 1) {
            switch (baseResp.errCode) {
                //同意授权
                case BaseResp.ErrCode.ERR_OK:
                    SendAuth.Resp resp = (SendAuth.Resp) baseResp;
                    Define.resp = resp;//微信登录成功,保存resp到全局变量里面
                    break;
                case BaseResp.ErrCode.ERR_USER_CANCEL:
                case BaseResp.ErrCode.ERR_AUTH_DENIED:
                default:
                    //MTACountUtil.registerUser(this, "weixin", "fail");
                    break;
            }
            finish();
        }
    }
}

3、AppActivity里面定义静态全局变量wxApi以及初始化函数regToWx(),将regToWx()写入页面的onCreate函数中去

public static IWXAPI wxApi;
public void regToWx() {
        //IWXAPI 是第三方app和微信通信的openapi接口
        wxApi = WXAPIFactory.createWXAPI(this, Define.WX_APPID, false);
        //将应用注册到微信
        wxApi.registerApp(Define.WX_APPID);
    }

4、登录函数,当这个函数被调用时会弹出微信的登录页面。

public static void loginByWeiXin(int val) {
        //mProgressDialog.show();
        // send oauth request
        SendAuth.Req req = new SendAuth.Req();
        req.scope = "snsapi_userinfo";
        req.state = "wechat_sdk_aifuns";
        wxApi.sendReq(req);
    }

5、微信登录成功后会调用WxEntryActivity页面,已经在这里获取到了resp,resp.code可以用来获取微信的access_token。获取access_token的函数:

private void getWeiXinAccessToken(String code) {
        //ToastUtil.showShortToast(this,"getWeiXinAccessToken,code:"+code);
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + "appid=" + Define.WX_APPID + "&secret=" + Define.WX_APPSECRET + "&code=" + code + "&grant_type=authorization_code";
        OkHttpHelper.getinstance().post(this, url, null, new OkHttpBaseCallBack() {
            @Override
            public void onRequestBefore() {

            }

            @Override
            public void onFailure(Request request, Exception e) {
                Toast.makeText(instance, "请求微信token失败",Toast.LENGTH_LONG).show();
            }

            @Override
            public void onSuccess(Response response, Object o) {
                try {
                    JSONObject jsonObject = new JSONObject((String) o);
                    String token = jsonObject.optString("access_token");
                    String openId = jsonObject.optString("openid");
                    getWeiXinInfo(token,openId);
                } catch (Exception e) {

                }
            }

            @Override
            public void onError(Response response, int errorCode, Exception e) {

            }
        });
    }

将getWeiXinAccessToken写入到onResume里面:

if(Define.resp != null)
        {
            String code = Define.resp.code;
            getWeiXinAccessToken(code);
        }

6、上面函数中有个函数getWeiXinInfo是用来获取微信名称、头像之类的。

void  getWeiXinInfo(String token,String id)
    {
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token="+token+"&openid="+id;
        OkHttpHelper.getinstance().post(this, url, null, new OkHttpBaseCallBack() {
            @Override
            public void onRequestBefore() {

            }

            @Override
            public void onFailure(Request request, Exception e) {

            }

            @Override
            public void onSuccess(Response response, Object o) {
                try{
                    JSONObject jsonObject = new JSONObject((String) o);
                    wxFlag = true;
                    openId = jsonObject.optString("openid");
                    nickname = jsonObject.optString("nickname");
                    avatar = jsonObject.optString("headimgurl");
                    sex = jsonObject.optInt("sex");//0:未知 1:男 2:女
                    //mProgressDialog.dismiss();
                }catch (Exception e)
                {

                }

            }

            @Override
            public void onError(Response response, int errorCode, Exception e) {

            }
        });
    }

7、将获取到的值封装成函数以备cocoscreator中调用

public static boolean getWxFlag(int x)
    {
        return wxFlag;
    }
    public static void setWxFlag(boolean val){wxFlag=val;}
    public static String getOpenId(int x){return openId;}
    public static String getNickname(int x){return nickname;}
    public static String getAvatar(int x){return avatar;}
    public static int getSex(int x){return sex;}

8、游戏端登录函数

login :function() {
        cc.log("login...");
        this.loginFlag = true;
        jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "loginByWeiXin","(I)V",0);
       //Global.sendWxLoginMsg("hello")
    },

9、login调用后,就会调用java端一系列函数,直到最终获取到微信id,名称,头像,性别等信息。得到这些信息后,怎么通知js端呢?由于坑爹的cocoscreator在java调用js端还不成熟,所以不采用java调用js的方法,而是在js端采用查询的方式来查看登录是否成功。js的update函数中写入查询代码:

update:function(dt)
    {
        if(this.loginFlag)
        {
            var wxFlag = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "getWxFlag","(I)Z",0);
            if(wxFlag)
            {
                this.loginFlag = false;
                this.openId = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "getOpenId","(I)Ljava/lang/String;",0);
                this.nickname = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "getNickname","(I)Ljava/lang/String;",0);
                this.avatar = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "getAvatar","(I)Ljava/lang/String;",0);
                this.sex = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "getSex","(I)I",0);
                jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "setWxFlag","(Z)V",false);
                this.labName.string = this.nickname;
                if(this.sex == 1)
                    this.labSex.String = "男";
                else if(this.sex == 2)
                    this.labSex.String = "女";
                this.labId.string = this.openId;
                this.getUserPic(this.avatar);
            }
        }
    },

至此微信登录已经完毕。

10、微信分享比微信登录简单蛮多。在java里面写函数

public static void shareWX(boolean isShareFriend)
    {
        Bitmap bitmap = BitmapFactory.decodeResource(instance.getResources(), R.mipmap.ic_launcher);
        Bitmap thumbBmp = Bitmap.createScaledBitmap(bitmap, 150, 150, true); //缩略图大小
        WXWebpageObject webpage = new WXWebpageObject();
        webpage.webpageUrl = "http://baidu.com";
        WXMediaMessage msg = new WXMediaMessage(webpage);
        msg.title = "share wx";
        msg.description = "this is my share wx";
        msg.thumbData = bmpToByteArray(thumbBmp, true); // 设置缩略图

        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.transaction = String.valueOf(System.currentTimeMillis());
        req.message = msg;
        req.scene = isShareFriend ? SendMessageToWX.Req.WXSceneSession : SendMessageToWX.Req.WXSceneTimeline;
        wxApi.sendReq(req);
    }

    private static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG, 100, output);
        if (needRecycle) {
            bmp.recycle();
        }

        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

js端调用share函数来实现分享。

share:function()
    {
        jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "shareWX","(Z)V",true);
    }
12赞

赞一个

感谢,正需要

赞赞赞

赞,不过OkHttpHelper又是个什么?

是自己封装的一个安卓下进行Http下载的类

顶。字数补丁

在分享的代码那报错了,instance.getResources(), R.mipmap.ic_launcher, 怎么破?

我也是卡在这个上,好像少了Util和R文件。但不知道怎么解决

12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: java.lang.NullPointerException: Attempt to invoke interface method ‘int com.tencent.mm.opensdk.modelmsg.WXMediaMessage$IMediaObject.type()’ on a null object reference
12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: at com.tencent.mm.opensdk.modelmsg.SendMessageToWX$Req.checkArgs(Unknown Source)
12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: at com.tencent.mm.opensdk.openapi.WXApiImplV10.sendReq(Unknown Source)
12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: at org.cocos2dx.javascript.AppActivity.shareWeiXin(AppActivity.java:130)
12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: at org.cocos2dx.lib.Cocos2dxRenderer.nativeTouchesEnd(Native Method)
12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: at org.cocos2dx.lib.Cocos2dxRenderer.handleActionUp(Cocos2dxRenderer.java:128)
12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: at org.cocos2dx.lib.Cocos2dxGLSurfaceView$9.run(Cocos2dxGLSurfaceView.java:283)
12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1507)
12-21 17:43:16.963 27921-27941/com.bzw315.game.app W/System.err: at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1267)
12-21 17:43:16.963 27921-27941/com.bzw315.game.app E/JavaScriptJavaBridge: [ERROR] (D:/cocos_build/jsb-default/frameworks/cocos2d-x/cocos/scripting/js-bindings/proj.android/…/manual/JavaScriptJavaBridge.cpp, 554): js_cocos2dx_JSJavaBridge : call result code: -4
12-21 17:43:16.963 27921-27941/com.bzw315.game.app E/JavaScriptJavaBridge: [ERROR] Failed to invoke JavaScriptJavaBridge_callStaticMethod, location: D:/cocos_build/jsb-default/frameworks/cocos2d-x/cocos/scripting/js-bindings/proj.android/…/manual/JavaScriptJavaBridge.cpp:567

安卓应用分享没反应,以上是查看到的log信息,有遇到的ccc友吗?

有空指针异常,可以debug下看看

如果客户端代码有改动的话,android项目需不需要重新构建一次

感谢分享 为我解决碰到的问题提供了思路

mark

mark

mark

大佬您好,我能够拉取授权界面,但是同意后,WXEntryActivity 各个方法都没有执行,包括onCreate()方法都没有执行,不知道有什么需要注意的么

需要注意看看你的WXEntryActivity有没有在AndroidManifest.xml里面注册过哦

先 mark 一下,确实不错