Cocos 2dx3.15 Access to Wechat SDK to Realize Logon and Share Android studio 2.3.3

Keywords: Android Attribute Java Qt

To start with, I have to talk about online tutorials and the official website of WeChat open platform. Online tutorials are mostly too old, though they can be used but incomplete. Some things have been changed. The reference function is almost no, the only function is to see what the return value and some parameters are useful. Yes, that's right. Nothing to say.

Start the course now:

Step one:

Get ready for your APP_ID, which doesn't explain. If you don't know, please go to the Open Wechat Platform (https://open.weixin.qq.com/) to check the registration of your application. Then the login function is charged, and sharing is free.
 Here are the steps to register the application:
     Open the official website of Wechat Open Platform:

Click to create the application, type it in as prompted, and then click Next. :

After filling in, submit the audit. In general, the audit may take 1-3 days.

Take Android as an example, the signature and package name must be the same as the package name and signature of the cocos project you want to access. For signature acquisition, see the following figure:

Open the Android resource download and slide to the right to find:

Download and install it on your mobile phone. I use the simulator here. Then pack up the cocos project you want to access and open the signature generation tool installed before:

After opening the tool, enter your package name:

This is the acquisition of signatures.

Start the next step after the application registration is approved

The second step:
Import your cocos project into android studio 2.3.3. Other environments refer to the corresponding tutorials to import the project, but it is recommended to use android studio for convenience. The import method is as follows:


After the project is imported, it only takes one sentence to configure the environment of Wechat SDK, but only if your computer can download Wechat SDK online:

Add this sentence:'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'

Then you can start to write code, first of all, the Java side of the code, the code is relatively simple, I do not know Java, so I do not explain line by line, basically directly copy can be used.

First open the file:

The following is the code on the java side:

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 = "Fill in your form here. Appid";
    public static IWXAPI api;
    private static AppActivity instance = null;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        instance = this;
        // Register to Wechat
        regToWx();
    }

    //Register to Wechat
    private void regToWx() {
        //Factory mode to create wechat api
        api = WXAPIFactory.createWXAPI(this, APP_ID, false);

        //Registration procedure
        api.registerApp(APP_ID);
    }

    //Start WeChat
    private static boolean LaunchWX() {
        boolean ret = false;
        if (!api.isWXAppInstalled())
        {//Judging whether to install Wechat
            Toast.makeText(instance, "Wechat is not installed. Please install Wechat first.!", Toast.LENGTH_LONG).show();
            return ret;
        }
        if (api.openWXApp())
        {//Judging whether the opening of Wechat is successful
            Log.d(TAG, "Wechat Open Successfully!");
            ret = true;
        }
        else
        {
            Log.d(TAG, "Wechat failed to open!");
            ret = false;
        }

        return ret;
    }

    //Resolve the picture into a binary array
    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;
    }

    //WeChat login
    public static void WXLogin(){
        Log.d(TAG, "login-------------");
        WXEntryActivity.ReqState = 0;
        final SendAuth.Req req = new SendAuth.Req();
        req.scope = "snsapi_userinfo";  //It can't be changed here.
        req.state = "QTNiuBuTing";  //Change this into your own data.
        api.sendReq(req);
    }

    //Share in the chat window
    public static void WXShareMsgToFriends(final String userNickName,
                                           final String roomNum,
                                           final String inningsNum,
                                           final String peopleNum,
                                           final int playType){
        //The parameters here depend on what you need, but you can also pass the values by calling this method in cocos.

        String strPlayType = "Cattle in wheel Village";

        if (playType == 1)   //2 is the wheel village.
        {
            strPlayType = "Rob Zhuang cattle";
        }

        WXEntryActivity.ReqState = 1;

        //Encapsulate a link and click to jump to the specified address
        WXWebpageObject webpag = new WXWebpageObject();
        webpag.webpageUrl = "http://www.0791youxi.com/";

        //Encapsulating game icons
        Bitmap bitmap = BitmapFactory.decodeResource(instance.getResources(), R.mipmap.icon);
        Bitmap thumb = Bitmap.createScaledBitmap(bitmap, 108, 108, true);
        bitmap.recycle();

        //Encapsulating Shared Content
        WXMediaMessage msg = new WXMediaMessage(webpag);
        msg.thumbData = instance.bmpToByteArrar(thumb, true);
        msg.title = "I am " + userNickName;  //This is the title.
        msg.description = "[" + strPlayType + "]"  //This is a description.
                + " Room number:" + roomNum + ". "
                + " number of games:" + inningsNum + ". "
                + " Number:" + peopleNum + "People."
                + "About? I am here QT The cow keeps creating rooms. Let's play together.";

        //Package request
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.transaction = buildTransaction("webpag");
        req.message = msg;
        req.scene = SendMessageToWX.Req.WXSceneSession;

        //Send request
        api.sendReq(req);
    }

    //Generate a Wechat Unique Request Identifier
    private static String buildTransaction(final String type) {
        return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
    }
}

Now you need to create a new package. The package name must be wxapi, and the package must be in the directory of the cocos package name, such as com.csn.cocosNew.wxapi. The new package is com.csn.cocosNew.wxapi. Then you need to create a new WXEntry Activity class under the package. Names must be the same. There's no way to request Weixin. Here's how to create them.
First, create packages:


Enter your own package name, don't lose the one I demonstrated, and then click OK

Next, create the class:

Right-click under the package name directory you just created when creating the class

Remember that the class name must be WXEntry Activity!!! Other defaults will do.

After all the files are created, the file structure is as follows:

Then double-click open and start writing callbacks:

The following is the complete code in the WXEntryActivity class:

package Your project package name.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 for login and 1 for share

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        AppActivity.api.handleIntent(this.getIntent(), this);
        //If there is no callback to onResp, 80% of this sentence is not written.
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        setIntent(intent);
        AppActivity.api.handleIntent(intent, this);
    }

    // When a wechat sends a request to a third party application, it calls back to this method.
    @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, "Request successful");
                if (ReqState == 0)  //This is added to determine whether to log in or share, you can remove the judgment as long as the code inside it.
                {
                    SendAuth.Resp sendResp = (SendAuth.Resp) resp;
                    JniHelper.onResp(sendResp.code); //This mapping code is used to call back the cocos end function after login
                    Log.d(TAG, sendResp.code);
                }
                break;
            case BaseResp.ErrCode.ERR_USER_CANCEL:
                //Send cancel
                Toast.makeText(this, "Request cancellation", Toast.LENGTH_LONG).show();
                break;
            case BaseResp.ErrCode.ERR_AUTH_DENIED:
                //Send rejected
                Toast.makeText(this, "The request was refused", Toast.LENGTH_LONG).show();
                break;
            default:
                //Send back
                Toast.makeText(this, "Request return", Toast.LENGTH_LONG).show();
                break;
        }
        ReqState = -1;
        finish();
    }
}

Here is the code in the class JniHelper. You have to create one for yourself. It doesn't matter if you create it under that package.
I was founded here:

Here's the code

package org.cocos2dx.cpp.tools;

/**
 * Created by Administrator on 2017/6/5.
 */

public class JniHelper {
    public static native void onResp(String code);
}

After doing this, you need to add the corresponding permissions, add them to the AndroidMainfest.xml file, and attach my file below. You can change it according to your requirements:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.qt.NiuBuTing"
    android:installLocation="auto">

    <uses-feature android:glEsVersion="0x00020000" />
     <!--These are the necessary permissions for Wechat. -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:label="@string/app_name"
        android:allowBackup="true"
        android:icon="@mipmap/icon">

        <!-- Tell Cocos2dxActivity the name of our .so -->
        <meta-data android:name="android.app.lib_name"
                   android:value="MyGame" />

        <activity
            android:name="org.cocos2dx.cpp.AppActivity"
            android:screenOrientation="landscape"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!--Registered Wechat Callback WXEntryActivity -->
        <activity
            android:name=".wxapi.WXEntryActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />

    </application>

</manifest>

After the above steps are completed, they can also be used in cocos.

Let's start with the use of cocos. My way of using cocos is to create a new class dedicated to accessing Wechat, which is a single example.
The complete code is attached below. First, the. h file.

#ifndef __WXAPIMANAGER_H__
#define __WXAPIMANAGER_H__

#include "cocos2d.h"
#include "network/HttpClient.h"

USING_NS_CC;
using namespace network;

typedef std::function<void(std::string &data)> LastCallBack;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)  //Judging if it's an Android environment?
#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();

    //Share with Friends
    void sendToFriend(const char *userNickName, const char *roomNum, const char *inningsNum, const char *peopleNum, const int playType);

    //WeChat login
    void loginWX();

public:
    static WXAPIManager *_instance;

    //http request
    void WX_RequestHttp(const char *url, const std::string &data);

    //Callbacks to requests
    void onResponse(HttpClient *client, HttpResponse *response);

    //Final callback
    void onTheEndResponse(std::string &data);

private:
    WXAPIManager();
    ~WXAPIManager();

    reqTag lastTag;
};
#endif // __WXAPIMANAGER_H__

Next is the code for. 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;
}

//Share it with friends
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) //Judging if it's an Android environment?
    JniMethodInfo minfo;

        //Calling static functions on the java side
        bool isHave = JniHelper::getStaticMethodInfo(minfo, 
            "org/cocos2dx/cpp/AppActivity", //This is fixed.
            "WXShareMsgToFriends",   //This is the name of the function on the java side that you are calling
            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
            //Following is the parameters that need to be received in java

    if (!isHave) {
        log("jni:WXShareImgToFriends is null");
    }
    else {
        //Here you need to convert the parameters to java format
        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);  //Start calling functions

        //Delete parameter
        minfo.env->DeleteLocalRef(jUserNickName);
        minfo.env->DeleteLocalRef(jRoomNum);
        minfo.env->DeleteLocalRef(jInnings);
        minfo.env->DeleteLocalRef(jpeopleNum);
    }
#endif
}

//WeChat login
void WXAPIManager::loginWX()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    JniMethodInfo minfo;

    bool isHave = JniHelper::getStaticMethodInfo(minfo,
        "org/cocos2dx/cpp/AppActivity",
        "WXLogin",
        "()V");  //No parameters

    if (!isHave) {
        log("jni:WXLogin is null");
    }
    else
    {
        minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID);
    }   
#endif
}

//http request
void WXAPIManager::WX_RequestHttp(const char *url, const std::string &data)
{
    log("WXAPIManager----------------WX_RequestHttp:");
    HttpRequest* request = new HttpRequest();
    //Setting Request Type  
    request->setRequestType(HttpRequest::Type::GET);
    request->setUrl(url);
    //Setting callback function  
    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);
    //Setting timeout time
    httpClient->setTimeoutForConnect(10);
    httpClient->setTimeoutForRead(10);
    httpClient->send(request);
    request->release();
}

//Request callback
void WXAPIManager::onResponse(HttpClient *client, HttpResponse *response)
{
    log("WXAPIManager----------------onResponse:");
    if (!response) {
        CCLOG("Log:response =null,plase check it.");
        return;
    }

    //request was aborted  
    if (!response->isSucceed())
    {
        CCLOG("ERROR BUFFER:%s", response->getErrorBuffer());
        return;
    }

    int codeIndex = response->getResponseCode();
    const char* tag = response->getHttpRequest()->getTag();

    //Request successful  
    std::vector<char>* buffer = response->getResponseData();
    std::string temp(buffer->begin(), buffer->end());
    log("temp OpenID = %s", temp.c_str());

    if (lastTag == reqTag::CMD_ACCESS_TOKEN)
    {
        //After getting access_token, you need to continue requesting to get the user information, which is explained on the official website.
        LastCallBack callback = CC_CALLBACK_1(WXAPIManager::onTheEndResponse, this);
        callback(temp);
    }
    else if(lastTag == reqTag::CMD_USER_INFO)
    {
        //Here's where you get the user information, and you can start doing your own processing.
    }
}

//Final callback
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 from the previous step
    strcat(url, WX_USER_OPEN_ID);
    strcat(url, openid);  //openid from the previous step

    CCLOG("%s", url);
    lastTag = reqTag::CMD_USER_INFO;

    //Continue requesting user information
    WXAPIManager::WX_RequestHttp(url, "");
}

#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
//Must be a function of C language, because C++ functions have different rules for symbol generation.  
//1.Java_: Format, must be added  
//2.org_cocos2dx_cpp_tools_JniHelper: is the package name + class name  
//3.onResp: The name declared in the Andriod Project  
//4. Intermediate Need Separation  
extern "C" {

    //native code for android calls, which will be called when Wechat calls back
    //This code is called for Android, where a code is passed over and converted directly to use it.
    /*
        The login process of Wechat:
            1,Pull up the Wechat login interface and call back the java callback after the user confirms.
            2,Java This function is called after the callback of the end is executed according to the code.
            3,The next steps are based on cocos and basically know how to execute them.
            So the first thing to execute on the cocos side is the code here.
    */
    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 = "This is yours. APPID";
        const char *WX_SECRET = "&secret=Query your website AppSecret";  //If you haven't gotten anything, just click on the next achievement.
        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

After the code is completed, you can start debugging by modifying it yourself. Don't be influenced by my code, just give you a reference and tell you the execution process. When the cocos end knows the process, it depends more on your own foundation.

There are two other points that some people may see me only after they have read other people's tutorials. They also use other people's code. Some of the code has BUG. For example, when you choose to return to your game after sharing, you can't get stuck there. In this case, you add a finish(); function at the end of the function of "sharing". If you encounter this problem, you can delete this function and try again.

This is the end of the course. It's hard to play with all hands. If it's helpful, just give a compliment and pay attention to it. If there are any inadequate or incorrect explanations, please leave a message to correct them. If you have any questions, you can leave a message or join my QQ group: 249155914. Discuss together! Thank you.

Posted by brbsta on Wed, 12 Dec 2018 00:21:07 -0800