
引言
在移动应用生态中,消息推送(Push Notification)是提升用户活跃度与留存率的核心手段。然而,在国产操作系统快速发展的今天,开发者面临一个严峻挑战:
如何在 OpenHarmony 设备上实现与 Android/iOS 一致的推送体验?
华为推出的 OpenHarmony Push Kit 提供了系统级推送通道,具备:
- ✅ 高到达率(系统保活,不受应用被杀影响);
- ✅ 低功耗(统一通道,避免多 SDK 轮询);
- ✅ 合规安全(符合《个人信息保护法》与信创要求)。
但目前 Flutter 官方并未提供对 OpenHarmony Push Kit 的原生支持,社区也缺乏成熟插件。
本文将手把手教你:
✅ 从零封装 OpenHarmony Push Kit 为 Flutter 插件
✅ 实现 Token 获取、消息接收、点击跳转全流程
✅ 构建统一推送接口,兼容 Android/iOS/OpenHarmony 三端
✅ 开发一个"政务通知"示例 App,支持紧急消息强提醒
所有代码基于 OpenHarmony API 10(4.1 SDK) + Flutter 3.19 + DevEco Studio 5.0,已在华为 MatePad(OpenHarmony 版)实测通过。
一、为什么不能直接用 Firebase 或极光?
| 推送方案 | OpenHarmony 支持 | 合规性 | 到达率 | 备注 |
|---|---|---|---|---|
| Firebase Cloud Messaging (FCM) | ❌ 不支持 | ⚠️ 境外服务 | - | 无法在纯国产设备运行 |
| 极光/JPush/个推 | ⚠️ 需自建长连接 | ⚠️ 需额外备案 | 中 | 违背"统一推送联盟"原则 |
| OpenHarmony Push Kit | ✅ 官方原生 | ✅ 国产合规 | 高 | 系统级通道,推荐 |
📌 政策背景 :根据《移动智能终端补充设备标识体系技术要求》,国内应用应优先使用 系统级推送服务,减少后台常驻。
二、整体集成架构
┌───────────────────────┐
│ Flutter (Dart) │
│ - 调用 push_ohos 插件 │ ← MethodChannel / EventChannel
└───────────▲───────────┘
│
┌───────────┴───────────┐
│ OpenHarmony (ArkTS) │
│ - 封装 @ohos.push │
│ - 实现 PushReceiver │
│ - 处理点击 Intent │
└───────────▲───────────┘
│
┌───────────┴───────────┐
│ OpenHarmony Push Kit │
│ - HMS Core (可选) │
│ - 系统推送服务 │
└───────────────────────┘
✅ 核心目标 :
Flutter 层只需调用
PushService.getToken()和监听onMessageReceived,无需关心底层实现差异。
三、Step 1:创建 Flutter 插件项目
bash
flutter create --org com.example --template=plugin --platforms=ohos push_ohos
cd push_ohos
💡 注意:需使用 Flutter 3.19+ 并配置好 OpenHarmony 开发环境。
四、Step 2:OpenHarmony 端实现 Push Kit 封装
1. 添加依赖与权限(module.json5)
json5
{
"module": {
"requestPermissions": [
{ "name": "ohos.permission.INTERNET" },
{ "name": "ohos.permission.GET_NETWORK_INFO" },
{ "name": "ohos.permission.PUSH_SERVICE" } // 关键权限
],
"abilities": [
{
"name": "PushReceiver",
"srcEntry": "./ets/push/PushReceiver.ets",
"exported": true,
"metadata": [
{
"name": "ohos.push.message.receiver",
"value": "com.example.push_ohos.PushReceiver"
}
]
}
]
}
}
2. 实现 Push Receiver(ets/push/PushReceiver.ets)
typescript
// ets/push/PushReceiver.ets
import push from '@ohos.push';
import Ability from '@ohos.app.ability.UIAbility';
export default class PushReceiver extends Ability {
onReceive(context, data) {
console.info('[PushKit] Received message:', JSON.stringify(data));
// 通过 EventChannel 通知 Flutter
const eventChannel = this.engine?.createEventChannel('com.example.push_ohos/messages');
if (eventChannel) {
eventChannel.success({
title: data.title || '新消息',
body: data.body || '',
extra: data.extraData || {},
messageId: data.messageId
});
}
}
}
3. 封装 MethodChannel 接口(ets/PushPlugin.ets)
typescript
// ets/PushPlugin.ets
import push from '@ohos.push';
export class PushPlugin {
private context: any;
constructor(context: any) {
this.context = context;
}
// 获取 Push Token
async getToken(): Promise<string> {
try {
const token = await push.getToken({
appId: 'your_app_id', // 在 AGC 控制台注册
scope: 'push'
});
console.info('[PushKit] Token:', token);
return token;
} catch (e) {
console.error('[PushKit] Get token failed:', e);
throw new Error('获取推送Token失败');
}
}
// 请求通知权限(OpenHarmony 4.1+)
async requestPermission(): Promise<boolean> {
const result = await push.requestEnableNotification(this.context);
return result;
}
}
4. 在 EntryAbility 中注册插件
typescript
// EntryAbility.ts
import { PushPlugin } from './PushPlugin';
export default class EntryAbility extends UIAbility {
onCreate() {
// 注册 MethodChannel
this.engine?.registerMethodChannel('com.example.push_ohos/methods', (method, args, callback) => {
const plugin = new PushPlugin(this.context);
switch (method) {
case 'getToken':
plugin.getToken().then(callback.success).catch(callback.error);
break;
case 'requestPermission':
plugin.requestPermission().then(callback.success).catch(callback.error);
break;
default:
callback.error('METHOD_NOT_FOUND');
}
});
}
}
五、Step 3:Flutter 端插件封装
1. 定义 Dart 接口(lib/push_ohos.dart)
dart
// lib/push_ohos.dart
import 'package:flutter/services.dart';
class PushOhos {
static const _methodChannel = MethodChannel('com.example.push_ohos/methods');
static const _eventChannel = EventChannel('com.example.push_ohos/messages');
// 获取 Token
static Future<String?> getToken() async {
try {
final token = await _methodChannel.invokeMethod('getToken');
return token as String?;
} catch (e) {
print('获取 Push Token 失败: $e');
return null;
}
}
// 请求通知权限
static Future<bool> requestPermission() async {
try {
final result = await _methodChannel.invokeMethod('requestPermission');
return result as bool;
} catch (e) {
return false;
}
}
// 监听推送消息
static Stream<Map<String, dynamic>> get onMessageReceived {
return _eventChannel.receiveBroadcastStream().map((event) {
return event as Map<String, dynamic>;
});
}
}
2. 使用示例(main.dart)
dart
// main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 1. 请求通知权限
await PushOhos.requestPermission();
// 2. 获取 Token 并上传至业务服务器
final token = await PushOhos.getToken();
if (token != null) {
await ApiService.registerPushToken(token);
}
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _messages = <Map<String, dynamic>>[];
@override
void initState() {
super.initState();
// 3. 监听推送消息
PushOhos.onMessageReceived.listen((message) {
setState(() {
_messages.insert(0, message);
});
// 可选:上报消息已读
ApiService.reportMessageRead(message['messageId']);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('政务通知中心')),
body: ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) {
final msg = _messages[index];
return ListTile(
title: Text(msg['title']),
subtitle: Text(msg['body']),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
);
},
),
),
);
}
}
六、Step 4:处理通知点击跳转
当用户点击通知时,需打开指定页面(如"查看详细通知")。
OpenHarmony 端:解析 Intent 参数
typescript
// EntryAbility.ts 的 onNewWant 方法
onNewWant(want) {
// 检查是否由通知唤醒
if (want.parameters?.messageId) {
// 通过 EventChannel 通知 Flutter 跳转
const eventChannel = this.engine?.createEventChannel('com.example.push_ohos/launch');
eventChannel?.success({
messageId: want.parameters.messageId,
extra: want.parameters.extraData
});
}
}
Flutter 端:监听启动参数
dart
// 在 main.dart 中
PushOhos.onAppLaunchedByNotification.listen((params) {
// 跳转到详情页
Navigator.pushNamed(
navigatorKey.currentContext!,
'/notice-detail',
arguments: params['messageId'],
);
});
七、服务端集成要点
-
注册 AGC 应用
登录 AppGallery Connect,创建 OpenHarmony 应用,获取
appId和证书。 -
发送推送请求(REST API)
bash
POST https://push-api.cloud.huawei.com/v1/[APP_ID]/messages:send
Headers:
Authorization: Bearer [ACCESS_TOKEN]
Content-Type: application/json
Body:
{
"message": {
"notification": {
"title": "紧急通知",
"body": "今日有暴雨预警,请注意安全!"
},
"android": {
"notification_channel_id": "emergency" // 需提前创建高优先级通道
},
"token": ["PUSH_TOKEN_HERE"]
}
}
🔔 重要 :为政务/应急类消息创建 高优先级通知通道,支持强提醒(震动+铃声)。
八、调试与常见问题
1. 收不到 Token?
- 检查
module.json5是否声明PUSH_SERVICE权限; - 确认设备已登录 华为账号(Push Kit 依赖账号体系);
- 查看 AGC 应用是否配置正确。
2. 消息不显示?
- 确保应用 未被电池优化限制;
- 检查通知权限是否开启(设置 → 通知 → 应用名);
- 使用 AGC 推送测试工具 直接发送。
3. 真机 vs 模拟器
- 模拟器不支持 Push Kit,必须使用真机调试;
- 开发阶段可 Mock 数据:
dart
// 开发模式 Mock
if (kDebugMode) {
PushOhos.onMessageReceived = Stream.value({
'title': '【测试】模拟推送',
'body': '这是一条模拟消息',
'extra': {'type': 'test'}
});
}
九、扩展:构建跨平台统一推送层
为兼容 Android/iOS,可抽象统一接口:
dart
// lib/services/push_service.dart
abstract class PushService {
Future<String?> getToken();
Stream<Map<String, dynamic>> get onMessageReceived;
}
class OhosPushService implements PushService {
@override
Future<String?> getToken() => PushOhos.getToken();
@override
Stream<Map<String, dynamic>> get onMessageReceived => PushOhos.onMessageReceived;
}
// 在 main.dart 中
final pushService = Platform.isAndroid || Platform.isIOS
? FirebasePushService()
: OhosPushService();
十、总结
通过本文,你已掌握:
✅ 从零封装 OpenHarmony Push Kit 为 Flutter 插件
✅ 实现 Token 获取、消息接收、点击跳转全链路
✅ 构建符合国产化合规要求的推送方案
✅ 为政务、金融、能源等关键领域提供可靠触达能力
🌐 未来展望 :
随着 OpenHarmony 生态完善,Push Kit 将支持 富媒体通知、分组聚合、定时推送 等高级能力。建议开发者尽早接入,抢占国产化应用先机。