鸿蒙Notification Kit通知服务开发快速指南
一、Notification Kit概述
Notification Kit为开发者提供本地通知发布能力,可以在应用运行时向用户推送通知,包括文本、进度条、角标等多种样式。
1.1 核心能力
- ✅ 发布文本类型通知(普通文本、多行文本)
- ✅ 发布进度条通知
- ✅ 管理应用角标
- ✅ 取消和查询通知
- ✅ 请求用户授权
1.2 业务流程
sequenceDiagram
participant App as 应用
participant NM as NotificationManager
participant User as 用户
participant NC as 通知中心
App->>NM: 请求授权
NM->>User: 弹窗询问
User->>NM: 允许/拒绝
NM-->>App: 授权结果
App->>NM: publish(通知)
NM->>NC: 展示通知
NC->>User: 显示通知
1.3 约束限制
| 限制项 | 说明 |
|---|---|
| 留存数量 | 单个应用最多24条 |
| 通知大小 | 不超过200KB |
| 发布频次 | 单应用≤10条/秒 |
| 更新频次 | 单应用≤20条/秒 |
二、请求通知授权
应用首次发布通知前必须获取用户授权。
2.1 授权流程
typescript
import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
class NotificationAuth {
async requestPermission(context: common.UIAbilityContext) {
try {
// 1. 检查是否已授权
let isEnabled = await notificationManager.isNotificationEnabled();
if (!isEnabled) {
// 2. 请求授权(首次会弹窗)
await notificationManager.requestEnableNotification(context);
console.info('通知授权成功');
} else {
console.info('已获得通知授权');
}
} catch (err) {
let error = err as BusinessError;
if (error.code === 1600004) {
console.error('用户拒绝授权');
// 3. 可选:拉起设置页面再次请求
this.openSettings(context);
} else {
console.error(`授权失败: ${error.message}`);
}
}
}
async openSettings(context: common.UIAbilityContext) {
try {
await notificationManager.openNotificationSettings(context);
} catch (err) {
let error = err as BusinessError;
console.error(`打开设置失败: ${error.message}`);
}
}
}
三、发布文本通知
3.1 普通文本通知
typescript
import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';
async function publishTextNotification() {
let notificationRequest: notificationManager.NotificationRequest = {
id: 1,
content: {
notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: '新消息',
text: '您有一条新消息',
additionalText: '刚刚'
}
}
};
try {
await notificationManager.publish(notificationRequest);
console.info('通知发布成功');
} catch (err) {
let error = err as BusinessError;
console.error(`通知发布失败: ${error.message}`);
}
}
3.2 多行文本通知
typescript
async function publishMultiLineNotification() {
let notificationRequest: notificationManager.NotificationRequest = {
id: 2,
content: {
notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_MULTILINE,
multiLine: {
title: '会议提醒',
text: '团队会议',
briefText: '3条新通知',
longTitle: '今日会议安排',
lines: [
'上午10:00 - 产品评审会',
'下午14:00 - 技术分享会',
'下午16:00 - 周报会议'
]
}
}
};
try {
await notificationManager.publish(notificationRequest);
} catch (err) {
let error = err as BusinessError;
console.error(`发布失败: ${error.message}`);
}
}
四、进度条通知
4.1 下载进度示例
typescript
class DownloadNotification {
private notificationId = 100;
async showDownloadProgress(fileName: string, progress: number) {
let notificationRequest: notificationManager.NotificationRequest = {
id: this.notificationId,
content: {
notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: `下载中: ${fileName}`,
text: `进度: ${progress}%`,
additionalText: ''
}
},
// 进度条配置
template: {
name: 'downloadTemplate',
data: {
progressValue: progress,
progressMaxValue: 100
}
}
};
try {
await notificationManager.publish(notificationRequest);
} catch (err) {
let error = err as BusinessError;
console.error(`更新进度失败: ${error.message}`);
}
}
async completeDownload(fileName: string) {
let notificationRequest: notificationManager.NotificationRequest = {
id: this.notificationId,
content: {
notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: '下载完成',
text: fileName,
additionalText: '点击查看'
}
}
};
await notificationManager.publish(notificationRequest);
}
async cancelDownload() {
await notificationManager.cancel(this.notificationId);
}
}
// 使用示例
let downloader = new DownloadNotification();
// 模拟下载进度
for (let i = 0; i <= 100; i += 10) {
await downloader.showDownloadProgress('document.pdf', i);
await new Promise(resolve => setTimeout(resolve, 500));
}
await downloader.completeDownload('document.pdf');
五、通知角标管理
5.1 设置和更新角标
typescript
class BadgeManager {
async setBadgeNumber(count: number) {
let notificationRequest: notificationManager.NotificationRequest = {
id: 1,
content: {
notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: '新消息',
text: `您有${count}条未读消息`
}
},
// 设置角标数字
badgeNumber: count
};
try {
await notificationManager.publish(notificationRequest);
} catch (err) {
let error = err as BusinessError;
console.error(`设置角标失败: ${error.message}`);
}
}
async clearBadge() {
// 取消所有通知即可清除角标
await notificationManager.cancelAll();
}
}
六、通知管理操作
6.1 取消通知
typescript
class NotificationControl {
// 取消指定通知
async cancelNotification(id: number) {
try {
await notificationManager.cancel(id);
console.info(`通知${id}已取消`);
} catch (err) {
let error = err as BusinessError;
console.error(`取消失败: ${error.message}`);
}
}
// 取消所有通知
async cancelAllNotifications() {
try {
await notificationManager.cancelAll();
console.info('所有通知已清除');
} catch (err) {
let error = err as BusinessError;
console.error(`清除失败: ${error.message}`);
}
}
// 查询活跃通知
async getActiveNotifications() {
try {
let notifications = await notificationManager.getActiveNotifications();
console.info(`当前有${notifications.length}条活跃通知`);
return notifications;
} catch (err) {
let error = err as BusinessError;
console.error(`查询失败: ${error.message}`);
return [];
}
}
}
七、实战示例:消息通知管理器
7.1 完整通知管理器
typescript
import { notificationManager } from '@kit.NotificationKit';
import { wantAgent, WantAgent } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
export enum NotificationType {
MESSAGE = 'message',
SYSTEM = 'system',
PROGRESS = 'progress'
}
export interface NotificationConfig {
id: number;
type: NotificationType;
title: string;
content: string;
badgeNumber?: number;
}
export class NotificationManager {
private static instance: NotificationManager;
private isAuthorized: boolean = false;
private constructor() {}
static getInstance(): NotificationManager {
if (!NotificationManager.instance) {
NotificationManager.instance = new NotificationManager();
}
return NotificationManager.instance;
}
// 初始化并请求授权
async init(context: common.UIAbilityContext): Promise<boolean> {
try {
this.isAuthorized = await notificationManager.isNotificationEnabled();
if (!this.isAuthorized) {
await notificationManager.requestEnableNotification(context);
this.isAuthorized = true;
}
return this.isAuthorized;
} catch (err) {
let error = err as BusinessError;
console.error(`初始化失败: ${error.message}`);
return false;
}
}
// 发布普通通知
async publishNotification(config: NotificationConfig) {
if (!this.isAuthorized) {
console.error('未获得通知授权');
return;
}
let notificationRequest: notificationManager.NotificationRequest = {
id: config.id,
content: {
notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: config.title,
text: config.content
}
}
};
if (config.badgeNumber !== undefined) {
notificationRequest.badgeNumber = config.badgeNumber;
}
try {
await notificationManager.publish(notificationRequest);
console.info(`通知${config.id}发布成功`);
} catch (err) {
let error = err as BusinessError;
console.error(`发布失败: ${error.message}`);
}
}
// 发布可点击通知
async publishClickableNotification(
config: NotificationConfig,
context: common.UIAbilityContext,
targetAbility: string
) {
try {
// 创建WantAgent
let wantAgentInfo: wantAgent.WantAgentInfo = {
wants: [
{
bundleName: context.abilityInfo.bundleName,
abilityName: targetAbility
}
],
requestCode: 0,
operationType: wantAgent.OperationType.START_ABILITY,
wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
};
let wantAgentObj = await wantAgent.getWantAgent(wantAgentInfo);
let notificationRequest: notificationManager.NotificationRequest = {
id: config.id,
content: {
notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: config.title,
text: config.content
}
},
wantAgent: wantAgentObj
};
await notificationManager.publish(notificationRequest);
console.info('可点击通知发布成功');
} catch (err) {
let error = err as BusinessError;
console.error(`发布失败: ${error.message}`);
}
}
// 更新通知
async updateNotification(config: NotificationConfig) {
// 更新通知只需使用相同ID重新发布
await this.publishNotification(config);
}
// 取消通知
async cancelNotification(id: number) {
try {
await notificationManager.cancel(id);
} catch (err) {
let error = err as BusinessError;
console.error(`取消失败: ${error.message}`);
}
}
// 清除所有通知
async cancelAll() {
try {
await notificationManager.cancelAll();
} catch (err) {
let error = err as BusinessError;
console.error(`清除失败: ${error.message}`);
}
}
// 获取活跃通知数量
async getActiveCount(): Promise<number> {
try {
let notifications = await notificationManager.getActiveNotifications();
return notifications.length;
} catch (err) {
return 0;
}
}
}
7.2 使用示例页面
typescript
import { NotificationManager, NotificationType } from '../model/NotificationManager';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct NotificationDemo {
private notificationMgr: NotificationManager = NotificationManager.getInstance();
private context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
@State messageCount: number = 0;
@State activeNotifications: number = 0;
async aboutToAppear() {
await this.notificationMgr.init(this.context);
this.updateActiveCount();
}
async updateActiveCount() {
this.activeNotifications = await this.notificationMgr.getActiveCount();
}
async sendTextNotification() {
this.messageCount++;
await this.notificationMgr.publishNotification({
id: 1,
type: NotificationType.MESSAGE,
title: '新消息',
content: `您有${this.messageCount}条新消息`,
badgeNumber: this.messageCount
});
this.updateActiveCount();
}
async sendClickableNotification() {
await this.notificationMgr.publishClickableNotification(
{
id: 2,
type: NotificationType.SYSTEM,
title: '系统通知',
content: '点击查看详情'
},
this.context,
'EntryAbility'
);
this.updateActiveCount();
}
async clearNotifications() {
await this.notificationMgr.cancelAll();
this.messageCount = 0;
this.activeNotifications = 0;
}
build() {
Column({ space: 20 }) {
// 标题
Text('通知服务演示')
.fontSize(24)
.fontWeight(FontWeight.Bold)
// 状态显示
Row({ space: 20 }) {
Text(`未读消息: ${this.messageCount}`)
.fontSize(16)
Text(`活跃通知: ${this.activeNotifications}`)
.fontSize(16)
}
.padding(15)
.backgroundColor('#f0f0f0')
.borderRadius(8)
.width('90%')
// 操作按钮
Column({ space: 15 }) {
Button('发送文本通知')
.width('100%')
.onClick(() => this.sendTextNotification())
Button('发送可点击通知')
.width('100%')
.onClick(() => this.sendClickableNotification())
Button('发送多行通知')
.width('100%')
.onClick(async () => {
let notificationRequest: notificationManager.NotificationRequest = {
id: 3,
content: {
notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_MULTILINE,
multiLine: {
title: '待办事项',
text: '今日待办',
lines: [
'完成项目文档',
'参加团队会议',
'代码review'
]
}
}
};
await notificationManager.publish(notificationRequest);
this.updateActiveCount();
})
Button('清除所有通知')
.width('100%')
.backgroundColor('#ff6b6b')
.onClick(() => this.clearNotifications())
}
.width('90%')
}
.width('100%')
.height('100%')
.padding(20)
}
}
八、最佳实践
8.1 通知频率控制
typescript
class NotificationRateLimiter {
private lastPublishTime: number = 0;
private minInterval: number = 1000; // 最小间隔1秒
async publishWithLimit(request: notificationManager.NotificationRequest) {
let now = Date.now();
if (now - this.lastPublishTime < this.minInterval) {
console.warn('发布频率过高,请稍后再试');
return false;
}
try {
await notificationManager.publish(request);
this.lastPublishTime = now;
return true;
} catch (err) {
return false;
}
}
}
8.2 通知分组管理
typescript
class NotificationGroup {
private groupedNotifications: Map<string, number[]> = new Map();
async publishToGroup(group: string, request: notificationManager.NotificationRequest) {
await notificationManager.publish(request);
if (!this.groupedNotifications.has(group)) {
this.groupedNotifications.set(group, []);
}
this.groupedNotifications.get(group)?.push(request.id);
}
async cancelGroup(group: string) {
let ids = this.groupedNotifications.get(group);
if (ids) {
for (let id of ids) {
await notificationManager.cancel(id);
}
this.groupedNotifications.delete(group);
}
}
}
8.3 错误处理
typescript
class RobustNotification {
async publishWithRetry(
request: notificationManager.NotificationRequest,
maxRetries: number = 3
): Promise<boolean> {
for (let i = 0; i < maxRetries; i++) {
try {
await notificationManager.publish(request);
return true;
} catch (err) {
let error = err as BusinessError;
console.error(`第${i + 1}次发布失败: ${error.message}`);
if (i < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
return false;
}
}
九、总结
本文介绍了HarmonyOS通知服务开发的核心内容:
| 功能 | API | 使用场景 |
|---|---|---|
| 请求授权 | requestEnableNotification | 首次使用通知 |
| 文本通知 | NOTIFICATION_CONTENT_BASIC_TEXT | 普通消息提醒 |
| 多行通知 | NOTIFICATION_CONTENT_MULTILINE | 列表消息 |
| 进度通知 | template配置 | 下载/上传进度 |
| 通知角标 | badgeNumber | 未读消息数 |
| 可点击通知 | wantAgent | 跳转到详情页 |
开发要点:
- ✅ 首次使用必须请求授权
- ✅ 控制通知发布频率
- ✅ 及时取消无用通知
- ✅ 合理使用通知ID管理
- ✅ 做好错误处理和重试
通过本文学习,您应该能够:
- 熟练请求和管理通知授权
- 发布各种类型的通知
- 实现进度类通知
- 管理通知角标
- 开发完整的通知管理系统