OpenHarmony 通知消息 Notification 完整开发(API Version23 + 适配版)
摘要
Notification 通知模块用于在系统状态栏弹出消息提醒,包含普通文本通知、多行详情通知、大图片横幅通知、常驻后台通知,适用于消息推送、定时提醒、任务进度、离线消息等场景。API Version23 重构通知渠道管理、权限校验、通知生命周期、点击跳转 Want 逻辑,修复低版本通知无法弹出、点击无响应、重复推送、后台进程通知消失、渠道删除残留等兼容缺陷。旧项目升级 API23 后常出现:发送通知无任何状态栏提示、点击通知无法跳转页面、退出应用通知自动清除、多次推送产生大量重复通知、无通知权限直接报错闪退等问题。本文基于 DevEco Studio 适配 OpenHarmony API23 及以上版本,封装全局通知工具类,实现普通文本通知、大图通知、常驻通知、通知点击路由跳转四大核心能力,搭配消息提醒、后台定时任务两套实战页面提供完整可运行代码,输出通知权限、渠道创建、资源销毁规范,汇总版本升级兼容故障解决方案,为鸿蒙消息提醒功能开发提供标准化实操模板。
关键词
OpenHarmony;ArkUI;API Version23;Notification;系统通知;消息推送;通知渠道;通知点击跳转
一、引言
1.1 通知开发背景
聊天消息、日程提醒、下载进度、离线推送都依赖系统通知能力,通知独立于应用页面,锁屏、应用切后台状态下仍可展示在状态栏。系统对通知实行渠道分组管理,同类型消息共用一个渠道,用户可在系统设置单独关闭某一类通知。 OpenHarmony API Version23 针对 Notification 底层调度引擎完成全面升级,核心变更点:
- 强制所有通知必须先创建 NotificationChannel 渠道,无渠道发送直接失败;
- 重构通知动态权限校验逻辑,未授予通知权限拦截推送并友好提示;
- 标准化点击通知 Want 跳转规则,区分打开页面、跳转 Ability;
- 优化通知缓存队列,限制同一渠道短时间重复推送频率,避免刷屏;
- 新增常驻通知(ONGOING)生命周期管控,退出应用不会自动移除;
- 修复通知 ID 复用覆盖原有通知、渠道删除后无法重建的 bug。
大量 API9~11 旧项目升级后,调用推送接口状态栏无消息,根源是缺少渠道创建逻辑、未申请通知动态权限,因此掌握 API23 标准通知封装规范是消息提醒类功能必备技能。
1.2 开发环境与测试场景
开发工具:DevEco Studio 5.0 及以上 适配系统:OpenHarmony API Version23、HarmonyOS NEXT 导入模块:@ohos.notification、@ohos.notificationManager 前置权限:动态通知权限 ohos.permission.NOTIFICATION_AGENT 测试场景:普通文字消息通知、大图预览通知、常驻后台提醒、点击通知跳转指定页面、清除全部通知、删除单条通知
二、API23+ Notification 通知核心 API 与版本变更说明
2.1 核心模块导入
ets
import notificationManager from '@ohos.notificationManager'
import notification from '@ohos.notification'
2.2 通知渠道创建(API23 强制前置)
ets
// 创建渠道配置
const channel: notification.NotificationChannel = {
id: "msg_channel",
name: "消息通知",
description: "应用普通消息提醒",
importance: notification.NotificationImportance.LEVEL_3
}
await notificationManager.createChannel(channel)
importance 优先级等级:
- LEVEL_0:无提醒,静默存储
- LEVEL_3:状态栏展示 + 提示音(常规消息推荐)
- LEVEL_4:横幅弹窗强提醒
2.3 通知基础推送结构
- NotificationRequest:通知载体,包含 id、渠道 ID、内容、点击跳转 want
- NotificationContent:通知内容,支持普通文本、大图、多行文本
- Want:点击通知后跳转页面路由参数
2.4 常用控制 API
- notificationManager.publish (request):推送通知
- notificationManager.cancel (id):根据 ID 删除单条通知
- notificationManager.cancelAll ():清空本应用全部通知
- notificationManager.getChannels ():获取已创建渠道列表
2.5 API23 废弃与强制约束
- 废弃无渠道直接推送通知,必须提前创建对应 channel;
- 通知属于动态敏感权限,页面调用前必须申请 NOTIFICATION_AGENT;
- 相同 channel + 相同 id 会覆盖旧通知,不同 id 生成多条独立消息;
- 常驻 ONGOING 通知无法被用户手动清除,仅代码可 cancel;
- 后台无进程状态下部分设备限制普通通知推送,常驻通知不受限。
三、API23 标准基础示例代码
3.1 创建通知渠道 + 普通文本通知推送
ets
import notificationManager from '@ohos.notificationManager'
import notification from '@ohos.notification'
import Want from '@ohos.app.ability.Want'
import router from '@ohos.router'
async function createMsgChannel() {
const channel: notification.NotificationChannel = {
id: "msg_default",
name: "通用消息",
description: "应用各类消息推送提醒",
importance: notification.NotificationImportance.LEVEL_3
}
await notificationManager.createChannel(channel)
}
async function sendSimpleNotify(id: number, title: string, content: string) {
await createMsgChannel()
// 点击跳转首页Want
let want: Want = {
bundleName: getContext(this).bundleName,
abilityName: "EntryAbility",
uri: "pages/index/index"
}
const notifyRequest: notification.NotificationRequest = {
id: id,
channelId: "msg_default",
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: { title: title, text: content }
},
want: want
}
await notificationManager.publish(notifyRequest)
}
3.2 清除指定 ID 通知
ets
async function cancelSingleNotify(notifyId: number) {
await notificationManager.cancel(notifyId)
}
async function clearAllNotify() {
await notificationManager.cancelAll()
}
四、两大业务完整实战案例(全兼容 API23)
4.1 实战一:全局通知工具类封装(utils/notify_util.ets)
ets
import notificationManager from '@ohos.notificationManager'
import notification from '@ohos.notification'
import Want from '@ohos.app.ability.Want'
import common from '@ohos.app.ability.common'
import promptAction from '@ohos.promptAction'
import PermissionUtil, { PERMISSION } from './permission_util'
// 通知渠道常量统一管理
export const NOTIFY_CHANNEL = {
MSG: "channel_msg",
TASK: "channel_task"
}
class NotifyUtil {
private static instance: NotifyUtil
private ctx: common.UIAbilityContext | null = null
static getInstance(): NotifyUtil {
if (!NotifyUtil.instance) {
NotifyUtil.instance = new NotifyUtil()
}
return NotifyUtil.instance
}
setContext(context: common.UIAbilityContext) {
this.ctx = context
}
// 初始化消息通知渠道
private async createMsgChannel() {
const channel: notification.NotificationChannel = {
id: NOTIFY_CHANNEL.MSG,
name: "消息通知",
description: "聊天、资讯类消息提醒",
importance: notification.NotificationImportance.LEVEL_3
}
await notificationManager.createChannel(channel)
}
// 初始化后台任务常驻渠道
private async createTaskChannel() {
const channel: notification.NotificationChannel = {
id: NOTIFY_CHANNEL.TASK,
name: "后台任务",
description: "下载、同步常驻提醒",
importance: notification.NotificationImportance.LEVEL_2
}
await notificationManager.createChannel(channel)
}
// 推送普通文本通知
async sendBasicNotify(notifyId: number, title: string, text: string, pageUrl: string) {
if (!this.ctx) return
// 前置校验通知权限
const hasPerm = PermissionUtil.checkSingle("ohos.permission.NOTIFICATION_AGENT")
if (!hasPerm) {
promptAction.showToast({ message: "未开启通知权限,无法推送消息" })
return
}
await this.createMsgChannel()
// 构建跳转Want
const want: Want = {
bundleName: this.ctx.bundleName,
abilityName: "EntryAbility",
uri: pageUrl
}
const request: notification.NotificationRequest = {
id: notifyId,
channelId: NOTIFY_CHANNEL.MSG,
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: { title, text }
},
want: want
}
try {
await notificationManager.publish(request)
promptAction.showToast({ message: "通知已发送至状态栏" })
} catch (err) {
promptAction.showToast({ message: "通知推送失败" })
console.error("推送通知异常", err)
}
}
// 推送常驻后台通知(无法手动清除)
async sendOngoingTaskNotify(notifyId: number, title: string, text: string) {
if (!this.ctx) return
const hasPerm = PermissionUtil.checkSingle("ohos.permission.NOTIFICATION_AGENT")
if (!hasPerm) return
await this.createTaskChannel()
const request: notification.NotificationRequest = {
id: notifyId,
channelId: NOTIFY_CHANNEL.TASK,
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: { title, text }
},
ongoing: true // 标记为常驻通知
}
await notificationManager.publish(request)
}
// 删除单条通知
async cancelNotify(notifyId: number) {
await notificationManager.cancel(notifyId)
promptAction.showToast({ message: "已移除该条通知" })
}
// 清空全部通知
async clearAll() {
await notificationManager.cancelAll()
promptAction.showToast({ message: "已清空所有通知" })
}
}
export default NotifyUtil.getInstance()
4.2 实战二:通知推送演示页面(普通通知 + 常驻任务通知)
ets
import NotifyUtil from '../utils/notify_util'
import PermissionUtil from '../utils/permission_util'
@Entry
@Component
struct NotificationPage {
notifyId: number = 1001
taskNotifyId: number = 9001
aboutToAppear() {
// 绑定页面上下文
const ctx = getContext(this)
NotifyUtil.setContext(ctx)
PermissionUtil.setContext(ctx)
}
// 发送普通资讯通知,点击跳转首页
async sendMsgNotify() {
await NotifyUtil.sendBasicNotify(
this.notifyId++,
"新资讯推送",
"今日鸿蒙技术更新,点击查看详情",
"pages/index/index"
)
}
// 发送常驻后台同步通知
async sendSyncTaskNotify() {
await NotifyUtil.sendOngoingTaskNotify(
this.taskNotifyId,
"文件同步中",
"后台正在同步本地笔记数据"
)
}
// 清除常驻任务通知
async removeTaskNotify() {
await NotifyUtil.cancelNotify(this.taskNotifyId)
}
// 清空全部通知
async clearAllNotify() {
await NotifyUtil.clearAll()
}
build() {
Column({ space: 20 }) {
Text("系统通知Notification演示")
.fontSize(22)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Button("推送普通资讯通知")
.width(300)
.height(46)
.backgroundColor("#007DFF")
.onClick(async () => await this.sendMsgNotify())
Button("推送常驻后台同步通知")
.width(300)
.height(46)
.backgroundColor("#009966")
.onClick(async () => await this.sendSyncTaskNotify())
Button("移除常驻同步通知")
.width(300)
.height(46)
.backgroundColor("#ff9500")
.onClick(async () => await this.removeTaskNotify())
Button("清空全部应用通知")
.width(300)
.height(46)
.backgroundColor("#f56c6c")
.onClick(async () => await this.clearAllNotify())
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
.padding(20)
.backgroundColor("#F5F5F5")
}
}
五、API23+ 通知适配与性能优化规范
5.1 渠道管理规范
- 按业务类型拆分渠道:消息、后台任务、活动推送分开创建;
- 页面推送前自动检测并创建渠道,无需手动提前执行;
- 同一渠道相同 ID 通知会覆盖,不同 ID 独立多条展示。
5.2 权限交互规范
- 推送通知前校验 NOTIFICATION_AGENT 动态权限,无权限阻断推送并提示;
- 应用首次使用通知功能主动申请权限,不静默失败;
- 用户永久拒绝权限时提示前往系统设置开启通知。
5.3 常驻通知业务规范
- 下载、同步、录音等后台服务使用 ongoing 常驻通知;
- 常驻通知用户无法手动清除,业务完成必须代码调用 cancel 删除;
- 普通聊天、资讯消息不使用常驻类型,允许用户上滑清除。
5.4 跳转 Want 规范
- Want 必须填写当前应用 bundleName 与 EntryAbility;
- uri 填写目标页面路由地址,点击通知自动跳转对应业务页面;
- 需要携带参数可在 want.parameters 中追加自定义键值。
六、API23 升级高频兼容问题与解决方案
问题 1:调用推送接口,状态栏完全不显示通知 解决:1. 创建对应 NotificationChannel 渠道;2. 授予 NOTIFICATION_AGENT 通知权限;3. 渠道 importance 等级≥LEVEL_2。
问题 2:多次推送通知只会显示一条,新消息覆盖旧消息 解决:每次推送使用不同 notifyId,相同 ID 会覆盖同渠道旧通知。
问题 3:点击通知无任何页面跳转 解决:完整配置 want 的 bundleName、abilityName、uri 页面路由。
问题 4:退出应用后常驻通知自动消失 解决:推送时设置 ongoing:true 标记为后台常驻通知。
问题 5:升级 API23 旧代码直接推送报错 解决:全部补充渠道创建逻辑,API9 及以下无强制渠道要求,API23 必须创建。
问题 6:短时间连续推送多条通知系统拦截不展示 解决:拆分不同 channel 或增加推送间隔,避免高频刷屏触发系统限流。
七、总结
Notification 系统通知是鸿蒙应用消息提醒标准实现方案,API Version23 强制引入通知渠道前置创建、动态权限校验机制,统一通知内容、点击跳转、常驻任务的标准化配置,彻底解决旧版无消息、点击失效、通知丢失等核心兼容问题。项目封装全局通知工具类,拆分消息、任务双渠道,提供普通通知、常驻后台通知、清除通知全套方法,搭配权限前置校验,适配资讯推送、后台同步、日程提醒等主流业务场景。
更多推荐
所有评论(0)