HarmonyOs应用《重要日》开发第13篇 - 通知提醒系统实现 本文深入解析 ImportantDays 项目中的通知提醒系统包括NotificationUtil工具类的设计、通知权限管理、基本通知与多行通知的发布、通知取消与角标设置以及WantAgent实现通知点击跳转的完整方案。一、通知系统概述ImportantDays 的通知系统负责在重要日临近时向用户发送提醒通知。整个通知系统由以下部分组成NotificationUtil (工具类) ├── 权限管理requestPermission / checkPermission ├── 通知发布publishBasic / publishMultiLine ├── 通知取消cancel / cancelAll └── 角标设置setBadge ImportantDayManager (业务层) ├── scheduleReminder单个重要日提醒 └── checkAndSendReminders批量检查提醒 EntryAbility (生命周期) ├── onCreate启动时检查提醒 └── onForeground回到前台时检查提醒二、NotificationUtil 工具类权限管理staticasyncrequestPermission():Promiseboolean{try{awaitnotificationManager.requestEnableNotification();returntrue;}catch(e){console.error(Failed to request notification permission:,e);returnfalse;}}staticasynccheckPermission():Promiseboolean{try{constenabledawaitnotificationManager.isNotificationEnabled();returnenabled;}catch(e){console.error(Failed to check notification permission:,e);returnfalse;}}权限管理流程应用首次启动 ↓ 用户进入我的页面 ↓ 切换通知开关 → ON ↓ requestPermission() → 弹出系统权限对话框 ↓ 用户选择 ├── 允许 → requestPermission 返回 true └── 拒绝 → requestPermission 返回 falsecheckPermission 的使用场景// 应用启动时检查consthasPermissionawaitNotificationUtil.checkPermission();if(hasPermission){awaitImportantDayManager.getInstance().checkAndSendReminders();}// 我的页面显示通知状态aboutToAppear():void{this.checkNotificationStatus();}privateasynccheckNotificationStatus():Promisevoid{this.notificationEnabledawaitNotificationUtil.checkPermission();}三、WantAgent通知点击跳转staticasyncgetDefaultWantAgent():PromiseWantAgent{constwantAgentInfo:wantAgent.WantAgentInfo{wants:[{bundleName:com.importantdays.app,abilityName:EntryAbility,action:action.system.home}],actionType:wantAgent.OperationType.START_ABILITY,requestCode:0,wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]};returnawaitwantAgent.getWantAgent(wantAgentInfo);}WantAgent 的作用WantAgent是鸿蒙系统中用于封装意图的对象。在通知中使用WantAgent可以实现点击通知后自动打开应用的指定页面。参数说明参数值说明bundleNamecom.importantdays.app应用包名abilityNameEntryAbility目标 Abilityactionaction.system.home启动 ActionactionTypeSTART_ABILITY启动 AbilityrequestCode0请求码wantAgentFlagsUPDATE_PRESENT_FLAG更新已有通知交互流程通知栏显示通知 ↓ 用户点击通知 ↓ 系统触发 WantAgent ↓ 启动 EntryAbility ↓ 应用打开到主页面 ↓ onForeground → checkAndSendReminders四、基本通知发布staticasyncpublishBasic(title:string,content:string,notificationId:number):Promisevoid{try{constagentawaitNotificationUtil.getDefaultWantAgent();constrequest:notificationManager.NotificationRequest{id:notificationId,content:{notificationContentType:notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,normal:{title:title,text:content,additionalText:}},wantAgent:agent,notificationSlotType:notificationManager.SlotType.SOCIAL_COMMUNICATION};awaitnotificationManager.publish(request);console.info(Notification published successfully, id:,notificationId);}catch(e){console.error(Failed to publish notification:,e);}}NotificationRequest 结构{id:notificationId,// 通知唯一IDcontent:{notificationContentType:NOTIFICATION_CONTENT_BASIC_TEXT,// 基本文本类型normal:{title:即将到来妈妈生日,// 通知标题text:还有 3 天,// 通知内容additionalText:// 附加文本}},wantAgent:agent,// 点击跳转意图notificationSlotType:SOCIAL_COMMUNICATION// 通知渠道类型}SlotType 选择SlotType说明适用场景SOCIAL_COMMUNICATION社交通信重要提醒项目选用SERVICE_INFORMATION服务信息一般通知CONTENT_INFORMATION内容信息内容推送OTHER_TYPES其他其他场景选择SOCIAL_COMMUNICATION确保通知优先级较高用户更容易注意到。五、多行文本通知staticasyncpublishMultiLine(title:string,lines:string[],notificationId:number):Promisevoid{try{constagentawaitNotificationUtil.getDefaultWantAgent();constrequest:notificationManager.NotificationRequest{id:notificationId,content:{notificationContentType:notificationManager.ContentType.NOTIFICATION_CONTENT_MULTILINE,multiLine:{title:title,text:lines[0]||,briefText:,longTitle:title,lines:lines,additionalText:}},wantAgent:agent,notificationSlotType:notificationManager.SlotType.SOCIAL_COMMUNICATION};awaitnotificationManager.publish(request);}catch(e){console.error(Failed to publish multi-line notification:,e);}}多行通知 vs 基本通知特性基本通知多行通知ContentTypeBASIC_TEXTMULTILINE内容字段normalmultiLine显示行数标题 1行内容标题 多行内容适用场景单条提醒多条提醒汇总使用场景示例当有多个重要日需要提醒时可以使用多行通知// 概念性使用项目中未直接调用constlines[妈妈生日 - 还有3天,结婚纪念日 - 还有7天,体检预约 - 还有10天];awaitNotificationUtil.publishMultiLine(重要日提醒,lines,10001);六、通知取消取消单个通知staticasynccancel(notificationId:number):Promisevoid{try{awaitnotificationManager.cancel(notificationId);}catch(e){console.error(Failed to cancel notification:,e);}}取消所有通知staticasynccancelAll():Promisevoid{try{awaitnotificationManager.cancelAll();}catch(e){console.error(Failed to cancel all notifications:,e);}}取消通知的时机删除重要日取消该重要日的通知更新重要日先取消旧通知再发布新通知用户手动清除在我的页面点击清除所有通知// 删除时取消asyncdeleteDay(dayID:string):Promisevoid{constdaythis.allDays[index];if(day.reminderEnabled){awaitNotificationUtil.cancel(this.getNotificationId(dayID));}// ...}// 更新时取消旧通知asyncupdateDay(day:ImportantDay):Promisevoid{awaitNotificationUtil.cancel(this.getNotificationId(day.dayID));// ...}七、角标设置staticasyncsetBadge(count:number):Promisevoid{try{awaitnotificationManager.setBadgeNumber(count);}catch(e){console.error(Failed to set badge:,e);}}角标的作用应用图标上显示数字角标提示用户有未读通知。可以设置需要提醒的重要日数量作为角标数字。八、通知 ID 生成策略// ImportantDayManager 中的方法privategetNotificationId(dayID:string):number{lethash0;for(leti0;idayID.length;i){hash((hash5)-hash)dayID.charCodeAt(i);hash|0;}returnMath.abs(hash)%100000ImportantDayManager.notificationIdBase;}哈希算法分析这是经典的字符串哈希算法djb2 变体初始hash 0对每个字符hash hash * 31 charCodehash | 0确保是 32 位整数取绝对值后对 100000 取模加上基数 10000ID 生成特性特性说明稳定性同一dayID总是生成相同的notificationId唯一性不同dayID大概率生成不同 ID范围10000 ~ 109999冲突概率100000 个槽位碰撞概率约 1/100000为什么需要稳定的 ID添加重要日 A → 通知 ID 10234 更新重要日 A → 需要取消旧通知 → cancel(10234) → 发布新通知 删除重要日 A → 需要取消通知 → cancel(10234)稳定的 ID 确保增删改操作能正确管理对应的通知。九、提醒逻辑单个提醒privateasyncscheduleReminder(day:ImportantDay):Promisevoid{constdiffday.getDaysDiff();if(diff0)return;if(diffday.reminderDaysBefore){consttitleday.isToday()?今天${day.title}:即将到来${day.title};constcontentday.getDisplayText();awaitNotificationUtil.publishBasic(title,content,this.getNotificationId(day.dayID));}}批量检查asynccheckAndSendReminders():Promisevoid{constneedReminderthis.getDaysNeedReminder();consthasPermissionawaitNotificationUtil.checkPermission();if(!hasPermission)return;for(constdayofneedReminder){consttitleday.isToday()?今天${day.title}:即将到来${day.title};constcontentday.getDisplayText();awaitNotificationUtil.publishBasic(title,content,this.getNotificationId(day.dayID));}}通知标题策略场景标题内容今天“今天妈妈生日”“就是今天”即将到来“即将到来妈妈生日”“还有 3 天”十、生命周期集成onCreateasynconCreate(want:Want,launchParam:AbilityConstant.LaunchParam):Promisevoid{PreferenceUtil.init(this.context);ImportantDayManager.getInstance().init();consthasPermissionawaitNotificationUtil.checkPermission();if(hasPermission){awaitImportantDayManager.getInstance().checkAndSendReminders();}}onForegroundonForeground():void{ImportantDayManager.getInstance().checkAndSendReminders();}设计考量每次应用回到前台都检查提醒确保用户不会错过在应用后台期间到期的提醒。十一、总结NotificationUtilImportantDayManager构成了完整的通知提醒系统权限先行所有通知操作前检查权限WantAgent 跳转点击通知自动打开应用稳定 ID基于哈希的通知 ID 确保正确管理生命周期集成启动和前台切换时自动检查安全可靠所有操作都有 try-catch 保护渠道选择使用社交通信渠道确保高优先级这套通知系统虽然代码量不大但覆盖了权限、发布、取消、跳转、角标等通知开发的全链路。