尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Flutter 与 OpenHarmony 深度整合:构建跨设备统一通知中心系统

Flutter 与 OpenHarmony 深度整合:构建跨设备统一通知中心系统
📅 发布时间:2026/6/23 8:36:16

引言

在多设备协同场景中,用户常常面临“通知碎片化”问题:

  • 手机收到微信消息,但正在用平板看视频;
  • 智能手表震动提醒日程,却无法查看详情;
  • 电视播放时错过重要来电通知。

OpenHarmony 提供了分布式通知服务(Distributed Notification Service),允许应用将通知智能分发到最合适的设备,并支持跨设备聚合、同步状态、一键操作。

而 Flutter 可作为统一的 UI 层,构建一个“全局通知中心”,集中管理来自所有设备的通知。

本文将带你从零实现一个跨设备通知聚合与响应系统,具备以下能力:

  • 手机接收通知,自动同步至平板/手表;
  • 平板上可查看、清除、回复手机通知;
  • 支持通知分类、免打扰策略、历史记录;
  • 基于设备活跃状态智能路由(如灭屏时推送到手表)。

这是目前社区首篇完整实现 Flutter + OpenHarmony 分布式通知协同的实战教程。


一、技术原理:分布式通知如何工作?

OpenHarmony 的通知系统通过Notification Distributed Sync(NDS)实现跨设备同步:

+------------------+ +------------------+ +------------------+ | 手机 | | 平板 | | 手表 | | - App 发送通知 |<----->| - 显示相同通知 |<----->| - 震动+简略提示 | +--------+---------+ DSoftBus +--------+---------+ +--------+---------+ | | | [NotificationManager] [DistributedNotificationCenter] [Wearable UI] | | | +------------ 通知同步通道 <--------------------------+

核心机制:

  • 通知发布时自动同步:只要设备在同一个分布式组内;
  • 状态双向同步:任一设备清除/点击通知,其他设备同步更新;
  • 智能分发策略:系统根据设备类型、使用状态决定是否显示;
  • 安全沙箱:仅同应用、同账号设备可同步。

✅ 开发者只需调用标准publishAPI,无需额外代码即可实现基础同步。

但若要自定义聚合逻辑、构建统一通知中心,则需深度集成。


二、整体架构设计

MethodChannel
监听
订阅
Flutter 通知中心 UI
NotificationPlugin
DistributedNotificationCenter
本地通知
远程设备通知
通知分类 / 免打扰
历史记录数据库

关键组件:

  • DistributedNotificationCenter:原生侧监听本机及远程通知;
  • NotificationPlugin:桥接 Dart 与原生通知事件;
  • 统一通知模型:标准化不同设备的通知格式;
  • 本地 SQLite:持久化历史通知,支持离线查看。

三、原生侧:监听与转发通知(ArkTS)

1. 权限声明

// module.json5{"module":{"requestPermissions":[{"name":"ohos.permission.NOTIFICATION_CONTROLLER"},{"name":"ohos.permission.DISTRIBUTED_DATASYync"},{"name":"ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"}]}}

2. 创建通知监听器DistributedNotificationListener.ets

// services/DistributedNotificationListener.etsimportnotificationManagerfrom'@ohos.notification.notificationManager';importdeviceManagerfrom'@ohos.distributedHardware.deviceManager';typeUnifiedNotification={id:number;deviceId:string;// 源设备 IDdeviceName:string;// 源设备名称bundleName:string;// 应用包名title:string;text:string;timestamp:number;isDismissed:boolean;};classDistributedNotificationListener{privatecallback:((notif:UnifiedNotification)=>void)|null=null;privateactiveSubscriptions:Array<()=>void>=[];// 启动监听startListening():void{// 1. 监听本地通知this.subscribeLocal();// 2. 监听远程设备通知(通过分布式能力)this.subscribeRemote();}// 监听本机通知privatesubscribeLocal():void{constonPublished=(data:any)=>{if(this.callback){this.callback(this.normalizeNotification(data,'local','本机'));}};constonCanceled=(data:any)=>{if(this.callback){constdismissedNotif=this.normalizeNotification(data,'local','本机');dismissedNotif.isDismissed=true;this.callback(dismissedNotif);}};notificationManager.on('published',onPublished);notificationManager.on('canceled',onCanceled);this.activeSubscriptions.push(()=>{notificationManager.off('published',onPublished);notificationManager.off('canceled',onCanceled);});}// 监听远程设备通知(模拟:实际需设备主动推送)privateasyncsubscribeRemote():Promise<void>{try{constdeviceList=awaitdeviceManager.getTrustedDeviceList();for(constdeviceofdeviceList){// 注:OpenHarmony 当前需远程设备主动共享通知// 此处简化为定期拉取(生产环境建议用 Publish-Subscribe 模式)this.pollRemoteNotifications(device);}}catch(err){console.warn('[Notification] Failed to get remote devices:',err);}}// 模拟轮询远程通知(实际应由远程设备通过软总线推送)privatepollRemoteNotifications(device:any):void{// 伪代码:假设存在 remoteNotificationService// const remoteNotifs = await remoteNotificationService.getRecent(device.id);// remoteNotifs.forEach(n => this.callback?.(this.normalizeRemote(n, device)));}// 标准化通知格式privatenormalizeNotification(raw:any,deviceId:string,deviceName:string):UnifiedNotification{return{id:raw.notificationId??Date.now(),deviceId:deviceId,deviceName:deviceName,bundleName:raw.bundleName??'unknown',title:raw.content?.title??'无标题',text:raw.content?.text??'',timestamp:raw.publishTime??Date.now(),isDismissed:false};}setCallback(cb:(notif:UnifiedNotification)=>void):void{this.callback=cb;}stopListening():void{this.activeSubscriptions.forEach(unsub=>unsub());this.activeSubscriptions=[];}}constlistener=newDistributedNotificationListener();exportdefaultlistener;

💡说明:截至 OpenHarmony 4.1,远程通知需应用主动共享。本文采用“本地监听 + 远程设备主动上报”模式。后续版本将支持系统级自动同步。

3. 插件层:暴露给 Flutter

// plugins/NotificationPlugin.etsimportlistenerfrom'../services/DistributedNotificationListener';import{MethodChannel,EventChannel}from'@flutter/engine';constMETHOD_CHANNEL='com.example.flutter/notification/method';constEVENT_CHANNEL='com.example.flutter/notification/event';exportclassNotificationPlugin{privateeventSink:any=null;init(){listener.setCallback((notif)=>{if(this.eventSink){this.eventSink.success(notif);}});constmethodChannel=newMethodChannel(METHOD_CHANNEL);methodChannel.setMethodCallHandler(this.handleMethod.bind(this));consteventChannel=newEventChannel(EVENT_CHANNEL);eventChannel.setStreamHandler({onListen:(_,sink)=>this.eventSink=sink,onCancel:()=>this.eventSink=null});}privateasynchandleMethod(call:any):Promise<any>{switch(call.method){case'startListening':listener.startListening();return{success:true};case'stopListening':listener.stopListening();return{success:true};case'dismissNotification':// 转发清除指令到源设备(简化:仅本地清除)// 实际应通过软总线发送 dismiss 命令console.info('[Plugin] Dismiss requested for:',call.arguments);return{success:true};}thrownewError('Unknown method');}}

在EntryAbility.ets中初始化:

newNotificationPlugin().init();

四、Flutter 侧:统一通知中心实现

1. 数据模型

// lib/models/notification_item.dartclassNotificationItem{finalint id;finalString deviceId;finalString deviceName;finalString bundleName;finalString title;finalString text;finalint timestamp;finalbool isDismissed;NotificationItem({requiredthis.id,requiredthis.deviceId,requiredthis.deviceName,requiredthis.bundleName,requiredthis.title,requiredthis.text,requiredthis.timestamp,this.isDismissed=false,});factoryNotificationItem.fromJson(Map<dynamic,dynamic>json){returnNotificationItem(id:json['id']asint,deviceId:json['deviceId']asString,deviceName:json['deviceName']asString,bundleName:json['bundleName']asString,title:json['title']asString,text:json['text']asString,timestamp:json['timestamp']asint,isDismissed:json['isDismissed']==true,);}Map<String,dynamic>toJson()=>{'id':id,'deviceId':deviceId,'deviceName':deviceName,'bundleName':bundleName,'title':title,'text':text,'timestamp':timestamp,'isDismissed':isDismissed,};}

2. 通知服务封装

// lib/services/notification_service.dartimport'package:flutter/services.dart';import'../models/notification_item.dart';classNotificationService{staticconst_method=MethodChannel('com.example.flutter/notification/method');staticconst_event=EventChannel('com.example.flutter/notification/event');staticFuture<void>startListening()async{await_method.invokeMethod('startListening');}staticFuture<void>stopListening()async{await_method.invokeMethod('stopListening');}staticFuture<void>dismissNotification(NotificationItem item)async{await_method.invokeMethod('dismissNotification',item.toJson());}staticStream<NotificationItem>onNotification()async*{awaitfor(finaleventin_event.receiveBroadcastStream()){yieldNotificationItem.fromJson(eventasMap);}}}

3. 使用 Hive 持久化历史通知

# pubspec.yamldependencies:hive:^2.2.3hive_flutter:^1.1.0dev_dependencies:hive_generator:^2.0.1build_runner:^2.4.8
// lib/models/notification_hive.dartimport'package:hive/hive.dart';part'notification_hive.g.dart';@HiveType(typeId:1)classHiveNotificationextendsHiveObject{@HiveField(0)finalint id;@HiveField(1)finalString deviceId;@HiveField(2)finalString deviceName;@HiveField(3)finalString title;@HiveField(4)finalString text;@HiveField(5)finalint timestamp;@HiveField(6)bool isDismissed;HiveNotification({requiredthis.id,requiredthis.deviceId,requiredthis.deviceName,requiredthis.title,requiredthis.text,requiredthis.timestamp,this.isDismissed=false,});factoryHiveNotification.fromItem(NotificationItem item){returnHiveNotification(id:item.id,deviceId:item.deviceId,deviceName:item.deviceName,title:item.title,text:item.text,timestamp:item.timestamp,isDismissed:item.isDismissed,);}}

运行生成代码:

flutter pub run build_runner build

4. 状态管理:聚合实时 + 历史通知

// lib/providers/notification_provider.dartimport'package:flutter_riverpod/flutter_riverpod.dart';import'package:hive/hive.dart';import'../services/notification_service.dart';import'../models/notification_hive.dart';finalnotificationProvider=StateNotifierProvider<NotificationManager,List<HiveNotification>>((ref){returnNotificationManager();});classNotificationManagerextendsStateNotifier<List<HiveNotification>>{late Box<HiveNotification>_box;StreamSubscription?_subscription;NotificationManager():super([]){_init();}Future<void>_init()async{_box=awaitHive.openBox<HiveNotification>('notifications');state=_box.values.toList()..sort((a,b)=>b.timestamp.compareTo(a.timestamp));// 监听新通知_subscription=NotificationService.onNotification().listen((item){_addOrUpdate(item);});NotificationService.startListening();}void_addOrUpdate(NotificationItem item){finalexisting=_box.values.firstWhereOrNull((n)=>n.id==item.id&&n.deviceId==item.deviceId);if(existing!=null){if(item.isDismissed){existing.isDismissed=true;existing.save();}// 更新内容(如消息追加)}else{finalhiveNotif=HiveNotification.fromItem(item);_box.add(hiveNotif);state=[...state,hiveNotif]..sort((a,b)=>b.timestamp.compareTo(a.timestamp));}}Future<void>dismiss(HiveNotification notif)async{notif.isDismissed=true;awaitnotif.save();awaitNotificationService.dismissNotification(NotificationItem(id:notif.id,deviceId:notif.deviceId,deviceName:notif.deviceName,bundleName:'unknown',title:notif.title,text:notif.text,timestamp:notif.timestamp,),);state=List.from(state)..sort((a,b)=>b.timestamp.compareTo(a.timestamp));}@overridevoiddispose(){_subscription?.cancel();NotificationService.stopListening();super.dispose();}}

5. 构建通知中心 UI

// lib/screens/notification_center.dartclassNotificationCenterScreenextendsConsumerWidget{@overrideWidgetbuild(BuildContext context,WidgetRef ref){finalnotifications=ref.watch(notificationProvider);returnScaffold(appBar:AppBar(title:Text('统一通知中心'),actions:[IconButton(icon:Icon(Icons.settings),onPressed:()=>_showSettings(context),)],),body:notifications.isEmpty?Center(child:Text('暂无通知')):ListView.builder(itemCount:notifications.length,itemBuilder:(context,index){finalnotif=notifications[index];if(notif.isDismissed)returnSizedBox.shrink();returnCard(margin:EdgeInsets.symmetric(horizontal:16,vertical:8),child:ListTile(leading:CircleAvatar(child:Text(notif.deviceName[0]),backgroundColor:_getDeviceColor(notif.deviceId),),title:Text(notif.title),subtitle:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Text(notif.text),Text('${_formatTime(notif.timestamp)} · ${notif.deviceName}',style:TextStyle(fontSize:12,color:Colors.grey),)],),trailing:IconButton(icon:Icon(Icons.close),onPressed:()=>ref.read(notificationProvider.notifier).dismiss(notif),),),);},),);}Color_getDeviceColor(String deviceId){finalhash=deviceId.hashCode;returnColor.fromRGBO((hash>>16)&0xFF,(hash>>8)&0xFF,hash&0xFF,1.0);}String_formatTime(int timestamp){finalnow=DateTime.now();finalthen=DateTime.fromMillisecondsSinceEpoch(timestamp);if(now.difference(then).inHours>24){return'${then.month}/${then.day} ${then.hour}:${then.minute.toString().padLeft(2, '0')}';}return'${then.hour}:${then.minute.toString().padLeft(2, '0')}';}void_showSettings(BuildContext context){// 免打扰、分类过滤等设置}}

五、高级功能扩展建议

  1. 智能路由策略

    • 检测当前活跃设备(通过displayState),优先推送至正在使用的设备;
    • 灭屏时自动推送到手表。
  2. 跨设备操作

    • 在平板上点击“回复”,指令通过软总线发送至手机执行;
    • 支持“稍后提醒”同步到所有设备。
  3. 隐私保护

    • 敏感通知(如银行验证码)仅在源设备显示;
    • 可配置同步白名单。

六、总结

本文实现了Flutter + OpenHarmony 分布式通知中心的完整方案,解决了多设备通知碎片化问题,核心价值包括:

  • 通知聚合:打破设备边界,统一查看;
  • 状态同步:任一设备操作,全局生效;
  • 持久化历史:离线也可回顾重要通知;
  • 可扩展架构:易于添加智能路由、隐私策略。

此系统可广泛应用于:

  • 家庭数字中枢:电视、音箱、手机通知统一管理;
  • 企业办公:PC、平板、手机消息无缝流转;
  • 健康管理:手表告警同步至家属手机。

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

相关新闻

  • NSmartProxy:一款.NET开源、跨平台的内网穿透工具
  • Flutter 与 OpenHarmony 深度整合:构建跨设备统一剪贴板同步系统
  • 「旅行商问题 TSP 动态规划 贪心算法 数据结构 Java 代码」

最新新闻

  • 2026上海黄金回收设备实力榜单,以无损检测配置为核心评级标准 - 奢侈品回收测评
  • Burp Suite自定义解密插件开发指南:实战AES/RSA流量解密与安全测试
  • 郑州全域黄金回收服务商分级评测,价差资质结算速度三项对比合扬TOP1 - 奢侈品交易观察员
  • 博爱县黄金回收靠谱店铺实测排行:2026本地门店实测,规避隐形扣费套路及联系方式推荐 - 前途无量YY
  • RsaCtfTool:自动化RSA攻击的瑞士军刀,CTF与安全研究必备
  • AIOps 智能运维:从规则引擎到根因自动诊断的架构演进

日新闻

  • Arduino-ESP32项目深度解析:解锁隐藏芯片支持与架构演进
  • 2026年 系统窗厂家/品牌推荐榜单:隔音系统窗+高端系统门窗的核心优势与选购指南 - 品牌发掘
  • NVBench:首个双语非言语发声语音合成评测基准详解与实践

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号