文章配图: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——分享战绩到社交平台。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐