You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中使用SignalR处理应用关闭时的推送通知

Flutter 后台(应用关闭/锁屏)通知实现方案(基于SignalR + 免费替代方案)

针对你提到的场景——用SignalR做后端、需要处理应用关闭/锁屏时的通知、不想用Firebase,这里给你一套可落地的免费方案:

核心思路

flutter_local_notifications只能处理应用前台/后台未完全关闭的情况,应用彻底关闭时必须依赖系统级推送通道。整体逻辑如下:

  1. 客户端启动时,获取设备的推送令牌,通过SignalR提交给后端保存。
  2. 后端有消息要推送时,先判断用户是否在线(SignalR连接是否存在):
    • 在线:直接通过SignalR发消息,客户端用flutter_local_notifications显示。
    • 离线:调用免费第三方推送服务的API,推送到设备令牌,触发系统级通知。

免费推送服务替代方案

不用Firebase的话,这两个免费方案足够覆盖小型项目需求:

  • OneSignal:免费版每月支持10k推送量,兼容Android/iOS,集成步骤简单,自带后台通知处理逻辑。
  • Pushy:免费版每月5k推送量,支持自定义后端集成,适合需要更灵活控制的场景。

分平台具体实现

Android 端

  1. 集成选定的推送SDK,在AndroidManifest.xml中注册推送接收器,确保应用关闭时能接收系统推送。
  2. 配置flutter_local_notifications的通知渠道(Android 8+强制要求),设置锁屏显示权限:
    const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
      'lock_screen_channel',
      '锁屏通知',
      importance: Importance.max,
      priority: Priority.high,
      visibility: NotificationVisibility.public, // 锁屏显示完整内容
    );
    
  3. Android 12+需动态申请POST_NOTIFICATIONS权限,避免通知被系统拦截。

iOS 端

  1. 在苹果开发者后台申请APNs证书(免费开发者账号可申请开发证书用于测试)。
  2. 集成推送SDK后,在Xcode中开启Remote notifications后台模式,确保应用关闭时系统能接收推送。
  3. 配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 22:47:08