当前位置:   article > 正文

鸿蒙实战开发-如何使用后台代理提醒,实现一个简易闹钟

鸿蒙实战开发-如何使用后台代理提醒,实现一个简易闹钟

介绍

本篇Codelab将介绍如何使用后台代理提醒,实现一个简易闹钟。要求完成以下功能:

  1. 展示指针表盘或数字时间。
  2. 添加、修改和删除闹钟。
  3. 展示闹钟列表,并可打开和关闭单个闹钟。
  4. 闹钟到设定的时间后弹出提醒。
  5. 将闹钟的定时数据保存到轻量级数据库。

相关概念

  • Canvas:提供画布组件,用于自定义绘制图形。
  • CanvasRenderingContext2D:使用RenderingContext在Canvas组件上进行绘制,绘制对象可以是矩形、文本、图片等。
  • 后台代理提醒:开发应用时,开发者可以调用后台提醒发布的接口创建定时提醒,包括倒计时、日历、闹钟三种提醒类型。使用后台代理提醒能力后,应用可以被冻结或退出,计时和弹出提醒的功能将被后台系统服务代理。本应用中主要使用到后台代理提醒的两个接口:publishReminder 发布一个后台代理提醒,使用callback方式实现异步调用,该方法需要申请通知弹窗Notification.requestEnableNotification后才能调用。cancelReminder 取消指定id的提醒,使用callback方式实现异步调用。

相关权限

本篇Codelab需要在module.json5中配置如下权限:

  1. "requestPermissions": [
  2. {
  3. "name": "ohos.permission.PUBLISH_AGENT_REMINDER"
  4. }
  5. ]

环境搭建

软件要求

  • DevEco Studio版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:润和RK3568开发板。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:

2.搭建烧录环境。

  1. 完成DevEco Device Tool的安装
  2. 完成RK3568开发板的烧录

3.搭建开发环境。

  1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
  2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”)。
  3. 工程创建完成后,选择使用真机进行调测。

代码结构解读

本篇Codelab只对核心代码进行讲解。

  1. ├──entry/src/main/ets // 代码区
  2. │ ├──common
  3. │ │ ├──constants
  4. │ │ │ ├──AlarmSettingType.ets // 闹钟设置类型枚举
  5. │ │ │ ├──CommonConstants.ets // 公共常量类
  6. │ │ │ ├──DetailConstant.ets // 详情页常量类
  7. │ │ │ └──MainConstant.ets // 首页常量类
  8. │ │ └──utils
  9. │ │ ├──DataTypeUtils.ets // 数据类型工具类
  10. │ │ ├──DimensionUtil.ets // 屏幕适配工具类
  11. │ │ └──GlobalContext.ets // 全局变量工具类
  12. │ ├──entryability
  13. │ │ └──EntryAbility.ets // 程序入口类
  14. │ ├──model
  15. │ │ ├──database
  16. │ │ │ ├──PreferencesHandler.ets // 轻量级数据库操作类
  17. │ │ │ └──PreferencesListener.ets // 轻量级数据库回调接口
  18. │ │ └──ReminderService.ets // 系统后台提醒服务类
  19. │ │──pages
  20. │ │ ├──DetailIndex.ets // 详情页入口文件
  21. │ │ └──MainIndex.ets // 主页入口文件
  22. │ │──view
  23. │ │ ├──Detail
  24. │ │ │ ├──dialog
  25. │ │ │ │ ├──CommonDialog.ets // 公共Dialog组件
  26. │ │ │ │ ├──DurationDialog.ets // 闹铃时长选择Dialog组件
  27. │ │ │ │ ├──IntervalDialog.ets // 闹铃间隔选择Dialog组件
  28. │ │ │ │ ├──RenameDialog.ets // 闹铃名设置Dialog组件
  29. │ │ │ │ └──RepeatDialog.ets // 闹铃重复设置Dialog组件
  30. │ │ │ ├──DatePickArea.ets // 详情页时间选择组件
  31. │ │ │ └──SettingItem.ets // 详情页设置组件
  32. │ │ ├──Main
  33. │ │ │ ├──AlarmList.ets // 主页闹钟列表组件
  34. │ │ │ ├──AlarmListItem.ets // 主页闹钟列表子项组件
  35. │ │ │ └──ClockArea.ets // 主页时钟组件
  36. │ │ └──BackContainer.ets // 自定义头部组件
  37. │ └──viewmodel
  38. │ ├──AlarmItemBean.ets // 闹钟属性类
  39. │ ├──AlarmSettingBean.ets // 闹钟设置属性类
  40. │ ├──DayDateBean.ets // 日期属性类
  41. │ ├──DetailViewModel.ets // 详情模块逻辑功能类
  42. │ ├──MainViewModel.ets // 主页逻辑功能类
  43. │ └──ReminderItemBean.ets // 后台提醒属性类
  44. └──entry/src/main/resources // 资源文件目录

闹钟主界面

闹钟界面包括当前时间、闹钟列表、添加闹钟子组件,具体包括以下模块:

  • 展示当前时间。
  • 展示闹钟列表。
  • 添加闹钟。
  • 后台代理提醒。

展示当前时间

当前时间使用了Canvas组件绘制,默认展示指针表盘,点击表盘区域切换为数字时钟。

在主页的ClockArea组件中初始化Canvas画布,并绑定指针表盘和数字时钟切换事件。

  1. // ClockArea.ets
  2. @Component
  3. export default struct ClockArea {
  4. ...
  5. build() {
  6. Canvas(this.renderContext)
  7. .width(this.canvasSize)
  8. .aspectRatio(CommonConstants.DEFAULT_LAYOUT_WEIGHT)
  9. .onReady(() => {
  10. if (this.drawInterval === CommonConstants.DEFAULT_NUMBER_NEGATIVE) {
  11. this.startDrawTask();
  12. }
  13. })
  14. .onClick(() => {
  15. this.showClock = !this.showClock;
  16. })
  17. }
  18. // 启动绘画任务
  19. private startDrawTask() {
  20. let that = this;
  21. that.renderContext.translate(
  22. this.canvasSize / CommonConstants.DEFAULT_DOUBLE,
  23. this.canvasSize / CommonConstants.DEFAULT_DOUBLE);
  24. that.drawClockArea();
  25. this.drawInterval = setInterval(() => {
  26. that.drawClockArea();
  27. }, MainConstant.DEFAULT_ONE_SECOND_MS);
  28. }
  29. ...
  30. }

绘画任务是使用CanvasRenderingContext2D对象在Canvas画布组件上绘制指针表盘和数字时钟。

  1. // ClockArea.ets
  2. // 开始绘制时钟区域
  3. private drawClockArea(): void{
  4. this.renderContext.clearRect(
  5. -this.canvasSize,
  6. -this.canvasSize / CommonConstants.DEFAULT_DOUBLE,
  7. this.canvasSize * CommonConstants.DEFAULT_DOUBLE,
  8. this.canvasSize);
  9. let date = new Date();
  10. let hours = date.getHours();
  11. let minutes = date.getMinutes();
  12. let seconds = date.getSeconds();
  13. if (this.showClock) {
  14. // 绘制表盘时钟
  15. } else {
  16. // 绘制数字时钟
  17. }
  18. }

展示闹钟列表

闹钟列表组件,展示已添加的闹钟信息,可对闹钟进行启停操作,点击闹钟可跳转到闹钟操作界面(修改和删除闹钟)。主页启动后获取轻量级数据库中的闹钟定时数据,并监控数据库数据变化。

  1. // MainViewModel.ets
  2. public queryAlarmsTasker(callback: (alarms: Array<AlarmItem>) => void) {
  3. let that = this;
  4. that.queryDatabaseAlarms(callback);
  5. let preference = GlobalContext.getContext().getObject('preference') as PreferencesHandler;
  6. preference.addPreferencesListener({
  7. onDataChanged() {
  8. that.queryDatabaseAlarms(callback);
  9. }
  10. } as PreferencesListener)
  11. }

在AlarmList.ets中添加闹钟列表子组件,并绑定启停、跳转事件。

  1. // AlarmList.ets
  2. @Component
  3. export default struct AlarmList {
  4. @Link alarmItems: Array<AlarmItem>;
  5. build() {
  6. List({ space: DimensionUtil.getVp($r('app.float.alarm_list_space')) }) {
  7. ForEach(this.alarmItems, (item: AlarmItem) => {
  8. ListItem() {
  9. AlarmListItem({ alarmItem: item })
  10. }.onClick(() => {
  11. router.pushUrl({ url: "pages/DetailIndex", params: { alarmItem: item } });
  12. })
  13. }, (item: AlarmItem) => JSON.stringify(item))
  14. }
  15. .padding({
  16. left: DimensionUtil.getVp($r('app.float.alarm_list_content_distance')),
  17. right: DimensionUtil.getVp($r('app.float.alarm_list_content_distance'))
  18. })
  19. .listDirection(Axis.Vertical)
  20. .layoutWeight(CommonConstants.DEFAULT_LAYOUT_WEIGHT)
  21. .margin({ top: DimensionUtil.getVp($r('app.float.alarm_list_content_distance')) })
  22. }
  23. }

添加闹钟

添加闹钟,点击界面底部闹钟添加按钮,跳转到闹钟操作界面(新增闹钟)。

在MainIndex.ets中为添加按钮绑定跳转事件。

  1. // MainIndex.ets
  2. @Entry
  3. @Component
  4. struct MainIndex {
  5. ...
  6. build() {
  7. Column() {
  8. ...
  9. Button() {
  10. Image($r('app.media.ic_add')).objectFit(ImageFit.Fill)
  11. }
  12. ...
  13. .onClick(() => {
  14. router.pushUrl({ url: "pages/DetailIndex" });
  15. })
  16. }
  17. ...
  18. }
  19. }

后台代理提醒

后台代理提醒,根据闹钟列表中的数据来设置(启停)闹钟实例。

  1. // MainViewModel.ets
  2. // 开启/关闭闹钟
  3. public openAlarm(id: number, isOpen: boolean) {
  4. for (let i = 0; i < this.alarms.length; i++) {
  5. if (this.alarms[i].id === id) {
  6. this.alarms[i].isOpen = isOpen;
  7. if (isOpen) {
  8. this.reminderService.addReminder(this.alarms[i]);
  9. } else {
  10. this.reminderService.deleteReminder(this.alarms[i].id);
  11. }
  12. let preference = GlobalContext.getContext().getObject('preference') as PreferencesHandler;
  13. preference.set(CommonConstants.ALARM_KEY, JSON.stringify(this.alarms));
  14. break;
  15. }
  16. }
  17. }

闹钟详情界面

闹钟操作界面分为新增和修改界面,其中在修改界面可删除闹钟。具体包括以下模块:

  • 退出或保存详情。
  • 设置闹钟时间。
  • 设置闹钟详情。
  • 提供后台代理提醒能力

退出或保存详情

点击左上角“x”图标关闭操作界面,关闭闹钟操作界面子组件,点击右上角“√”图标,保存当前设置并关闭操作界面。

在DetailIndex.ets入口页面中引入头部组件BackContainer,自定义了返回按钮和返回逻辑操作,添加确定(“√”)子组件,并绑定点击事件。

  1. // DetailIndex.ets
  2. build()
  3. {
  4. Column() {
  5. ...
  6. Button() {
  7. Image($r('app.media.ic_confirm')).objectFit(ImageFit.Fill)
  8. }
  9. .backgroundColor($r('app.color.trans_parent'))
  10. .width(DimensionUtil.getVp($r('app.float.title_button_size')))
  11. .height(DimensionUtil.getVp($r('app.float.title_button_size')))
  12. .onClick(() => {
  13. this.viewModel.setAlarmRemind(this.alarmItem);
  14. router.back();
  15. })
  16. ...
  17. }
  18. }
  19. // BackContainer.ets
  20. build() {
  21. Row() {
  22. ...
  23. Text(this.header)
  24. .fontSize(DimensionUtil.getFp($r('app.float.detail_title_font_size')))
  25. .lineHeight(DimensionUtil.getVp($r('app.float.title_line_height')))
  26. .margin({ left: DimensionUtil.getVp($r('app.float.title_margin')) })
  27. .fontColor($r('app.color.grey_divider'))
  28. .fontWeight(FontWeight.Bold)
  29. Blank()
  30. if (this.closer) {
  31. this.closer();
  32. }
  33. }
  34. .padding({
  35. left: DimensionUtil.getVp($r('app.float.title_horizon_margin')),
  36. right: DimensionUtil.getVp($r('app.float.title_horizon_margin'))
  37. })
  38. .height(DimensionUtil.getVp($r('app.float.page_title_height')))
  39. .width(CommonConstants.FULL_LENGTH)
  40. }

设置闹钟时间

设置闹钟提醒时间,在闹钟操作界面可通过滑动选择器设置闹钟的提醒时间(包括:时段、小时、分钟)。详情页DetailIndex.ets中添加闹钟时间选择器子组件DatePickArea.ets。

  1. // DatePickArea.ets
  2. @Component
  3. export default struct DatePickArea {
  4. build() {
  5. Stack({ alignContent: Alignment.Center }) {
  6. Row() {
  7. ForEach(DetailConstant.DAY_DATA, (item: DayDataBean) => {
  8. TextPicker({ range: item.data, selected: item.delSelect })
  9. .layoutWeight(CommonConstants.DEFAULT_LAYOUT_WEIGHT)
  10. .backgroundColor($r('app.color.grey_light'))
  11. .onChange((value: string, index: number) => {
  12. item.delSelect = index;
  13. })
  14. }, (item: DayDataBean) => JSON.stringify(item))
  15. }
  16. }
  17. .height(DimensionUtil.getVp($r('app.float.date_picker_height')))
  18. .padding({
  19. left: DimensionUtil.getVp($r('app.float.date_picker_padding_horizon')),
  20. right: DimensionUtil.getVp($r('app.float.date_picker_padding_horizon'))
  21. })
  22. }
  23. }

设置闹钟详情

点击详情页DetailIndex.ets设置条目组件SettingItem.ets,支持设置闹钟重复时间、闹钟名称、重复次数和闹铃时长。

  1. // SettingItem.ets
  2. build() {
  3. Column() {
  4. ForEach(this.settingInfo, (item: AlarmSettingBean, index: number | undefined) => {
  5. Divider()
  6. ...
  7. Row() {
  8. Text(item.title)...
  9. Text(item.content)...
  10. Image($r('app.media.ic_right'))...
  11. }
  12. ...
  13. .onClick(() => {
  14. this.showSettingDialog(item.sType);
  15. })
  16. }, (item: AlarmSettingBean, index: number | undefined) => JSON.stringify(item) + index)
  17. }
  18. ...
  19. }

提供后台代理提醒能力

导入系统提醒服务类ReminderService.ets,它由系统后台代理提醒能力封装,支持新增、修改、删除系统闹钟功能,在设置、删除闹钟后同步更新到轻量级数据库中并刷新主页页面。

  1. // DetailViewModel.ets
  2. public async setAlarmRemind(alarmItem: AlarmItem) {
  3. alarmItem.hour = this.getAlarmTime(CommonConstants.DEFAULT_SINGLE);
  4. alarmItem.minute = this.getAlarmTime(CommonConstants.DEFAULT_DATA_PICKER_HOUR_SELECTION);
  5. let index = await this.findAlarmWithId(alarmItem.id);
  6. if (index !== CommonConstants.DEFAULT_NUMBER_NEGATIVE) { // 已存在,删除原有提醒
  7. this.reminderService.deleteReminder(alarmItem.id);
  8. } else { // 不存在,以数据长度为notificationId新增闹钟数据
  9. index = this.alarms.length;
  10. alarmItem.notificationId = index;
  11. this.alarms.push(alarmItem);
  12. }
  13. this.reminderService.addReminder(alarmItem, (newId: number) => {
  14. alarmItem.id = newId;
  15. alarmItem.isOpen = true;
  16. this.alarms[index] = alarmItem;
  17. let preference = GlobalContext.getContext().getObject('preference') as PreferencesHandler;
  18. preference.set(CommonConstants.ALARM_KEY, JSON.stringify(this.alarms));
  19. })
  20. }
  21. public async removeAlarmRemind(id: number) {
  22. this.reminderService.deleteReminder(id);
  23. let index = await this.findAlarmWithId(id);
  24. if (index !== CommonConstants.DEFAULT_NUMBER_NEGATIVE) {
  25. this.alarms.splice(index, CommonConstants.DEFAULT_SINGLE);
  26. }
  27. let preference = GlobalContext.getContext().getObject('preference') as PreferencesHandler;
  28. preference.set(CommonConstants.ALARM_KEY, JSON.stringify(this.alarms));
  29. }

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. Canvas画布组件的使用。
  2. 后台代理提醒的使用。

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→HarmonyOS教学视频

HarmonyOS教学视频:语法ArkTS、TypeScript、ArkUI等…视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取完整版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF

在这里插入图片描述

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. .……

在这里插入图片描述


二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

在这里插入图片描述

三、如何快速入门?鸿蒙基础入门学习指南

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. .……

在这里插入图片描述


四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. .……

在这里插入图片描述


五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 7.网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. .……

在这里插入图片描述


更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/334377
推荐阅读
相关标签
  

闽ICP备14008679号