2026/1/8 20:56:28
网站建设
项目流程
电子政务系统网站建设的基本过程,朔州企业网站建设,哈尔滨自助建站软件,网站原型图展示引言
在多设备协同场景中#xff0c;用户常常面临“通知碎片化”问题#xff1a;
手机收到微信消息#xff0c;但正在用平板看视频#xff1b;智能手表震动提醒日程#xff0c;却无法查看详情#xff1b;电视播放时错过重要来电通知。
OpenHarmony 提供了 分布式通知服…引言在多设备协同场景中用户常常面临“通知碎片化”问题手机收到微信消息但正在用平板看视频智能手表震动提醒日程却无法查看详情电视播放时错过重要来电通知。OpenHarmony 提供了分布式通知服务Distributed Notification Service允许应用将通知智能分发到最合适的设备并支持跨设备聚合、同步状态、一键操作。而 Flutter 可作为统一的 UI 层构建一个“全局通知中心”集中管理来自所有设备的通知。本文将带你从零实现一个跨设备通知聚合与响应系统具备以下能力手机接收通知自动同步至平板/手表平板上可查看、清除、回复手机通知支持通知分类、免打扰策略、历史记录基于设备活跃状态智能路由如灭屏时推送到手表。这是目前社区首篇完整实现 Flutter OpenHarmony 分布式通知协同的实战教程。一、技术原理分布式通知如何工作OpenHarmony 的通知系统通过Notification Distributed SyncNDS实现跨设备同步------------------ ------------------ ------------------ | 手机 | | 平板 | | 手表 | | - App 发送通知 |-----| - 显示相同通知 |-----| - 震动简略提示 | ----------------- DSoftBus ----------------- ----------------- | | | [NotificationManager] [DistributedNotificationCenter] [Wearable UI] | | | ------------ 通知同步通道 --------------------------核心机制通知发布时自动同步只要设备在同一个分布式组内状态双向同步任一设备清除/点击通知其他设备同步更新智能分发策略系统根据设备类型、使用状态决定是否显示安全沙箱仅同应用、同账号设备可同步。✅ 开发者只需调用标准publishAPI无需额外代码即可实现基础同步。但若要自定义聚合逻辑、构建统一通知中心则需深度集成。二、整体架构设计MethodChannel监听订阅Flutter 通知中心 UINotificationPluginDistributedNotificationCenter本地通知远程设备通知通知分类 / 免打扰历史记录数据库关键组件DistributedNotificationCenter原生侧监听本机及远程通知NotificationPlugin桥接 Dart 与原生通知事件统一通知模型标准化不同设备的通知格式本地 SQLite持久化历史通知支持离线查看。三、原生侧监听与转发通知ArkTS1. 权限声明// 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.etsimportnotificationManagerfromohos.notification.notificationManager;importdeviceManagerfromohos.distributedHardware.deviceManager;typeUnifiedNotification{id:number;deviceId:string;// 源设备 IDdeviceName:string;// 源设备名称bundleName:string;// 应用包名title:string;text:string;timestamp:number;isDismissed:boolean;};classDistributedNotificationListener{privatecallback:((notif:UnifiedNotification)void)|nullnull;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){constdismissedNotifthis.normalizeNotification(data,local,本机);dismissedNotif.isDismissedtrue;this.callback(dismissedNotif);}};notificationManager.on(published,onPublished);notificationManager.on(canceled,onCanceled);this.activeSubscriptions.push((){notificationManager.off(published,onPublished);notificationManager.off(canceled,onCanceled);});}// 监听远程设备通知模拟实际需设备主动推送privateasyncsubscribeRemote():Promisevoid{try{constdeviceListawaitdeviceManager.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.callbackcb;}stopListening():void{this.activeSubscriptions.forEach(unsubunsub());this.activeSubscriptions[];}}constlistenernewDistributedNotificationListener();exportdefaultlistener;说明截至 OpenHarmony 4.1远程通知需应用主动共享。本文采用“本地监听 远程设备主动上报”模式。后续版本将支持系统级自动同步。3. 插件层暴露给 Flutter// plugins/NotificationPlugin.etsimportlistenerfrom../services/DistributedNotificationListener;import{MethodChannel,EventChannel}fromflutter/engine;constMETHOD_CHANNELcom.example.flutter/notification/method;constEVENT_CHANNELcom.example.flutter/notification/event;exportclassNotificationPlugin{privateeventSink:anynull;init(){listener.setCallback((notif){if(this.eventSink){this.eventSink.success(notif);}});constmethodChannelnewMethodChannel(METHOD_CHANNEL);methodChannel.setMethodCallHandler(this.handleMethod.bind(this));consteventChannelnewEventChannel(EVENT_CHANNEL);eventChannel.setStreamHandler({onListen:(_,sink)this.eventSinksink,onCancel:()this.eventSinknull});}privateasynchandleMethod(call:any):Promiseany{switch(call.method){casestartListening:listener.startListening();return{success:true};casestopListening:listener.stopListening();return{success:true};casedismissNotification:// 转发清除指令到源设备简化仅本地清除// 实际应通过软总线发送 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.isDismissedfalse,});factoryNotificationItem.fromJson(Mapdynamic,dynamicjson){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,);}MapString,dynamictoJson(){id:id,deviceId:deviceId,deviceName:deviceName,bundleName:bundleName,title:title,text:text,timestamp:timestamp,isDismissed:isDismissed,};}2. 通知服务封装// lib/services/notification_service.dartimportpackage:flutter/services.dart;import../models/notification_item.dart;classNotificationService{staticconst_methodMethodChannel(com.example.flutter/notification/method);staticconst_eventEventChannel(com.example.flutter/notification/event);staticFuturevoidstartListening()async{await_method.invokeMethod(startListening);}staticFuturevoidstopListening()async{await_method.invokeMethod(stopListening);}staticFuturevoiddismissNotification(NotificationItem item)async{await_method.invokeMethod(dismissNotification,item.toJson());}staticStreamNotificationItemonNotification()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.dartimportpackage:hive/hive.dart;partnotification_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.isDismissedfalse,});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 build4. 状态管理聚合实时 历史通知// lib/providers/notification_provider.dartimportpackage:flutter_riverpod/flutter_riverpod.dart;importpackage:hive/hive.dart;import../services/notification_service.dart;import../models/notification_hive.dart;finalnotificationProviderStateNotifierProviderNotificationManager,ListHiveNotification((ref){returnNotificationManager();});classNotificationManagerextendsStateNotifierListHiveNotification{late BoxHiveNotification_box;StreamSubscription?_subscription;NotificationManager():super([]){_init();}Futurevoid_init()async{_boxawaitHive.openBoxHiveNotification(notifications);state_box.values.toList()..sort((a,b)b.timestamp.compareTo(a.timestamp));// 监听新通知_subscriptionNotificationService.onNotification().listen((item){_addOrUpdate(item);});NotificationService.startListening();}void_addOrUpdate(NotificationItem item){finalexisting_box.values.firstWhereOrNull((n)n.iditem.idn.deviceIditem.deviceId);if(existing!null){if(item.isDismissed){existing.isDismissedtrue;existing.save();}// 更新内容如消息追加}else{finalhiveNotifHiveNotification.fromItem(item);_box.add(hiveNotif);state[...state,hiveNotif]..sort((a,b)b.timestamp.compareTo(a.timestamp));}}Futurevoiddismiss(HiveNotification notif)async{notif.isDismissedtrue;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,),);stateList.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){finalnotificationsref.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){finalnotifnotifications[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){finalhashdeviceId.hashCode;returnColor.fromRGBO((hash16)0xFF,(hash8)0xFF,hash0xFF,1.0);}String_formatTime(int timestamp){finalnowDateTime.now();finalthenDateTime.fromMillisecondsSinceEpoch(timestamp);if(now.difference(then).inHours24){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){// 免打扰、分类过滤等设置}}五、高级功能扩展建议智能路由策略检测当前活跃设备通过displayState优先推送至正在使用的设备灭屏时自动推送到手表。跨设备操作在平板上点击“回复”指令通过软总线发送至手机执行支持“稍后提醒”同步到所有设备。隐私保护敏感通知如银行验证码仅在源设备显示可配置同步白名单。六、总结本文实现了Flutter OpenHarmony 分布式通知中心的完整方案解决了多设备通知碎片化问题核心价值包括通知聚合打破设备边界统一查看状态同步任一设备操作全局生效持久化历史离线也可回顾重要通知可扩展架构易于添加智能路由、隐私策略。此系统可广泛应用于家庭数字中枢电视、音箱、手机通知统一管理企业办公PC、平板、手机消息无缝流转健康管理手表告警同步至家属手机。欢迎大家加入开源鸿蒙跨平台开发者社区一起共建开源鸿蒙跨平台生态。