今天开始我们就正式开始鸿蒙next的代码开发啦,掌门人会带着大家一步步体验各种功能的实现,并且会在最后带着大家实现一个完整的项目,当然了,肯定不会是烂大街的那种商城啊、TOList啥的,大家可以放心。
在鸿蒙开发中,实现华为账号一键登录可以为用户提供更加便捷的登录方式。掌门人将会通过本文详细介绍如何在鸿蒙应用中实现华为账号一键登录功能。
好了,废话不多说,我们直接进入正题。
DevEco Studio下载/安装以及创建项目
下载
请前往下载中心获取并下载DevEco Studio。
为保证DevEco Studio正常运行,建议电脑配置满足如下要求:
Windows运行环境要求
- 操作系统:Windows10 64位、Windows11 64位
- 内存:16GB及以上
- 硬盘:100GB及以上
- 分辨率:1280*800像素及以上
Mac运行环境要求
- 作系统:macOS(X86) 11/12/13/14 macOS(ARM) 12/13/14
- 内存:8GB及以上
- 硬盘:100GB及以上
- 分辨率:1280*800像素及以上
Windows安装
下载完成后,双击下载的"deveco-studio-xxxx.exe",进入DevEco Studio安装向导,可以自行修改安装目录,一直点击下一步即可。
mac安装
在安装界面中,将"DevEco-Studio.app"拖拽到"Applications"中,等待安装完成。
DevEco Studio提供开箱即用的开发体验,将HarmonyOS SDK、Node.js、Hvigor、OHPM、模拟器平台等进行合一打包,简化DevEco Studio安装配置流程。
HarmonyOS SDK已嵌入DevEco Studio中,无需额外下载配置
创建项目
-
打开DevEco Studio,在欢迎页单击Create Project,创建一个新工程。
-
根据工程创建向导,选择创建Application或Atomic Service。选择Empty Ability模板,然后单击Next。关于工程模板的介绍和支持的设备类型,请参考工程模板介绍。
-
填写工程相关信息,单击Finish。关于各个参数的详细介绍,请参考创建一个新的工程。
运行Hello World
-
将搭载HarmonyOS系统的真机与电脑连接。具体指导及要求,可查看运行应用/服务。
-
点击File > Project Structure... > Project > SigningConfigs界面勾选"Support HarmonyOS"和"Automatically generate signature",点击界面提示的"Sign In",使用华为账号登录。等待自动签名完成后,点击"OK"即可。如下图所示:
-
在编辑窗口右上角的工具栏,点击运行按钮运行项目。效果如下图所示:
至此一个鸿蒙next应用就创建完毕了,接下来我们来实现华为账号相关的。
开发准备
我们需要配置以下两个东西:
配置Client ID
- 登录AppGallery Connect平台,在"我的项目"中选择目标应用,在"项目设置 > 常规 > 应用"区域获取"OAuth 2.0客户端ID(凭据)"处的Client ID。
- 在工程中entry模块的module.json5文件中,新增metadata,配置name为client_id,value为上一步获取的Client ID的值,如下所示:
配置scope权限
具体配置步骤大家可以移步官网查看配置scope权限
关于UI,华为账号服务需要遵循华为登录UX设计规范。
一、导入所需模块
首先,在代码的开头,我们需要导入一系列的模块,这些模块将为实现华为账号一键登录提供必要的功能支持。
ts
import { loginComponentManager, LoginWithHuaweiIDButton, authentication } from '@kit.AccountKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction, router } from '@kit.ArkUI';
import { connection } from '@kit.NetworkKit';
import { util } from '@kit.ArkTS';
二、定义组件结构
接下来,定义一个名为QuickLoginButtonComponent
的组件结构。这个组件将包含实现华为账号一键登录所需的各种属性和方法。
ts
@Component
export struct QuickLoginButtonComponent {
logTag: string = 'QuickLoginButtonComponent';
domainId: number = 0x0000;
// 第二步获取的匿名化手机号传到此处
@State quickLoginAnonymousPhone: string = this.getQuickLoginAnonymousPhone() || '';
// 是否勾选协议
@State isSelected: boolean = false;
// 华为账号用户认证协议链接,此处仅为示例,实际开发过程中,域名不建议硬编码在本地
private static USER_AUTHENTICATION_PROTOCOL: string =
'https://privacy.consumer.huawei.com/legal/id/authentication-terms.htm?code=CN&language=zh-CN';
private static USER_SERVICE_TAG = '用户服务协议';
private static PRIVACY_TAG = '隐私协议';
private static USER_AUTHENTICATION_TAG = '华为账号用户认证协议';
// 定义LoginWithHuaweiIDButton展示的隐私文本,展示应用的用户服务协议、隐私协议和华为账号用户认证协议
privacyText: loginComponentManager.PrivacyText[] = [{
text: '已阅读并同意',
type: loginComponentManager.TextType.PLAIN_TEXT
}, {
text: '《用户服务协议》',
tag: QuickLoginButtonComponent.USER_SERVICE_TAG,
type: loginComponentManager.TextType.RICH_TEXT
}, {
text: '《隐私协议》',
tag: QuickLoginButtonComponent.PRIVACY_TAG,
type: loginComponentManager.TextType.RICH_TEXT
}, {
text: '和',
type: loginComponentManager.TextType.PLAIN_TEXT
}, {
text: '《华为账号用户认证协议》',
tag: QuickLoginButtonComponent.USER_AUTHENTICATION_TAG,
type: loginComponentManager.TextType.RICH_TEXT
}, {
text: '。',
type: loginComponentManager.TextType.PLAIN_TEXT
}];
//... 其他方法和属性的定义
}
三、获取匿名手机号的方法
在组件中,定义了一个名为getQuickLoginAnonymousPhone
的方法,用于获取匿名手机号。这个方法通过创建授权请求,并设置相应的参数,包括请求的范围scopes
等。如果成功获取到匿名手机号,则返回该手机号;如果未获取到,则返回空字符串,并可能需要跳转到应用自定义的登录页面。
ts
getQuickLoginAnonymousPhone():string {
// 创建授权请求,并设置参数
const authRequest = new authentication.HuaweiIDProvider().createAuthorizationWithHuaweiIDRequest();
// 获取匿名手机号需传quickLoginAnonymousPhone这个scope,传参之前需要先申请"华为账号一键登录"权限
//(权限名称为:quickLoginMobilePhone),后续才能获取匿名手机号数据
authRequest.scopes = ['quickLoginAnonymousPhone'];
// 用于防跨站点请求伪造
authRequest.state = util.generateRandomUUID();
// 一键登录场景该参数只能设置为false
authRequest.forceAuthorization = false;
const controller = new authentication.AuthenticationController();
try {
controller.executeRequest(authRequest).then((response: authentication.AuthorizationWithHuaweiIDResponse) => {
// 获取到UnionID、OpenID、匿名手机号
const unionID = response.data?.unionID;
const openID = response.data?.openID;
const anonymousPhone = response.data?.extraInfo?.quickLoginAnonymousPhone as string;
if (anonymousPhone) {
hilog.info(0x0000, 'testTag', 'Succeeded in authentication.');
return anonymousPhone;
}
hilog.info(0x0000, 'testTag', 'Succeeded in authentication. AnonymousPhone is empty.');
return response;
// 未获取到匿名手机号需要跳转到应用自定义的登录页面
}).catch((error: BusinessError) => {
this.dealAllError(error);
return '';
})
} catch (error) {
hilog.error(0x0000, 'testTag',
`Failed to login, errorCode is ${error.code}, errorMessage is ${error.message}`);
return '';
}
return '';
}
四、构造登录按钮控制器
通过构造LoginWithHuaweiIDButtonController
来控制华为账号一键登录按钮的行为。可以设置协议状态、处理登录按钮的点击事件等。
ts
controller: loginComponentManager.LoginWithHuaweiIDButtonController =
new loginComponentManager.LoginWithHuaweiIDButtonController()
/**
* 当应用使用自定义的登录页时,如果用户未同意协议,需要设置协议状态为NOT_ACCEPTED,当用户同意协议后再设置
* 协议状态为ACCEPTED,才可以使用华为账号一键登录功能
*/
.setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED)
.onClickLoginWithHuaweiIDButton((error: BusinessError | undefined,
response: loginComponentManager.HuaweiIDCredential) => {
this.handleLoginWithHuaweiIDButton(error, response);
})
.onClickEvent((error: BusinessError, clickEvent: loginComponentManager.ClickEvent) => {
if (error) {
this.dealAllError(error);
return;
}
hilog.info(this.domainId, this.logTag, `onClickEvent clickEvent: ${clickEvent}`);
});
五、协议对话框
定义一个协议对话框agreementDialog
,用于展示用户服务协议、隐私协议和华为账号用户认证协议。用户可以在这个对话框中选择同意或取消协议。
ts
agreementDialog: CustomDialogController = new CustomDialogController({
builder: AgreementDialog({
privacyText: this.privacyText,
cancel: () => {
this.agreementDialog.close();
this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED);
},
confirm: () => {
this.agreementDialog.close();
this.isSelected = true;
this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.ACCEPTED);
// 调用此方法,同意协议与登录一并完成,无需再次点击登录按钮
this.controller.continueLogin((error: BusinessError) => {
if (error) {
hilog.error(this.domainId, this.logTag,
`Failed to click agreementDialog continueLogin. errCode is ${error.code}, errMessage is ${error.message}`);
} else {
hilog.info(this.domainId, this.logTag,
'Succeeded in clicking agreementDialog continueLogin.');
}
});
},
clickHyperlinkText: () => {
this.agreementDialog.close();
this.jumpToPrivacyWebView();
}
}),
autoCancel: false,
alignment: DialogAlignment.Center,
});
六、页面渲染和其他方法
aboutToAppear
方法在页面即将显示时被调用,可以用于传递页面渲染所需的数据。showToast
方法用于显示 Toast 提示信息。jumpToPrivacyWebView
方法用于跳转华为账号用户认证协议页,需要在工程的main_pages.json
文件中进行配置,并确保相应的权限已经申请。handleLoginWithHuaweiIDButton
方法处理华为账号一键登录按钮的点击事件,根据不同的错误情况进行相应的提示。dealAllError
方法用于处理所有的错误情况。
七、定义协议对话框结构
ts
@CustomDialog
export struct AgreementDialog {
logTag: string = 'AgreementDialog';
domainId: number = 0x0000;
dialogController?: CustomDialogController;
cancel: () => void = () => {
};
confirm: () => void = () => {
};
clickHyperlinkText: () => void = () => {
};
privacyText: loginComponentManager.PrivacyText[] = [];
private static USER_AUTHENTICATION_TAG = '华为账号用户认证协议';
//... 构建方法的定义
}
八、定义错误码枚举
ts
export enum ErrorCode {
// 账号未登录
ERROR_CODE_LOGIN_OUT = 1001502001,
// 该账号不支持一键登录,如儿童账号、海外账号
ERROR_CODE_NOT_SUPPORTED = 1001500003,
// 网络错误
ERROR_CODE_NETWORK_ERROR = 1001502005,
// 用户未同意用户协议
ERROR_CODE_AGREEMENT_STATUS_NOT_ACCEPTED = 1005300001
}
通过以上步骤,我们可以在鸿蒙应用中实现华为账号一键登录功能。在实际开发过程中,需要根据具体的业务需求和用户体验进行适当的调整和优化。同时,确保在开发过程中遵循鸿蒙开发的最佳实践和安全规范,以提供稳定、安全、便捷的用户登录体验。