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

Flutter实现App关闭后监听Supabase数据变化并推送通知方案咨询

实现方案:Supabase实时监听+Flutter后台服务推送通知

1. 添加依赖

在pubspec.yaml中加入以下依赖:

dependencies:
  supabase_flutter: ^2.0.0
  flutter_local_notifications: ^16.0.0
  flutter_background_service: ^5.0.0
  flutter_background_service_android: ^5.0.0 # Android专属依赖
  flutter_background_service_ios: ^5.0.0 # iOS专属依赖

2. 初始化后台服务

2.1 编写后台任务逻辑

在项目根目录创建background_service.dart,实现后台监听和通知推送:

import 'dart:async';
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();

Future<void> initializeService() async {
  final service = FlutterBackgroundService();

  // 配置跨平台后台服务
  await service.configure(
    androidConfiguration: AndroidConfiguration(
      onStart: onStart,
      autoStart: true,
      isForegroundMode: true,
      notificationChannelId: 'supabase_notification_channel',
      initialNotificationTitle: '后台监听中',
      initialNotificationContent: '正在监听数据库更新',
      foregroundServiceNotificationId: 888,
    ),
    iosConfiguration: IosConfiguration(
      autoStart: true,
      onForeground: onStart,
      onBackground: onIosBackground,
    ),
  );
}

// Android后台启动回调
@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  // 初始化Supabase(与前台配置保持一致)
  await Supabase.initialize(
    url: '你的Supabase项目URL',
    anonKey: '你的Supabase匿名密钥',
  );

  // 初始化本地通知
  await _initializeNotifications();

  // 监听目标表的新增数据事件
  final supabase = Supabase.instance.client;
  supabase.channel('public:你的目标表名')
    .on(
      RealtimeListenTypes.insert,
      (payload) {
        // 收到新增数据,触发本地通知
        _showNotification('新数据提醒', '数据库新增了一条记录');
      },
    )
    .subscribe();

  // 监听停止指令
  service.on('stop').listen((event) {
    service.stopSelf();
  });
}

// iOS后台回调
@pragma('vm:entry-point')
Future<bool> onIosBackground(ServiceInstance service) async {
  await Supabase.initialize(
    url: '你的Supabase项目URL',
    anonKey: '你的Supabase匿名密钥',
  );
  await _initializeNotifications();

  final supabase = Supabase.instance.client;
  supabase.channel('public:你的目标表名')
    .on(RealtimeListenTypes.insert, (payload) {
      _showNotification('新数据提醒', '数据库新增了一条记录');
    })
    .subscribe();

  return true;
}

// 初始化本地通知配置
Future<void> _initializeNotifications() async {
  const AndroidInitializationSettings androidInitSettings =
      AndroidInitializationSettings('@mipmap/ic_launcher');
  const IosInitializationSettings iosInitSettings =
      IosInitializationSettings();
  const InitializationSettings initSettings =
      InitializationSettings(android: androidInitSettings, iOS: iosInitSettings);
  await _notificationsPlugin.initialize(initSettings);
}

// 显示本地通知
Future<void> _showNotification(String title, String body) async {
  const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
    'supabase_notification_channel',
    'Supabase数据通知',
    importance: Importance.max,
    priority: Priority.high,
  );
  const NotificationDetails notificationDetails =
      NotificationDetails(android: androidDetails);
  await _notificationsPlugin.show(
    0,
    title,
    body,
    notificationDetails,
  );
}

2.2 在main函数启动后台服务

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 启动后台服务
  await initializeService();
  // 初始化前台Supabase
  await Supabase.initialize(
    url: '你的Supabase项目URL',
    anonKey: '你的Supabase匿名密钥',
  );
  runApp(const MyApp());
}

3. 系统权限配置

Android

在android/app/src/main/AndroidManifest.xml中添加权限:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.INTERNET"/>

iOS

在ios/Runner/Info.plist中添加后台模式配置:

<key>UIBackgroundModes</key>
<array>
  <string>fetch</string>
  <string>remote-notification</string>
  <string>processing</string>
</array>

4. 可选:用background_fetch补充定时监听

如果实时WebSocket在极端后台场景下不稳定,可以结合background_fetch定时拉取数据做补充:

// 初始化background_fetch
BackgroundFetch.configure(
  BackgroundFetchConfig(
    minimumFetchInterval: 15, // iOS限制最小15分钟一次
  ),
  (String taskId) async {
    // 拉取最新数据并对比本地记录
    final supabase = Supabase.instance.client;
    final latestData = await supabase.from('你的目标表名')
        .select()
        .limit(1)
        .order('created_at', ascending: false);
    
    // 根据业务逻辑判断是否为新数据,是则推送通知
    if (latestData.isNotEmpty) {
      _showNotification('新数据提醒', '数据库新增了一条记录');
    }
    BackgroundFetch.finish(taskId);
  },
);

注意事项

  • Supabase实时监听依赖WebSocket,后台环境下可能被系统断开,建议结合心跳机制或定时拉取做容错。
  • Android前台服务必须显示通知,无法完全隐藏;iOS后台任务的运行频率和时长受系统严格限制,无法保证100%实时性。
  • 测试后台功能请使用真实设备,模拟器的后台行为与真实设备存在差异。

内容的提问来源于stack exchange,提问作者mohammadmnyer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:03:42