手把手教你玩转 HarmonyOS 推送卡片刷新:从场景到代码全解析
摘要:HarmonyOS卡片刷新开发指南详解如何通过FormKit和PushKit实现实时数据推送。开发卡片需配置form_config.json并定义刷新字段,图片路径需加"memory://"前缀。推送消息需获取PushToken并按频控规则发送(测试阶段每日1000条,正式阶段单卡每日2-5条)。服务端调用REST API时需注意图片格式限制(≤512KB)和版本号递增原
一、场景介绍:为什么需要卡片刷新消息?
想想看,你有没有遇到过这种情况:想随时查看天气却得打开天气 APP,想看新闻更新还得点开新闻软件,这些繁琐的操作是不是很影响体验?HarmonyOS 推出的 Form Kit(卡片开发服务)就是来解决这个问题的 —— 它能把应用的重要信息或操作直接前置到桌面卡片上,让你不用打开应用就能获取关键信息。
而针对那些需要实时更新数据的卡片,比如实时天气、股票行情、外卖进度这类场景,Push Kit 提供的卡片刷新服务就派上用场了。简单来说,只要你的应用集成了 Push Kit,拿到 Push Token,就能通过系统级通道给用户推送卡片更新内容,用户感知更及时,自然也就更愿意用你的应用啦。
重点总结:
- Form Kit 让应用信息前置到桌面,减少用户操作层级
- Push Kit 提供卡片刷新服务,适合实时数据更新场景
- 集成 Push Kit 获取 Token 后,可通过系统通道推送更新
二、频控规则:发消息可不能太 "任性"
这里得先给开发者划重点:推送消息可不是想发多少就发多少,华为对推送频率做了明确限制,既能保证用户体验,也能避免被当成骚扰信息。
测试阶段(调测时)
每个项目每天全网最多只能发 1000 条测试消息,而且发送时必须把 testMessage 设为 true。记住哦,这是测试阶段的 "额度",可别超了。
正式发布阶段
- 单设备单应用总限制: 每天所有场景化消息加起来不能超过 3000 条
- 单张卡片限制: 这得看应用是否上架
- 已上架应用:单设备单应用下,单张卡片每天只能发 2 条刷新消息
- 未上架应用:稍微宽松点,单张卡片每天能发 5 条
特别提醒
不管是测试消息还是正式消息,单次发送只能携带一个 Token,可别想着 "批量操作" 哦。
重点总结:
- 测试阶段:每日 1000 条测试消息,需设置 testMessage=true
- 正式阶段:单设备单应用每日总消息≤3000 条
- 单张卡片:已上架每日 2 条,未上架每日 5 条
- 单次推送仅支持 1 个 Token
三、开发步骤:从零开始实现卡片刷新
(一)开发卡片:先把 "舞台" 搭好
要实现卡片刷新,得先把本地卡片开发好。这里分三步走,每一步都有对应的代码配置,咱们一步步来。
1. 创建 ArkTS 卡片
首先得创建一个基础的 ArkTS 卡片,这是卡片的 "骨架"。具体怎么创建呢?可以参考华为官方文档里 "创建一个 ArkTS 卡片" 的步骤,这里就不重复啦。
2. 配置 form_config.json
在项目模块的 src/main/resources/base/profile/form_config.json 里,有个关键配置:把 dataProxyEnabled 字段设为 true,这相当于开启了卡片的 "刷新开关"。来看具体配置示例:
{
"forms": [
{
"name": "widget",
"src": "./ets/widget/pages/WidgetCard.ets",
"uiSyntax": "arkts",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"colorMode": "auto",
"isDefault": true,
"updateEnabled": true,
"updateDuration": 1,
"scheduledUpdateTime": "10:30",
"defaultDimension": "2*2",
"supportDimensions": ["2*2"],
"dataProxyEnabled": true // 关键配置,开启卡片代理刷新功能
}
]
}
3. 获取 formId 并定义刷新字段
在卡片生命周期管理文件(比如 EntryFormAbility)的 onAddForm () 回调里,需要做两件事:获取 formId,定义要刷新的字段。以 text_key 和 image_key 为例,来看代码:
import { formBindingData, formInfo, FormExtensionAbility } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
export default class EntryFormAbility extends FormExtensionAbility {
onAddForm(want: Want): formBindingData.FormBindingData {
// 获取formId,这是卡片的唯一标识
const formId = want.parameters![formInfo.FormParam.IDENTITY_KEY] as string;
// 定义需要在卡片页面中刷新的字段
class CreateFormData {
formId: string = '';
text_key: string = '';
image_key: string = '';
}
const obj: CreateFormData = {
formId: formId,
text_key: '默认文本',
image_key: ''
}
// 创建绑定数据
const bindingData: formBindingData.FormBindingData = formBindingData.createFormBindingData(obj);
// 定义需要通过Push Kit代理刷新的字段,每个key都要在bindingData中定义
const text_key: formBindingData.ProxyData = {
key: 'text_key',
subscriberId: formId
};
const image_key: formBindingData.ProxyData = {
key: 'image_key',
subscriberId: formId
};
bindingData.proxies = [text_key, image_key];
return bindingData;
}
}
4. 卡片页面数据绑定
在卡片页面文件(比如 WidgetCard.ets)中,需要创建 LocalStorage 变量并绑定数据。这里要注意:图片组件传递的变量必须以 memory:// 开头。来看具体实现:
// 定义页面级的UI状态存储LocalStorage
const storage = new LocalStorage();
// 绑定
@Entry(storage)
@Component
struct WidgetCard {
@LocalStorageProp('formId') formId: string = '';
@LocalStorageProp('text_key') text: string = '';
@LocalStorageProp('image_key') image: string = '';
build() {
Flex({ direction: FlexDirection.Column }) {
Row() {
Text() {
// Span是Text组件的子组件,用于显示行内文本
Span('formID:')
Span(this.formId)
}
.fontSize(10)
}
Row() {
Text() {
Span('文本:')
Span(this.text)
}
.fontSize(10)
}
Row() {
if (this.image) {
Image('memory://' + this.image).height(80) // 图片路径必须以memory://开头
}
}
}
.padding(10)
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'MainAbility', // 请配置为应用实际的abilityName
});
})
}
}
开发卡片重点总结:
- 配置 form_config.json 开启 dataProxyEnabled=true
- 在 onAddForm () 中获取 formId 并定义刷新字段(text_key/image_key)
- 使用 LocalStorageProp 绑定页面数据,图片路径需以 memory:// 开头
(二)推送卡片刷新消息:让数据 "动" 起来
卡片开发好了,接下来就是关键的推送环节。这一步需要分三步走:获取 Push Token、上报信息到服务端、调用 REST API 推送消息。
1. 获取 Push Token
首先得获取 Push Token,这是推送消息的 "通行证"。可以参考华为文档中 "获取 Push Token" 的指导,这里给出获取 Token 的代码示例:
import { pushService } from '@kit.PushKit';
async function getPushToken() {
try {
const pushToken: string = await pushService.getToken();
return pushToken;
} catch (err) {
// 处理获取Token失败的情况
console.error('获取Push Token失败', err);
}
}
2. 上报 formId 和 Push Token 到服务端
建议把 formId、pushToken 等信息上报到应用服务端,这样服务端才能知道该给哪个卡片推送消息。来看伪代码实现:
import { Want } from '@kit.AbilityKit';
import { pushService } from '@kit.PushKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { formInfo } from '@kit.FormKit';
async function saveFormInfo(want: Want): Promise<void> {
try {
// 获取卡片相关信息
const formId = want.parameters![formInfo.FormParam.IDENTITY_KEY] as string;
const moduleName = want.moduleName;
const abilityName = want.abilityName;
const formName = want.parameters![formInfo.FormParam.NAME_KEY] as string;
// 获取Push Token
const pushToken: string = await pushService.getToken();
// 上报到应用服务端
// 这里需要调用你自己的服务端接口
await fetch('你的服务端接口地址', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
formId,
moduleName,
abilityName,
formName,
pushToken
})
});
} catch (err) {
let e: BusinessError = err as BusinessError;
hilog.error(0x0000, 'testTag', 'Failed to save form info: %{public}d %{public}s', e.code, e.message);
}
}
3. 服务端调用 REST API 推送消息
这是最关键的一步,服务端需要构造 HTTP 请求来推送卡片刷新消息。来看完整的请求示例:
// Request URL
POST https://push-api.cloud.huawei.com/v3/[projectId]/messages:send
// Request Header
Content-Type: application/json
Authorization: Bearer eyJr*****OiIx---****.eyJh*****iJodHR--***.QRod*****4Gp---****
push-type: 1 // 1表示服务卡片刷新场景
// Request Body
{
"payload": {
"moduleName": "entry", // 项目模块名,在module.json5中获取
"abilityName": "EntryFormAbility", // 服务卡片的ability名称
"formName": "widget", // 卡片名称,在form_config.json中定义
"formId": 423434262, // 卡片实例ID
"version": 123456, // 版本号,必须大于当前版本
"formData": {
"text_key": "刷新文本内容" // 要刷新的文本数据
},
"images": [
{
"keyName": "image_key", // 图片控件的key值
"url": "https://***.png", // 图片地址
"require": 1 // 刷新策略:1表示图片失败则不刷新
}
]
},
"target": {
"token": [
"IQAAAAC*************************dRH7_bPbfMrVfsYw" // Push Token
]
},
"pushOptions": {
"testMessage": true // 测试消息标识
}
}
关键参数说明
- projectId: 登录 AppGallery Connect 获取项目 ID
- Authorization: JWT 格式的授权字符串,按文档步骤获取
- version: 必须大于当前卡片刷新消息的版本号,否则刷新失败
- formData: 对应卡片页面中定义的文本数据字段
- images: 图片数据,keyName 对应卡片中的 image_key,url 是图片地址
- require: 图片刷新策略,0 表示图片失败时只刷新文字,1 表示失败则不刷新
- testMessage: true 表示测试消息,受每日 1000 条限制
推送消息重点总结:
- 获取 Push Token 作为推送凭证
- 上报 formId 和 Push Token 到服务端
- 服务端构造 HTTP 请求,注意各参数含义和格式
- version 必须递增,图片格式和大小有限制(PNG/JPG/JPEG,≤512KB,长 * 宽 < 12800 像素)
四、避坑指南:这些细节一定要注意
1. 图片相关限制
- 禁止推送包含敏感信息的图片
- 支持格式:PNG、JPG、JPEG
- 大小限制:单张图片≤512KB
- 像素限制:长 * 宽 < 12800 像素
2. 版本号 version 的重要性
每次推送的 version 必须比之前的大,不然会刷新失败。这就好比软件更新,必须是更高的版本号才能生效。
3. 测试消息与正式消息的区别
- 测试消息需要设置 testMessage=true
- 每个项目每天最多 1000 条测试消息
- 单次推送只能有一个 Token,正式消息同理
4. 字段对应关系
- form_config.json 中的 name 对应请求中的 formName
- module.json5 中的 module 名称对应请求中的 moduleName
- extensionAbilities 中的 ability 名称对应请求中的 abilityName
- 卡片页面中定义的 text_key/image_key 对应请求中的 formData/images 字段
五、总结:从原理到实践的全流程回顾
现在咱们来捋一捋整个流程:首先理解为什么需要卡片刷新(提升用户体验和活跃度),然后记住频控规则(测试和正式阶段的限制),接着分两步开发 —— 先搭好卡片 "舞台"(配置文件、获取 formId、绑定数据),再让数据 "动" 起来(获取 Token、上报信息、调用 API 推送)。
整个过程中,代码配置是核心,从 form_config.json 的关键字段到服务端请求的每个参数,都需要一一对应。特别是图片路径的 memory:// 前缀、version 的递增规则、测试消息的标识设置,这些细节很容易出错,一定要多检查。
其实说白了,卡片刷新就是让你的应用能主动把最新信息 "推" 给用户,而不用用户自己打开应用。这就像你有个贴心的小助手,主动把你关心的消息送到眼前,体验自然就上去了。赶紧按照这个步骤试试吧,让你的 HarmonyOS 应用更 "智能"、更懂用户!
更多推荐



所有评论(0)