如何在Flutter中使用SignalR处理应用关闭时的推送通知
Flutter 后台(应用关闭/锁屏)通知实现方案(基于SignalR + 免费替代方案)
针对你提到的场景——用SignalR做后端、需要处理应用关闭/锁屏时的通知、不想用Firebase,这里给你一套可落地的免费方案:
核心思路
flutter_local_notifications只能处理应用前台/后台未完全关闭的情况,应用彻底关闭时必须依赖系统级推送通道。整体逻辑如下:
- 客户端启动时,获取设备的推送令牌,通过SignalR提交给后端保存。
- 后端有消息要推送时,先判断用户是否在线(SignalR连接是否存在):
- 在线:直接通过SignalR发消息,客户端用flutter_local_notifications显示。
- 离线:调用免费第三方推送服务的API,推送到设备令牌,触发系统级通知。
免费推送服务替代方案
不用Firebase的话,这两个免费方案足够覆盖小型项目需求:
- OneSignal:免费版每月支持10k推送量,兼容Android/iOS,集成步骤简单,自带后台通知处理逻辑。
- Pushy:免费版每月5k推送量,支持自定义后端集成,适合需要更灵活控制的场景。
分平台具体实现
Android 端
- 集成选定的推送SDK,在
AndroidManifest.xml中注册推送接收器,确保应用关闭时能接收系统推送。 - 配置flutter_local_notifications的通知渠道(Android 8+强制要求),设置锁屏显示权限:
const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'lock_screen_channel', '锁屏通知', importance: Importance.max, priority: Priority.high, visibility: NotificationVisibility.public, // 锁屏显示完整内容 ); - Android 12+需动态申请
POST_NOTIFICATIONS权限,避免通知被系统拦截。
iOS 端
- 在苹果开发者后台申请APNs证书(免费开发者账号可申请开发证书用于测试)。
- 集成推送SDK后,在Xcode中开启
Remote notifications后台模式,确保应用关闭时系统能接收推送。 - 配置flutter_local_notifications的iOS初始化设置,允许通知权限:
const DarwinInitializationSettings iosSettings = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, );
结合SignalR的代码示例
1. 初始化通知插件与推送服务
final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> initNotificationSetup() async { // 初始化flutter_local_notifications const AndroidInitializationSettings androidInit = AndroidInitializationSettings('@mipmap/ic_launcher'); const DarwinInitializationSettings iosInit = DarwinInitializationSettings(); await _notificationsPlugin.initialize(const InitializationSettings( android: androidInit, iOS: iosInit, )); // 初始化OneSignal(示例) OneSignal.initialize("你的OneSignal App ID"); // 前台收到推送时,用自定义插件显示 OneSignal.Notifications.addForegroundWillDisplayListener((event) { _showNotification(event.notification.title!, event.notification.body!); event.preventDefault(); // 禁用OneSignal默认通知样式 }); } // 通用通知显示方法 Future<void> _showNotification(String title, String body) async { await _notificationsPlugin.show( DateTime.now().millisecondsSinceEpoch, title, body, const NotificationDetails( android: AndroidNotificationDetails( 'main_channel', '主通知渠道', importance: Importance.max, ), ), ); }
2. 推送令牌提交到SignalR后端
final HubConnection _hubConnection = HubConnectionBuilder() .withUrl('你的SignalR服务地址') .build(); Future<void> connectSignalRAndRegisterToken() async { await _hubConnection.start(); // 获取OneSignal推送令牌 final pushSubscription = await OneSignal.User.pushSubscription; // 提交令牌到后端,关联当前用户 await _hubConnection.invoke('RegisterPushToken', args: [pushSubscription.token, '当前用户ID']); }
3. 后端逻辑(伪代码)
// SignalR Hub中的方法,保存用户与令牌的关联 public async Task RegisterPushToken(string token, string userId) { // 保存到数据库或缓存 await _pushTokenRepository.SaveToken(userId, token); } // 发送通知的方法 public async Task SendNotification(string userId, string title, string body) { // 检查用户是否在线 var connectionIds = _hubContext.Clients.User(userId).ConnectionIds; if (connectionIds.Any()) { // 在线则通过SignalR发送 await _hubContext.Clients.User(userId).SendAsync("ReceiveNotification", title, body); } else { // 离线则调用推送服务API var token = await _pushTokenRepository.GetToken(userId); await _pushService.SendPush(token, title, body); } }
关键注意事项
- 免费推送服务的额度:根据项目规模选择,OneSignal的免费版足够大部分小型应用使用。
- Android后台存活:Android 10+对后台进程限制严格,建议查看推送SDK文档,配置避免接收器被系统杀死的策略。
- iOS测试:必须用真实设备测试推送,模拟器无法接收APNs通知。
内容的提问来源于stack exchange,提问作者e Res
相关产品推荐
相关产品推荐

