文章配图: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、测试、元服务和应用上架分发等。

更多推荐