鸿蒙掌上驾考宝典应用开发49:鸿蒙推送服务——PushUtils 与通知管理
·
第49篇:鸿蒙推送服务——PushUtils 与通知管理
一、引言
推送服务是应用主动触达用户的重要渠道,用于发送考试提醒、学习通知、模考成绩等消息。DriverLicenseExam 项目通过鸿蒙推送服务实现了消息推送功能,包括通知权限申请、消息构建、推送发送、点击处理等完整流程。本文将深入解析推送服务的实现。
二、推送服务架构
2.1 推送流程
应用启动
│
▼
申请通知权限(requestEnableNotification)
│
▼
权限已授权?
├── 否 → 不发送推送
│
└── 是 → 构建推送消息
│
▼
PushUtils.randomPushMessage()
│
▼
系统通知栏显示
│
▼
用户点击通知
│
▼
EntryAbility.onNewWant()
│
▼
解析参数 → 跳转到指定页面
2.2 推送相关文件
commons/commonLib/src/main/ets/push/
├── Model.ets ← 推送数据模型
└── PushUtils.ets ← 推送工具类
三、推送权限管理
3.1 通知权限申请
在 EntryAbility 的 onWindowStageCreate 中申请通知权限:
// EntryAbility.ets
notificationManager.requestEnableNotification(this.context).then(() => {
hilog.info(0x0000, 'testTag', '[ANS] requestEnableNotification success');
}).catch((err: BusinessError) => {
hilog.error(0x0000, 'testTag',
'[ANS] requestEnableNotification failed, code: ' + err.code + ', message: ' + err.message);
});
3.2 权限检查
在发送推送前检查通知权限是否已开启:
// MainEntry.ets
sendPushNotice() {
const isOn = notificationManager.isNotificationEnabledSync();
if (isOn) {
this.sendPushMessage();
}
}
isNotificationEnabledSync() 是同步方法,快速检查通知权限状态,避免在未授权时进行不必要的推送操作。
四、推送消息模型
4.1 推送参数定义
// PushUtils.ets
export interface PushActionParams {
picVideoUrl: string; // 图片/视频 URL(用于富媒体通知)
title: string; // 推送标题
id: string; // 推送 ID(用于去重和追踪)
}
4.2 推送消息构建
// PushUtils.ets
export class PushUtils {
// 构建推送通知请求
static buildNotificationRequest(params: PushActionParams): notificationManager.NotificationRequest {
let notificationRequest: notificationManager.NotificationRequest = {
id: parseInt(params.id) || 0,
content: {
contentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: params.title,
text: '点击查看详情',
additionalText: params.picVideoUrl || '',
},
},
// 点击通知后携带的参数
wantAgent: {
// 通过 Want 传递参数到 Ability
want: {
deviceId: '',
bundleName: 'qcjk.1.xxxxxx',
abilityName: 'EntryAbility',
parameters: {
params: JSON.stringify({
message: 'practiceView',
title: params.title,
id: params.id,
}),
},
},
},
};
return notificationRequest;
}
}
五、推送消息发送
5.1 随机推送消息
// PushUtils.ets
static randomPushMessage(params: PushActionParams, context: Context) {
// 随机决定是否发送推送
if (Math.random() > 0.3) { // 30% 概率发送
return;
}
const notificationRequest = this.buildNotificationRequest(params);
notificationManager.publish(notificationRequest)
.then(() => {
Logger.info('PushUtils', 'Push notification published successfully');
})
.catch((err: BusinessError) => {
Logger.error('PushUtils', 'Failed to publish notification: ' + err.message);
});
}
5.2 在主页面触发推送
// MainEntry.ets
aboutToAppear(): void {
this.bottomRectHeight = AppStorage.get('bottomRectHeight') || 0;
this.vm.navStack.pushPathByName('splashPage', true);
this.sendPushNotice(); // 启动时尝试发送推送
this.updateForm(0);
}
sendPushMessage() {
let pushArticle: PushActionParams = {
picVideoUrl: '',
title: '驾考模板',
id: '3445749589458989',
};
PushUtils.randomPushMessage(pushArticle, this.getUIContext().getHostContext() as Context);
}
六、推送点击处理
6.1 Want 参数解析
当用户点击通知栏的推送消息时,系统会通过 Want 参数将消息传递到 Ability:
// EntryAbility.ets - 处理推送点击
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
this.setLightOrDarkMode(this.context);
Logger.info(TAG, 'Ability onNewWant');
if (want.parameters && want.parameters.params) {
let param: ESObject = {};
try {
param = JSON.parse(want.parameters.params as string);
} catch (e) {
Logger.error(TAG, 'Failed to parse push params: ' + JSON.stringify(e));
}
// 根据推送消息类型跳转到不同页面
if (param.message === 'practiceView') {
// 跳转到模拟考试
const examService = ExamService.instance(this.context as Context);
const par: ROUTE_PARAM = {
title: '模拟考试',
type: EXAM_MANAGER_TYPE.mock_exam,
examManager: examService.getMockExamManager('模拟考试'),
};
CommonModel.instance.navStack.replacePathByName('practiceView', par);
} else if (param.message === 'orderPractice') {
// 跳转到顺序练习
const param: ROUTE_PARAM = {
title: '顺序练习',
type: EXAM_MANAGER_TYPE.sequence,
};
CommonModel.instance.navStack.replacePathByName('practiceView', param);
}
}
WantUtils.handlePushWant(want);
this.shareServiceImpl.handleWant(want, this.context);
}
6.2 冷启动与热启动处理
推送点击有两种场景:
- 冷启动:应用未运行,点击通知启动应用 → 在
onCreate中处理 - 热启动:应用已在后台,点击通知唤醒应用 → 在
onNewWant中处理
// 冷启动处理
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
Logger.info(TAG, 'Ability onCreate');
WantUtils.handlePushCall(want); // 处理冷启动推送
this.shareServiceImpl.handleWant(want, this.context);
}
// 热启动处理
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 处理热启动推送
WantUtils.handlePushWant(want);
this.shareServiceImpl.handleWant(want, this.context);
}
七、推送功能的扩展
7.1 本地通知
除了服务器推送,应用还可以发送本地通知,例如模拟考试完成后的成绩通知:
static sendLocalNotification(title: string, content: string, context: Context) {
const notificationRequest: notificationManager.NotificationRequest = {
id: Date.now(),
content: {
contentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: title,
text: content,
},
},
};
notificationManager.publish(notificationRequest)
.then(() => Logger.info('PushUtils', 'Local notification published'))
.catch((err) => Logger.error('PushUtils', 'Failed to publish: ' + err.message));
}
7.2 推送分类
不同类型的推送可以使用不同的通知渠道:
// 通知渠道分类
const NOTIFICATION_CHANNELS = {
EXAM_REMINDER: { id: 'exam_reminder', name: '考试提醒', importance: 4 },
STUDY_TIP: { id: 'study_tip', name: '学习建议', importance: 3 },
PROMOTION: { id: 'promotion', name: '活动推广', importance: 2 },
};
八、总结
推送服务是应用与用户保持互动的重要渠道。DriverLicenseExam 项目通过完整的推送实现展示了:
- 权限管理:通知权限的申请和检查
- 消息构建:NotificationRequest 的消息结构
- 推送发送:通过 notificationManager.publish 发送
- 点击处理:通过 Want 参数传递,支持冷启动和热启动
- 页面跳转:根据推送类型跳转到不同页面
关键源码文件:
commons/commonLib/src/main/ets/push/PushUtils.ets— 推送工具类commons/commonLib/src/main/ets/push/Model.ets— 推送数据模型products/entry/src/main/ets/entryability/EntryAbility.ets— 推送点击处理products/entry/src/main/ets/pages/MainEntry.ets— 推送触发入口products/entry/src/main/ets/util/WantUtils.ets— Want 参数处理工具
更多推荐





所有评论(0)