前提
本文介绍的是如果开发极光认证的 HBuilderX 插件,最终开发出的插件已开源,如果需要使用请点击前往github。
极光认证
极光认证整合了三大运营商的网关认证能力,为开发者提供了一键登录和号码认证功能。前往官网查看全部功能
HBuilderX
目前极光只提供了 Android&iOS 的原生 SDK 接入,如果希望在 HBuilderX 中接入极光认证,需要开发适用的插件以方便在 HX 中直接使用 JS 调用极光认证能力。
HBuilderX 是一款IDE,支持 uni-app 开发框架。所以需要按照 uni-app 开发完插件后打包给 HbuilderX 使用
插件准备工作
极光侧
1.在极光 Portal 测注册应用并开通认证功能,拿到对应的 appkey 等会做测试
2.前往下载最新的极光认证Android和iOS两端原生 SDK,本文示例版本
-
Android v2.5.2
-
iOS v2.5.3
uni-app 侧
创建插件项目,并接入认证 SDK
Android
-
1.参考Android平台uni-app原生插件开发文档 新建一个 module 命名为 uniplugin_jverification,并在 uniapp SDK 插件项目中接入。
-
2.按照接入指南手动集成部分(因为uniapp 官方建议 jar 包优先于 jcenter 集成方式)接入极光 SDK。
-
3.因为 appkey 和 channel 是变量需要配 meta ,为了方便用户使用,这两个 meta 配在 app 的 AndroidManifest 中,并在后续插件配置中预留给用户配置,而不是打进插件包里。
-
-
4 在 module 中新建一个类为 JVerificationWXModule 继承 WXSDKEngine.DestroyableModule,并将其配置成插件入口。
5.Android 插件开发准备完毕
iOS
-
1.参考iOS平台uni-app原生插件开发文档新建一个 framework 命名为 UnipluginJVerification,将其配置为静态库,并在 uniapp SDK 插件项目中接入。
-
2.按照iOS 接入配置手动导入
(因为uniapp 官方建议静态库优先于 pod 集成方式)接入极光 SDK。
-
3.因为 appkey 和 channel 是变量需要在后续插件配置中预留给用户配置,而不是打进插件包里,所以将其配在项目的 infolist 中动态获取。
-
4 在 framework 中新建一个声明 JVerificationModule.h 导入 WXModuleProtocal.h,并将其配置成插件入口。
5.iOS 插件开发准备完毕
插件开发
如何开发和调试 uniapp 插件
Android:https://ask.dcloud.net.cn/article/35416
iOS:https://ask.dcloud.net.cn/article/35415
认证插件开发注意事项
认证 Android 和 iOS 作为同一款产品的两端,虽然他们 API 命名不同,但两端的功能是极其相似的,比如请求一键登录时,均可以设置超时,设置登录完成后是否自动关闭授权页。
// Android
LoginSettings settings = new LoginSettings();
settings.setAutoFinish(true);//设置登录完成后是否自动关闭授权页
settings.setTimeout(15 * 1000);//设置超时时间,单位毫秒。 合法范围(0,30000],范围以外默认设置为10000
settings.setAuthPageEventListener(new AuthPageEventListener() {
@Override
public void onEvent(int cmd, String msg) {
//do something...
}
});//设置授权页事件监听
JVerificationInterface.loginAuth(this, settings, new VerifyListener() {
@Override
public void onResult(int code, String content, String operator) {
if (code == 6000){
Log.d(TAG, "code=" + code + ", token=" + content+" ,operator="+operator);
}else{
Log.d(TAG, "code=" + code + ", message=" + content);
}
}
});
// iOS
[JVERIFICATIONService getAuthorizationWithController:self hide:NO animated:YES timeout:5*1000 completion:^(NSDictionary *result) {
NSLog(@"一键登录 result:%@", result);
} actionBlock:^(NSInteger type, NSString *content) {
NSLog(@"一键登录 actionBlock :%ld %@", (long)type , content);
}];
所以为了方便用户的使用,插件需要尽可能的统一两端的使用方式,比如约定 timeout 和 autoFinish 作为一键认证功能超时,登录完成后是否自动关闭授权页功能的标识,前端下发一套配置,两端各自处理对应配置,并将结果统一返回,这样极大方便了前端使用者。
以一键登录为例定义对外接口:
API - loginAuth(Object,CALLBACK,EVENTCALLBACK)
调起一键登录授权页面,在用户授权后获取 loginToken,同时支持授权页事件监听。
参数说明
- Object
参数名称 | 参数类型 | 参数说明 |
---|---|---|
timeout | number | 设置初始化超时时间,单位毫秒,合法范围是(0,30000],推荐设置为 5000-10000,默认值为 10000。 |
autoFinish | boolean | 是否自动关闭授权页,true - 是,false - 否 |
animationFlag | boolean | 拉起授权页时是否需要动画效果,true - 是,false - 否,默认 true。(仅作用与 iOS) |
根据接口定义我们可以对应开发插件两端代码为
- Android
// Android
@JSMethod(uiThread = true)
public void loginAuth(JSONObject object, final JSCallback callback, final JSCallback eventCallback) {
int timeout = 10000;
boolean autoFinish = true;
if (object != null) {
timeout = object.containsKey(JConstants.TIME_OUT) ? object.getIntValue(JConstants.TIME_OUT) : 10000;
autoFinish = object.containsKey(JConstants.AUTO_FINISH) ? object.getBooleanValue(JConstants.AUTO_FINISH) : true;
}
JLogger.d("loginAuth with setting autoFinish:" + autoFinish + " timeout:" + timeout);
LoginSettings settings = new LoginSettings();
settings.setAutoFinish(autoFinish);//设置登录完成后是否自动关闭授权页
settings.setTimeout(timeout);//设置超时时间,单位毫秒。 合法范围(0,30000],范围以外默认设置为10000
settings.setAuthPageEventListener(new AuthPageEventListener() {
@Override
public void onEvent(int cmd, String msg) {
eventCallback.invokeAndKeepAlive(convertToResult(cmd, msg));
}
});//设置授权页事件监听
JVerificationInterface.loginAuth(mWXSDKInstance.getContext(), settings, new VerifyListener() {
@Override
public void onResult(int code, String content, String operator) {
callback.invoke(convertToResult(code, content, operator));
}
});
}
- iOS
- (void)loginAuth:(NSDictionary*)params callback:(WXModuleKeepAliveCallback)callback eventCallback:(WXModuleKeepAliveCallback)eventCallback
{
[self logger:@"loginAuth with params:" log:params];
BOOL autoFinish = true;
BOOL animation = true;
NSTimeInterval time = 10000;
if (params[@"autoFinish"]) {
autoFinish = [params[@"autoFinish"] boolValue];
}
if (params[@"animationFlag"]) {
animation = [params[@"animationFlag"] boolValue];
}
if(params[@"timeout"]){
time = [params[@"timeout"] doubleValue];
}
UIViewController *topVC = [self findVisibleVC];
[JVERIFICATIONService getAuthorizationWithController:topVC hide:autoFinish animated:animation timeout:time completion:^(NSDictionary *result) {
NSNumber *code = result[@"code"];
NSString *content = @"";
if(result[@"content"]){
content = result[@"content"];
}
if(result[@"loginToken"]){
content = result[@"loginToken"];
}
NSString *operator = result[@"operator"]?result[@"operator"]:@"";
NSDictionary *responseData = [self convertToResult:code content:content operator:operator];
callback(responseData,NO);
} actionBlock:^(NSInteger type, NSString *content) {
NSNumber *code = [NSNumber numberWithLong: type];
NSDictionary *responseData = [self convertToResult:code content:content];
eventCallback(responseData,YES);
}];
}
这样前端仅需一套代码即可控制两端的认证功能
示例
jv.loginAuth({
autoFinish:true,
timeout:5000
},result=>{
// 结果监听
let code = result.code;
let loginToken = result.content;
let operator = result.operator;
},event=>{
// 事件监听
let code = result.code;
let eventDesc = result.content;
})
这里就不重复接口定义了,更多 API 参考:https://github.com/jpush/jverification-hbuilder-plugin/blob/master/doc/API.md
插件打包
如何打包 uniapp 插件
- Android:https://ask.dcloud.net.cn/article/35416
-
将认证 module 中所有 implementation 改为 compileonly 再打包插件,否则会导致包冲突。
-
- iOS:https://ask.dcloud.net.cn/article/35415
-
打包需要将 framework 打包配置成 release 版本,并将 framework 设置成静态包。
-
认证打包注意事项
我们在配置工程时,预留了 appkey 和 channel 的配置,所以在打包需要动态配置两个参数,参考配置出 manifest,动态参数关键看 parameters 部分。
{
"name": "JIGUANG-JVerification",
"id": "JIGUANG-JVerification",
"version": "1.0.0",
"description": "极光认证Hbuilder插件",
"_dp_type":"nativeplugin",
"_dp_nativeplugin":{
"ios": {
"plugins": [{
"type": "module",
"name": "JIGUANG-JVerification",
"class": "JVerificationModule"
}],
"integrateType": "framework",
"deploymentTarget": "8.0",
"frameworks": [
"AdSupport.framework",
"CoreLocation.framework",
"CFNetwork.framework",
"CoreFoundation.framework",
"libresolv.tbd",
"libz.tbd",
"libc++.1.tbd",
"CoreTelephony.framework",
"SystemConfiguration.framework",
"Security.framework",
"CoreGraphics.framework",
"libsqlite3.tbd",
"MobileCoreServices.framework"
],
"resources": [
"JVerificationResource.bundle"
],
"parameters": {
"JPUSH_APPKEY_IOS": {
"des": "[iOS]极光 portal 配置应用信息时分配的 AppKey",
"key": "JVerification:APP_KEY"
},
"JPUSH_CHANNEL_IOS": {
"des": "[iOS]用于统计分发渠道,不需要可填默认值 developer-default",
"key": "JVerification:CHANNEL"
}
}
},
"android": {
"plugins": [
{
"type": "module",
"name": "JIGUANG-JVerification",
"class": "cn.jiguang.uniplugin_jverification.JVerificationWXModule"
}
],
"integrateType": "aar",
"minSdkVersion": "16",
"permissions": [
"android.permission.INTERNET",
"android.permission.READ_PHONE_STATE",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.ACCESS_NETWORK_STATE",
"android.permission.ACCESS_WIFI_STATE",
"android.permission.CHANGE_NETWORK_STATE",
"android.permission.WRITE_SETTINGS",
"android.permission.SYSTEM_ALERT_WINDOW",
"android.permission.CHANGE_WIFI_STATE",
"android.permission.GET_TASKS",
"android.permission.VIBRATE",
"android.permission.WAKE_LOCK"
],
"abis": [
"armeabi-v7a",
"arm64-v8a",
"x86"
],
"parameters": {
"JPUSH_APPKEY_ANDROID": {
"des": "[Android]极光 portal 配置应用信息时分配的 AppKey",
"key": "JPUSH_APPKEY"
},
"JPUSH_CHANNEL_ANDROID":{
"des": "[Android]用于统计分发渠道,不需要可填默认值 developer-default",
"key": "JPUSH_CHANNEL"
}
}
}
}
}
打包后插件名和插件 id 为 JIGUANG-JVerification,打包后插件工程目录:
插件接入
1.将 nativeplugins/JIGUANG-JVerification 导入项目对应位置。
-
2.项目 manifest.json 中接入 JIGUANG-JVerification 插件。并配置好 appkey(极光 portal 注册分配),channel 信息。
3.在项目中引用插件即可
const jv = uni.requireNativePlugin('JIGUANG-JVerification');
结尾
最终开发出的认证插件及源码已开源,点击前往。