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
相关产品推荐
相关产品推荐

