前提
本文介紹的是如果開發(fā)極光認(rèn)證的 HBuilderX 插件楼肪,最終開發(fā)出的插件已開源始鱼,如果需要使用請(qǐng)點(diǎn)擊前往github千埃。
極光認(rèn)證
極光認(rèn)證整合了三大運(yùn)營商的網(wǎng)關(guān)認(rèn)證能力济欢,為開發(fā)者提供了一鍵登錄和號(hào)碼認(rèn)證功能赠堵。前往官網(wǎng)查看全部功能
HBuilderX
目前極光只提供了 Android&iOS 的原生 SDK 接入,如果希望在 HBuilderX 中接入極光認(rèn)證法褥,需要開發(fā)適用的插件以方便在 HX 中直接使用 JS 調(diào)用極光認(rèn)證能力茫叭。
HBuilderX 是一款I(lǐng)DE,支持 uni-app 開發(fā)框架半等。所以需要按照 uni-app 開發(fā)完插件后打包給 HbuilderX 使用
插件準(zhǔn)備工作
極光側(cè)
1.在極光 Portal 測(cè)注冊(cè)應(yīng)用并開通認(rèn)證功能揍愁,拿到對(duì)應(yīng)的 appkey 等會(huì)做測(cè)試
2.前往下載最新的極光認(rèn)證Android和iOS兩端原生 SDK,本文示例版本
-
Android v2.5.2
-
iOS v2.5.3
uni-app 側(cè)
創(chuàng)建插件項(xiàng)目杀饵,并接入認(rèn)證 SDK
Android
-
1.參考Android平臺(tái)uni-app原生插件開發(fā)文檔 新建一個(gè) module 命名為 uniplugin_jverification莽囤,并在 uniapp SDK 插件項(xiàng)目中接入。
-
2.按照接入指南手動(dòng)集成部分(因?yàn)閡niapp 官方建議 jar 包優(yōu)先于 jcenter 集成方式)接入極光 SDK切距。
-
3.因?yàn)?appkey 和 channel 是變量需要配 meta 朽缎,為了方便用戶使用,這兩個(gè) meta 配在 app 的 AndroidManifest 中,并在后續(xù)插件配置中預(yù)留給用戶配置话肖,而不是打進(jìn)插件包里北秽。
-
-
4 在 module 中新建一個(gè)類為 JVerificationWXModule 繼承 WXSDKEngine.DestroyableModule,并將其配置成插件入口狼牺。
5.Android 插件開發(fā)準(zhǔn)備完畢
iOS
-
1.參考iOS平臺(tái)uni-app原生插件開發(fā)文檔新建一個(gè) framework 命名為 UnipluginJVerification羡儿,將其配置為靜態(tài)庫,并在 uniapp SDK 插件項(xiàng)目中接入是钥。
-
2.按照iOS 接入配置手動(dòng)導(dǎo)入
(因?yàn)閡niapp 官方建議靜態(tài)庫優(yōu)先于 pod 集成方式)接入極光 SDK掠归。
-
3.因?yàn)?appkey 和 channel 是變量需要在后續(xù)插件配置中預(yù)留給用戶配置,而不是打進(jìn)插件包里悄泥,所以將其配在項(xiàng)目的 infolist 中動(dòng)態(tài)獲取虏冻。
-
4 在 framework 中新建一個(gè)聲明 JVerificationModule.h 導(dǎo)入 WXModuleProtocal.h,并將其配置成插件入口弹囚。
5.iOS 插件開發(fā)準(zhǔn)備完畢
插件開發(fā)
如何開發(fā)和調(diào)試 uniapp 插件
認(rèn)證插件開發(fā)注意事項(xiàng)
認(rèn)證 Android 和 iOS 作為同一款產(chǎn)品的兩端厨相,雖然他們 API 命名不同,但兩端的功能是極其相似的鸥鹉,比如請(qǐng)求一鍵登錄時(shí)蛮穿,均可以設(shè)置超時(shí),設(shè)置登錄完成后是否自動(dòng)關(guān)閉授權(quán)頁毁渗。
// Android
LoginSettings settings = new LoginSettings();
settings.setAutoFinish(true);//設(shè)置登錄完成后是否自動(dòng)關(guān)閉授權(quán)頁
settings.setTimeout(15 * 1000);//設(shè)置超時(shí)時(shí)間践磅,單位毫秒。 合法范圍(0灸异,30000],范圍以外默認(rèn)設(shè)置為10000
settings.setAuthPageEventListener(new AuthPageEventListener() {
@Override
public void onEvent(int cmd, String msg) {
//do something...
}
});//設(shè)置授權(quán)頁事件監(jiān)聽
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);
}];
所以為了方便用戶的使用府适,插件需要盡可能的統(tǒng)一兩端的使用方式,比如約定 timeout 和 autoFinish 作為一鍵認(rèn)證功能超時(shí)肺樟,登錄完成后是否自動(dòng)關(guān)閉授權(quán)頁功能的標(biāo)識(shí)檐春,前端下發(fā)一套配置,兩端各自處理對(duì)應(yīng)配置么伯,并將結(jié)果統(tǒng)一返回疟暖,這樣極大方便了前端使用者。
以一鍵登錄為例定義對(duì)外接口:
API - loginAuth(Object田柔,CALLBACK誓篱,EVENTCALLBACK)
調(diào)起一鍵登錄授權(quán)頁面,在用戶授權(quán)后獲取 loginToken凯楔,同時(shí)支持授權(quán)頁事件監(jiān)聽窜骄。
參數(shù)說明
- Object
參數(shù)名稱 | 參數(shù)類型 | 參數(shù)說明 |
---|---|---|
timeout | number | 設(shè)置初始化超時(shí)時(shí)間,單位毫秒摆屯,合法范圍是(0,30000]邻遏,推薦設(shè)置為 5000-10000,默認(rèn)值為 10000糠亩。 |
autoFinish | boolean | 是否自動(dòng)關(guān)閉授權(quán)頁,true - 是准验,false - 否 |
animationFlag | boolean | 拉起授權(quán)頁時(shí)是否需要?jiǎng)赢嬓Ч晗撸瑃rue - 是,false - 否糊饱,默認(rèn) true垂寥。(僅作用與 iOS) |
根據(jù)接口定義我們可以對(duì)應(yīng)開發(fā)插件兩端代碼為
- 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);//設(shè)置登錄完成后是否自動(dòng)關(guān)閉授權(quán)頁
settings.setTimeout(timeout);//設(shè)置超時(shí)時(shí)間,單位毫秒另锋。 合法范圍(0滞项,30000],范圍以外默認(rèn)設(shè)置為10000
settings.setAuthPageEventListener(new AuthPageEventListener() {
@Override
public void onEvent(int cmd, String msg) {
eventCallback.invokeAndKeepAlive(convertToResult(cmd, msg));
}
});//設(shè)置授權(quán)頁事件監(jiān)聽
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);
}];
}
這樣前端僅需一套代碼即可控制兩端的認(rèn)證功能
示例
jv.loginAuth({
autoFinish:true,
timeout:5000
},result=>{
// 結(jié)果監(jiān)聽
let code = result.code;
let loginToken = result.content;
let operator = result.operator;
},event=>{
// 事件監(jiān)聽
let code = result.code;
let eventDesc = result.content;
})
這里就不重復(fù)接口定義了,更多 API 參考:https://github.com/jpush/jverification-hbuilder-plugin/blob/master/doc/API.md
插件打包
如何打包 uniapp 插件
- Android:https://ask.dcloud.net.cn/article/35416
-
將認(rèn)證 module 中所有 implementation 改為 compileonly 再打包插件夭坪,否則會(huì)導(dǎo)致包沖突文判。
-
- iOS:https://ask.dcloud.net.cn/article/35415
-
打包需要將 framework 打包配置成 release 版本,并將 framework 設(shè)置成靜態(tài)包室梅。
-
認(rèn)證打包注意事項(xiàng)
我們?cè)谂渲霉こ虝r(shí)戏仓,預(yù)留了 appkey 和 channel 的配置,所以在打包需要?jiǎng)討B(tài)配置兩個(gè)參數(shù)亡鼠,參考配置出 manifest赏殃,動(dòng)態(tài)參數(shù)關(guān)鍵看 parameters 部分。
{
"name": "JIGUANG-JVerification",
"id": "JIGUANG-JVerification",
"version": "1.0.0",
"description": "極光認(rèn)證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 配置應(yīng)用信息時(shí)分配的 AppKey",
"key": "JVerification:APP_KEY"
},
"JPUSH_CHANNEL_IOS": {
"des": "[iOS]用于統(tǒng)計(jì)分發(fā)渠道间涵,不需要可填默認(rèn)值 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 配置應(yīng)用信息時(shí)分配的 AppKey",
"key": "JPUSH_APPKEY"
},
"JPUSH_CHANNEL_ANDROID":{
"des": "[Android]用于統(tǒng)計(jì)分發(fā)渠道仁热,不需要可填默認(rèn)值 developer-default",
"key": "JPUSH_CHANNEL"
}
}
}
}
}
打包后插件名和插件 id 為 JIGUANG-JVerification,打包后插件工程目錄:
插件接入
1.將 nativeplugins/JIGUANG-JVerification 導(dǎo)入項(xiàng)目對(duì)應(yīng)位置浑厚。
-
2.項(xiàng)目 manifest.json 中接入 JIGUANG-JVerification 插件。并配置好 appkey(極光 portal 注冊(cè)分配)根盒,channel 信息钳幅。
3.在項(xiàng)目中引用插件即可
const jv = uni.requireNativePlugin('JIGUANG-JVerification');
結(jié)尾
最終開發(fā)出的認(rèn)證插件及源碼已開源,點(diǎn)擊前往炎滞。