在鸿蒙(HarmonyOS)系统中开通认证服务 如何使用自己设计的UI界面和修改个人信息(例:上传头像)的步骤如下:
2025-06-29 10:36:14
121次阅读
0个评论
1. 准备工作
1. 注册华为开发者账号
- 访问华为开发者联盟官网并注册账号。
- 完成实名认证(个人或企业开发者),需提供身份证或企业资质信息。
2. 登录AppGallery Connect (AGC)
- 使用华为开发者账号登录AGC控制台。
- 创建或选择已有项目。
3. 开通认证服务
- 在项目设置中,点击左侧菜单的 “认证服务”。
- 选择需要开通的认证方式(如手机验证码、邮箱、生物识别等)并启用。
4. 配置端侧项目
- 添加依赖:在
oh-package.json5
中引入相关SDK,如:
"dependencies": {
"@hw-agconnect/cloud": "^1.0.0",
"@hw-agconnect/hmcore": "^1.0.0"
}
- 开通网络权限:在
module.json5
中申请INTERNET
权限。 - 更新
agconnect-services.json
:从AGC下载最新配置文件并集成到项目中。
5. 登录页面实现 (MyLogin.ets)
5.1 基础界面代码
@Entry
@Component
struct MyLogin {
// 状态变量声明
@State phoneNumber: string = ''; //手机号
@State verifyCode: string = ''; //验证码
build() {
Column({space:10}){
Text('登录').fontSize(24)
Divider()
Row(){
TextInput({ placeholder: '请输入手机号' })
.width(160)
.onChange((val) => {
this.phoneNumber = val // 绑定手机号输入
})
}
Row(){
TextInput({placeholder:'请输入验证码'})
.width(150)
.onChange((val)=>{
this.verifyCode = val // 绑定验证码输入
})
Button('获取验证码').onClick(async ()=>{
/* 调用5.2逻辑 */
})
}
Button('登录').onClick(async () => {
/* 调用5.3逻辑 */
})
}
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
说明:
- 使用ArkUI声明式语法构建登录界面,包含手机号和验证码输入框
- 通过
@State
实现数据响应式绑定,输入内容实时更新状态变量
5.2 验证码功能实现
Button('获取验证码')
.onClick(async ()=>{
try {
await cloud.auth().requestVerifyCode({
verifyCodeType: {
kind: 'phone',
phoneNumber: this.phoneNumber, // 获取用户输入的手机号
countryCode: '86'
},
action: VerifyCodeAction.REGISTER_LOGIN,
lang: 'zh_CN',
sendInterval: 60
})
promptAction.showToast({ message: '验证码已发送' })
} catch (error) {
promptAction.showToast({ message: `发送失败: ${error.message}` })
}
})
说明:
requestVerifyCode
方法向指定手机号发送验证码sendInterval
参数防止频繁发送,提升安全性
5.3 登录功能实现
@State verifyCode:string = '' // 验证码
@StorageLink('user')user:AuthUser | null= null //使用 AppStorage 保存当前登录的用户信息
Button('登录')
.onClick(async () => {
try {
const result = await cloud.auth().signIn({
credentialInfo: {
kind: 'phone',
countryCode: '86',
phoneNumber: this.phoneNumber, // 获取用户输入的手机号
verifyCode: this.verifyCode // 获取用户输入的验证码
}
})
const user = result.getUser() // 用户信息
AppStorage.setOrCreate('user',user) // 保存用户信息
router.replaceUrl({url:'pages/MyInfo'})
promptAction.showToast({ message: '登录成功' })
} catch (error) {
console.error('登录失败:', error)
promptAction.showToast({ message: '登录失败' })
}
})
说明:
signIn
方法通过手机号+验证码完成登录验证AppStorage
实现用户信息跨页面持久化
5.4处理异常退出后无法登录
async aboutToAppear(): Promise<void> {
// 防止异常退出应用无法登录
try {
const user = await cloud.auth().getCurrentUser()
if (user != null) {
AppStorage.setOrCreate('user',user)
router.replaceUrl({url:'pages/MyInfo'})
}
}catch (e){
}
}
6. 用户信息页面 (MyInfo.ets)
6.1 基础界面
@State username: string = '';
@State photoUrl: string = '';
@State uris: Array<string> = []; // 新增:图片URI数组
@StorageLink('user') user: AuthUser | null = null;
build() {
Column({space:10}){
Image(this.photoUrl == undefined?$r('app.media.user_dark'):this.photoUrl)
.width(70)
.onClick(()=>{
this.getFileAssetsFromType() // 调用6.3逻辑
})
Row(){
Text('昵称:')
TextInput({placeholder:`${this.username}`})
.onChange((val)=>{
this.username = val
})
}
Button('保存').onClick(async () => {
/* 调用6.4逻辑 */
})
Button('退出登录').onClick(async ()=>{
/* 调用6.5逻辑 */
})
}
.height('100%')
.width('100%')
}
说明:
- 通过条件渲染显示用户头像或默认占位图
- 点击头像触发文件选择器
6.2 用户信息获取
@State username: string = ''; //用户昵称
@State photoUrl : string = '' //用户头像
@StorageLink('user')user:AuthUser | null= null // 登录的用户信息
aboutToAppear(): void {
// 1.
cloud.auth().getCurrentUser() // 方法一直接获取当前登录的用户信息
// 2.AppStorage 使用上一个登录页面的 AppStorage 保存当前登录的用户信息
this.photoUrl = this.user?.getPhotoUrl() as string
this.username = this.user?.getDisplayName() as string
}
说明:
aboutToAppear
生命周期钩子在页面显示前初始化数据- 优先从
AppStorage
获取用户信息,减少网络请求
6.3 头像上传功能
/**
* 图片上传
*/
getFileAssetsFromType(){
// 获取图片选择对象实例
const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions()
// 定义当前图片选择器选择图片的最大数量
photoSelectOptions.maxSelectNumber = 1
// 定义选择数据的类型
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE
// 创建图库选择器实例
const photoviewPicker = new photoAccessHelper.PhotoViewPicker()
photoviewPicker.select(photoSelectOptions)
.then((value)=>{
// 获取到选择图片的路径,数组类型数据
this.uris = value.photoUris
this.photoCount = this.uris.length
this.photoUrl = this.uris[0]
}).catch((err:BusinessError)=>{
console.error('err',JSON.stringify(err))
return
})
}
Image(this.photoUrl == undefined?$r('app.media.user_dark'):this.photoUrl) // 设置默认头像
.width(70)
.onClick(()=>{
this.getFileAssetsFromType() // 调用上传头像方法
})
说明:
- 使用系统相册选择器获取本地图片URI
6.4 数据保存功能
Button('保存')
.onClick(async () => {
if (!this.user) {
promptAction.showToast({ message: '用户未登录' });
return;
}
try {
await this.user.updateProfile({
displayName: this.username, // 获取修改后的用户名
photoUrl: this.photoUrl // 获取修改后的头像
});
promptAction.showToast({ message: '保存成功' });
} catch (e) {
console.error(e); // 打印错误信息到控制台
promptAction.showToast({ message: '保存失败: ' + e.message });
}
})
说明:
- 保存前校验用户登录状态
updateProfile
需配合云存储使用
6.5 退出登录
Button('退出登录')
.onClick(async ()=>{
try {
await cloud.auth().signOut();
this.user = null; // 清空本地用户状态
router.back(); // 返回上一页
} catch (error) {
console.error('退出失败:', error);
}
})
说明:
signOut
清除本地认证令牌- 同步更新全局存储中的用户状态
补充说明:
- 状态管理:
@State
用于组件内响应式数据,@StorageLink
实现跨组件数据共享- 复杂场景建议使用全局状态管理(如Redux模式)
- 调试建议:
- 真机测试需确保AGC项目配置正确的OAuth 2.0回调地址
- 使用
console.log
打印用户对象结构,验证数据获取
- 结合华为云服务实现端云一体化认证。
如需更详细的代码示例或高级配置(如生物识别认证),可参考华为官方文档或相关教程。
完整代码和模拟器演示:
1.登录页面实现 (MyLogin.ets)
import cloud, { AuthUser, VerifyCodeAction } from '@hw-agconnect/cloud'
import { promptAction, router } from '@kit.ArkUI'
@Entry
@Component
struct MyLogin {
@State phoneNumber:string = ''
@State verifyCode:string = ''
@StorageLink('user')user:AuthUser | null= null
async aboutToAppear(): Promise<void> {
// 防止异常退出应用无法登录
try {
const user = await cloud.auth().getCurrentUser()
if (user != null) {
AppStorage.setOrCreate('user',user)
router.replaceUrl({url:'pages/MyInfo'})
}
}catch (e){
}
}
build() {
Column({space:10}){
Text('登录')
.fontSize(24)
Divider()
Row(){
TextInput({placeholder:'请输入手机号'})
.width(260)
.onChange((val)=>{
this.phoneNumber = val
})
}
Row(){
TextInput({placeholder:'请输入验证码'})
.width(150)
.onChange((val)=>{
this.verifyCode = val
})
Button('获取验证码')
.onClick(async ()=>{
try {
await cloud.auth().requestVerifyCode({
verifyCodeType: {
kind: 'phone',
phoneNumber: this.phoneNumber,
countryCode: '86'
},
action: VerifyCodeAction.REGISTER_LOGIN,
lang: 'zh_CN',
sendInterval: 60
})
promptAction.showToast({ message: '验证码已发送' })
} catch (error) {
promptAction.showToast({ message: `发送失败: ${error.message}` })
}
})
}
Button('登录')
.onClick(async () => {
try {
const result = await cloud.auth().signIn({
credentialInfo: {
kind: 'phone',
countryCode: '86',
phoneNumber: this.phoneNumber,
verifyCode: this.verifyCode
}
})
const user = result.getUser() // 用户信息
AppStorage.setOrCreate('user',user) // 保存用户信息
router.replaceUrl({url:'pages/MyInfo'})
promptAction.showToast({ message: '登录成功' })
} catch (error) {
console.error('登录失败:', error)
promptAction.showToast({ message: '登录失败' })
}
})
}
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
/**
* user.getuid() //获取用户唯一标识
*user.getPhone() //获取手机号
*user.getEmail() // 获取邮箱
*user.getUserExtra() //获取用户创建时间 和 最近一次的登录时间
* user.getPhotoUrl() // 头像
* user.getDisplayName() //昵称
*/
2.用户信息页面 (MyInfo.ets)
import cloud, { AuthUser } from '@hw-agconnect/cloud';
import { promptAction, router } from '@kit.ArkUI';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { error } from '@hw-agconnect/hmcore/src/main/ets/error/CoreErrorCode';
@Entry
@Component
struct MyInfo {
@State username: string = ''; //用户昵称
@State photoUrl : string = '' //用户头像
@StorageLink('user')user:AuthUser | null= null // 登录的用户信息
@State uris:Array<string> = [] // 从图库获取的图片路径组
@State photoCount:number = 0
aboutToAppear(): void {
// 1.
cloud.auth().getCurrentUser()
// 2.AppStorage
this.photoUrl = this.user?.getPhotoUrl() as string
console.log('useruser',`${this.photoUrl}`);
this.username = this.user?.getDisplayName() as string
console.log('useruser',JSON.stringify(this.user?.getDisplayName()));
console.log('useruser',`${this.username}`);
}
/**
* 图片上传
*/
getFileAssetsFromType(){
// 获取图片选择对象实例
const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions()
// 定义当前图片选择器选择图片的最大数量
photoSelectOptions.maxSelectNumber = 1
// 定义选择数据的类型
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE
// 创建图库选择器实例
const photoviewPicker = new photoAccessHelper.PhotoViewPicker()
photoviewPicker.select(photoSelectOptions)
.then((value)=>{
// 获取到选择图片的路径,数组类型数据
this.uris = value.photoUris
this.photoCount = this.uris.length
this.photoUrl = this.uris[0]
}).catch((err:BusinessError)=>{
console.error('err',JSON.stringify(err))
return
})
}
build() {
Column({space:10}){
Image(this.photoUrl == undefined?$r('app.media.user_dark'):this.photoUrl)
.width(70)
.onClick(()=>{
this.getFileAssetsFromType()
this.photoUrl = this.uris[0]
})
Row(){
Text('昵称:')
TextInput({placeholder:`${this.username}`})
.onChange((val)=>{
this.username = val
})
}
Button('保存')
.onClick(async () => {
if (!this.user) {
promptAction.showToast({ message: '用户未登录' });
return;
}
try {
await this.user.updateProfile({
displayName: this.username,
photoUrl: this.photoUrl
});
promptAction.showToast({ message: '保存成功' });
} catch (e) {
console.error(e); // 打印错误信息到控制台
promptAction.showToast({ message: '保存失败: ' + e.message });
}
})
Button('退出登录')
.onClick(async ()=>{
try {
await cloud.auth().signOut() // 退出登录
router.replaceUrl({ url: 'pages/Index' })
promptAction.showToast({ message: '保存成功' })
}catch (e) {
}
})
}
.height('100%')
.width('100%')
}
}
3.演示效果
00
- 0回答
- 0粉丝
- 0关注
相关话题
- 在鸿蒙(HarmonyOS 5)系统中开通认证服务的步骤如下(Login()组件):
- 《仿盒马》app开发技术分享-- 个人信息页(23)
- Uniapp在鸿蒙中的使用 二
- HarmonyNext技术探索:ArkTS在鸿蒙系统中的高级动画与交互设计
- 鸿蒙5.0如何快速接入端云一体化的认证服务
- 【HarmonyOS】模仿个人中心头像图片,调用系统相机拍照,从系统相册选择图片和圆形裁剪显示 (一)
- 【HarmonyOS】模仿个人中心头像图片,调用系统相机拍照,从系统相册选择图片和圆形裁剪显示 (二)
- 【HarmonyOS 5】鸿蒙中如何使用MQTT
- 【HarmonyOS 5】鸿蒙中如何使用MQTT
- HarmonyOS NEXT 头像制作项目系列教程之 --- 头像上传功能实现
- HarmonyNext深度解析:ArkTS在鸿蒙系统中的高级应用与实践
- HarmonyNext技术解析:ArkTS在鸿蒙系统中的高效性能优化实践
- OpenHarmony 设计模式-单例模式
- 如何通过系统相机拍照和录像
- HarmonyNext:深入探索鸿蒙内核与ArkTS在系统开发中的实践