LayaBox安卓APP接入微信登录

LayaBox接入微信登录的方式网上几乎没有,在官方文档和上古教程的双重折磨下摸索了一天,终于实现近乎完美的接入方式,并作以记录。

我们用Android Studo打开打包后的项目文件。

基础框架配置

首先需要升级gradle tool和Android Gradle的版本,在用Android Studio打开工程时会提示更新,确认即可。

手动更新是在项目的build.gradle中更改依赖为新版,这里用的是4.1.2版本。

1
2
3
dependencies {
classpath 'com.android.tools.build:gradle:4.1.2'
}

同时在gradle-wrapper.properties中更新gradle,这里用的是6.5版本

1
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip

打开模块的build.gradle文件。位于Gradle Script 下。

  1. 在依赖项中添加微信的SDK。同时升级 appcompat到比较新的版本(打包后默认的版本很低)。

    1
    2
    3
    4
    5
    6
    dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:28.0.0'
    api 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
    }
  2. 更改默认配置中最低sdk版本为16或以上 ,默认为15,最新的微信SDK并不支持。

    1
    2
    3
    4
    5
    6
    7
    defaultConfig {
    applicationId "com.c1oudust.test"
    minSdkVersion 16
    targetSdkVersion 28
    versionCode 1
    versionName "2.0"
    }
  3. 同步gradle更改,完成配置。

SDK配置

java目录下新建以包名命名的package。

在此package中新建名为wxapi的package。

在此package中新建名为WXEntryActivity的class并继承AppCompatActivity类和IWXAPIEventHandler接口。

IWXAPIEventHandler接口需要实现onReqonResp两个方法。这里可以用自动补全一键生成。我们在onResp方法中处理登录回调。这里可以参考微信SDK官方文档

重写onCreate方法,注册微信appid。

在授权成功的回调中使用LayaBox提供的ConchJNI.RunJS调用JavaScript方法。此方法必须注册到window对象上,否则找不到,后文有详细方式。这里直接把获取到的登录code传给了Laya端。

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.c1oudust.test.wxapi;

import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

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 com.tencent.mm.opensdk.openapi.WXAPIFactory;

import layaair.game.browser.ConchJNI;

public class WXEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {
private IWXAPI iwxapi;
private static final String APP_ID = "wx123456123456123";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
iwxapi = WXAPIFactory.createWXAPI(this, APP_ID, false);
iwxapi.handleIntent(getIntent(), this);
}

@Override
public void onReq(BaseReq baseReq) {}

//登录回调
@Override
public void onResp(BaseResp baseResp) {
switch (baseResp.errCode) {
case BaseResp.ErrCode.ERR_OK: // 用户授权成功
String code = ((SendAuth.Resp) baseResp).code;
ConchJNI.RunJS("wxLoginCallback('" +code+"')");
finish(); // finish 是用来关闭当前activity的
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED://用户拒绝授权
finish();
break;
case BaseResp.ErrCode.ERR_USER_CANCEL://用户取消
finish();
break;
default:
finish();
break;
}
}
}

打开AndroidManifest.xml,我们需要在MainActivity中添加以下代码,taskAffinity为包名。

1
2
3
android:exported="true"
android:taskAffinity="com.c1oudust.test"
android:launchMode="singleTask"

同时添加一个activity,注意name须为WXEntryActivity的路径。

1
2
3
<activity android:name="com.c1oudust.test.wxapi.WXEntryActivity"
android:label="@string/app_name"
android:exported="true"/>

为了使安卓11的手机能调起微信,需要在根节点下添加以下代码,这部分在SDK文档的接入流程中。

1
2
3
<queries>
<package android:name="com.tencent.mm" />
</queries>

安卓端的配置基本完成。现在创建一个单独的静态方法,实现登录,供Laya端调用。

这里我们在java目录新建wx包,并新建wxLogin类。

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package wx;

import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.openapi.IWXAPI;

public class wxLogin {
public static IWXAPI api;
public static void login() {
if (!api.isWXAppInstalled()) {
// 未安装微信客户端
return;
}
final SendAuth.Req req =new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "wechat_sdk_demo_test";
api.sendReq(req);
}
}

其中的IWXAPI必须是之前注册过的,因此我们在MainActivity处理这部分。

打开demo包中的MainActivity文件,可以理解为APP的主入口。

onCreate方法中注册appid并将IWXAPI赋值给wxLogin中的IWXAPI

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static final String APP_ID = "wx123456123456123";
private IWXAPI api;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
JSBridge.mMainActivity = this;
mSplashDialog = new SplashDialog(this);
mSplashDialog.showSplash();
/*
* 如果不想使用更新流程,可以屏蔽checkApkUpdate函数,直接打开initEngine函数
*/
// checkApkUpdate(this);
regToWx();
initEngine();
}
private void regToWx() {
api = WXAPIFactory.createWXAPI(this, APP_ID, false);
api.registerApp(APP_ID);
wxLogin.api = api; // 赋值
}

Laya端处理

  1. 在想要调起微信登录的方法中添加

    1
    2
    3
    4
    if (window['PlatformClass']) {
    var wxLogin = window['PlatformClass'].createClass('wx.wxLogin');
    wxLogin.call('login');
    }

    这里的createClass参数即为之前创建的调起登录的java类。然后我们使用call来调起wxLogin类中的login方法。

  2. 登录回调。在APP主页面的构造器中为window对象添加一个方法,方法名需要和onResp回调中ConchJNI.RunJS执行的方法名一样。

    1
    2
    3
    Laya.Browser.window['wxLoginCallback'] = (code) => {
    console.log('返回的code: ' + code);
    };

    这里会拿到登录回调传过来的code

登录处理

以上操作初步完成了调起微信登录的流程。那么怎么获取到用户的个人信息呢?

这里在微信SDK文档中已经说的很清楚了,大概方式是通过登录返回的code获取access_token,再通过access_token来获取用户个人信息。

access_token涉及到有效期,有效期过了就需要重新获取。

由于获取access_token涉及到注册微信开放平台的app secret,因此建议把这部分放在后端。

在这里由于是demo,因此本人给出一个大概的流程,请求我们用Okhttp框架。

我们在登录成功的回调中不要把code传给前端,而是调用getAccessToken方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private void getAccessToken(String code) {
StringBuffer loginUrl = new StringBuffer();
loginUrl.append("https://api.weixin.qq.com/sns/oauth2/access_token")
.append("?appid=")
.append(APP_ID)
.append("&secret=")
.append(SECRET)
.append("&code=")
.append(code)
.append("&grant_type=authorization_code");

OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
.url(loginUrl.toString())
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}

@Override
public void onResponse(Call call, Response response) throws IOException {
String responseInfo= response.body().string();
String access = null;
String openId = null;
try {
JSONObject jsonObject = new JSONObject(responseInfo);
access = jsonObject.getString("access_token");
openid = jsonObject.getString("openid");
} catch (JSONException e) {
e.printStackTrace();
}
getUserInfo(token, openid);
}
});
}

我们把access_tokenopenid传给getUserInfo方法来获取个人信息。这里没有对access_token失效的处理,各位可以自行发挥。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void getUserInfo(String token, String openid) {
String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + token + "&openid=" + openid;

OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
.url(getUserInfoUrl)
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}

@Override
public void onResponse(Call call, Response response) throws IOException {
String responseInfo= response.body().string();
// 我们在这里调用Laya端方法传递用户信息responseInfo即可
finish();
}
});
}

参考文档

微信开放文档

Laya官方文档 - 二次开发

Laya打包AndroidStudio工程二次开发之相互调用