HarmonyOS应用开发实战:猫猫大作战-PushKit 的接收与处理
·


前言
PushKit 是 HarmonyOS 的远程推送服务,支持服务端向用户设备发送推送消息。对于游戏应用,远程推送可用于活动通知(“周末双倍积分!”)、好友邀请(“你的好友超过了你的得分!”)、以及流失召回(“猫咪们想念你回来合并!”)。
本文以「猫猫大作战」的推送集成为锚点,讲解 PushKit 的完整使用流程,包括推送权限申请、接收推送、消息解析、点击跳转、以及推送策略最佳实践。
提示:本系列不讲 ArkTS 基础语法与环境搭建。本篇是阶段五第 153 篇。
一、PushKit 基础概念
1.1 推送架构
┌──────────┐ ┌─────────────┐ ┌──────────┐
│ 服务端 │────►│ 华为推送服务 │────►│ 用户设备 │
│ (AGC) │ │ (PushKit) │ │ (App) │
└──────────┘ └─────────────┘ └──────────┘
│ │
│ 发送推送请求 │ on('receive') 回调
│ JSON 格式 │ 弹通知栏消息
└──────────────────────────────────────┘
1.2 推送数据类型
// 推送消息的 JSON 结构示例
interface PushMessage {
type: 'activity' | 'reminder' | 'invite' | 'notice';
title: string;
body: string;
data?: Record<string, string>; // 自定义数据
action?: string; // 点击后的跳转路由
}
提示:HarmonyOS 推送消息体最大 4KB,结构化数据放在
data字段,展示文本放在title/body。
二、推送权限与配置
2.1 module.json5 权限声明
// entry/src/main/module.json5
{
module: {
requestPermissions: [
{
name: 'ohos.permission.PUSH',
reason: '$string:push_permission_reason',
}
],
// ...
}
}
2.2 运行时权限申请
import { abilityAccessCtrl } from '@kit.AbilityKit';
async function requestPushPermission(context: common.UIAbilityContext): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager();
try {
const result = await atManager.requestPermissionsFromUser(context, [
'ohos.permission.PUSH'
]);
return result.authResults[0] === 0; // 0 表示授权
} catch (err) {
console.error(`推送权限申请失败: ${err.message}`);
return false;
}
}
三、接收推送消息
3.1 注册推送监听
import { pushService } from '@kit.PushKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct GameApp {
private TAG = 'PushKit';
private DOMAIN = 0xFF00;
aboutToAppear() {
this.initPush();
}
initPush() {
// 注册推送接收回调
pushService.on('receive', (data: string) => {
hilog.info(this.DOMAIN, this.TAG, `收到推送消息: ${data}`);
this.handlePushMessage(data);
});
// 注册推送点击回调
pushService.on('click', (data: string) => {
hilog.info(this.DOMAIN, this.TAG, `推送被点击: ${data}`);
this.handlePushClick(data);
});
}
handlePushMessage(data: string) {
try {
const msg: PushMessage = JSON.parse(data);
switch (msg.type) {
case 'activity':
this.showActivityBanner(msg.title, msg.body);
break;
case 'reminder':
// 系统已弹通知栏,应用无需额外处理
break;
case 'invite':
this.showInviteBadge();
break;
default:
console.info(`未知推送类型: ${msg.type}`);
}
} catch (err) {
console.error(`推送数据解析失败: ${(err as BusinessError).message}`);
}
}
handlePushClick(data: string) {
try {
const msg: PushMessage = JSON.parse(data);
if (msg.action === 'game') {
// 跳转到游戏页面
this.routerToGame();
} else if (msg.action === 'activity') {
// 跳转到活动详情
this.routerToActivity(msg.data?.activityId ?? '');
}
} catch (err) {
console.error(`推送点击处理失败`);
}
}
}
3.2 推送回调详解
| 回调事件 | 触发时机 | data 内容 | 典型处理 |
|---|---|---|---|
on('receive') |
设备收到推送 | 完整的 JSON 字符串 | 更新 UI 角标、处理自定义数据 |
on('click') |
用户点击通知栏 | 推送消息的 JSON | 路由跳转、打开指定页面 |
on('token') |
推送 Token 更新 | 新 Token 字符串 | 上报给服务端 |
四、游戏中的推送应用
4.1 活动通知推送
// 处理活动推送:在游戏内显示活动横幅
showActivityBanner(title: string, body: string) {
// 只在非游戏进行时弹横幅
if (this.gameState !== GameState.PLAYING) {
promptAction.showToast({
message: `${title}: ${body}`,
duration: 3000,
});
}
}
4.2 好友邀请推送
handleInvitePush(data: string) {
const msg = JSON.parse(data);
const inviter = msg.data?.inviter ?? '好友';
// 显示邀请红点
this.hasInviteBadge = true;
// 弹窗提示
promptAction.showDialog({
title: `📨 ${inviter} 邀请你`,
message: `你的好友 ${inviter} 在猫猫大作战中获得了 ${msg.data?.score} 分,快来挑战吧!`,
buttons: [
{ text: '稍后', color: '#95A5A6' },
{ text: '去挑战', color: '#2ECC71' },
],
}).then((result) => {
if (result.index === 1) {
this.startGame();
}
});
}
五、推送 Token 管理
5.1 获取和上报 Token
async function setupPush(context: common.UIAbilityContext): Promise<void> {
// 获取推送 Token
const token = await pushService.getToken();
hilog.info(0xFF00, 'PushKit', `推送 Token: ${token}`);
// 将 Token 上报到自己的服务端
await reportTokenToServer(token);
}
async function reportTokenToServer(token: string): Promise<void> {
const response = await fetch('https://api.example.com/push/register', {
method: 'POST',
body: JSON.stringify({ token, platform: 'harmonyos' }),
});
if (!response.ok) {
console.error('Token 上报失败');
}
}
5.2 Token 刷新监听
// 监听 Token 刷新(切换账号、重新安装等场景)
pushService.on('token', (newToken: string) => {
hilog.info(0xFF00, 'PushKit', `Token 已刷新: ${newToken}`);
reportTokenToServer(newToken);
});
六、服务端推送
6.1 通过 AGC 发送推送
# 使用 AGC REST API 发送推送
curl -X POST https://push-api.cloud.huawei.com/v1/{appId}/messages:send \
-H "Authorization: Bearer {accessToken}" \
-H "Content-Type: application/json" \
-d '{
"message": {
"token": ["user_device_token"],
"notification": {
"title": "🎉 周末双倍积分!",
"body": "本周末所有合并得分翻倍!"
},
"data": JSON.stringify({
"type": "activity",
"action": "game"
})
}
}'
6.2 推送策略建议
| 推送类型 | 频率 | 最佳时间 | 内容建议 |
|---|---|---|---|
| 活动通知 | 每周 1-2 次 | 周五 18:00-20:00 | 限时活动、双倍积分 |
| 召回提醒 | 每 3-7 天 | 用户活跃时段 | “猫咪想念你” |
| 好友邀请 | 不定时 | 好友在线时 | “好友超过了你” |
| 版本更新 | 每次更新 | 发布后 24h | 新功能预告 |
提示:推送频率过高会导致用户关闭通知权限。建议每月不超过 8 条推送,且推送内容要提供实际价值(福利、好友互动)。
七、推送调试
7.1 真机调试
async function debugPush(context: common.UIAbilityContext) {
// 检查推送权限
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.checkAccessToken({
token: atManager.getApplicationTokenSync(),
permission: 'ohos.permission.PUSH'
});
console.info(`推送权限: ${result === 0 ? '已授权' : '未授权'}`);
// 获取 Token
try {
const token = await pushService.getToken();
console.info(`当前 Token: ${token}`);
} catch (err) {
console.error(`获取 Token 失败: ${err.message}`);
}
}
7.2 常见问题
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
| 收不到推送 | 未申请权限 / Token 未上报 | 检查权限声明和设备 Token |
| 推送无点击回调 | 未注册 click 事件 | 添加 on('click', handler) |
| Token 为空 | 网络问题 / 服务异常 | 重试获取或重启应用 |
| 推送 JSON 解析失败 | data 格式异常 | 服务端确保 data 为 JSON 字符串 |
八、节电与合规
8.1 推送接收的电源策略
// PushKit 接收推送不额外消耗电量
// 系统级长连接,应用无需保活
// 但在 on('receive') 中做耗时操作会额外耗电
// ✅ 推荐:收到推送后只做轻量操作
pushService.on('receive', (data: string) => {
this.pendingPush = data; // 仅缓存
});
// 避免:在回调中做网络请求或数据库写入
8.2 隐私合规
// 在隐私政策中声明推送服务
const privacyPolicy = `
我们使用 PushKit 向您发送游戏活动通知和好友邀请。
您可以随时在系统设置中关闭推送通知权限。
`;
// 首次启动时弹窗获取同意
async function showPrivacyDialog(context: common.UIAbilityContext) {
const hasAgreed = AppStorage.get<boolean>('privacyAgreed');
if (!hasAgreed) {
const result = await promptAction.showDialog({
title: '隐私政策',
message: privacyPolicy,
buttons: [
{ text: '不同意', color: '#E74C3C' },
{ text: '同意', color: '#2ECC71' },
],
});
AppStorage.setOrCreate('privacyAgreed', result.index === 1);
}
}
九、完整接入示例
@Entry
@Component
struct PushDemo {
@State hasPermission: boolean = false;
@State lastPush: string = '';
aboutToAppear() {
this.initPushService();
}
async initPushService() {
const ctx = getContext() as common.UIAbilityContext;
// 1. 请求权限
this.hasPermission = await requestPushPermission(ctx);
if (!this.hasPermission) return;
// 2. 注册监听
this.registerPushListeners();
// 3. 获取并上报 Token
await setupPush(ctx);
}
registerPushListeners() {
pushService.on('receive', (data: string) => {
this.lastPush = data;
// 更新 UI 角标
});
pushService.on('click', (data: string) => {
// 路由跳转
});
pushService.on('token', (token: string) => {
reportTokenToServer(token);
});
}
aboutToDisappear() {
// 取消注册推送监听
pushService.off('receive');
pushService.off('click');
pushService.off('token');
}
}
十、PushKit vs 其他通知方式
| 维度 | PushKit | 本地通知 | WebSocket |
|---|---|---|---|
| 触发方 | 服务端 | 应用自身 | 服务端 |
| 在线要求 | 设备联网即可 | 无需联网 | 需保持连接 |
| 实时性 | 秒级延迟 | 精确定时 | 毫秒级 |
| 保活要求 | 无需 | 无需 | 需保活 |
| 电量消耗 | 低(系统长连接) | 低 | 高(持续连接) |
| 适用场景 | 活动通知、召回 | 每日提醒、闹钟 | 实时对战、聊天 |
总结
PushKit 是 HarmonyOS 的远程推送服务,通过 on('receive') 接收推送消息、on('click') 处理点击跳转、on('token') 管理设备 Token。核心要点:权限在 module.json5 和运行时双重申请、 推送数据 JSON.parse 解析、 点击回调路由跳转、 Token 上报服务端、 推送频率适度防骚扰。
下一篇将深入 ShareKit——分享战绩到社交平台。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐



所有评论(0)