Flutter应用完全关闭时如何显示本地通知(无需Firebase)
解决方案:无需Firebase实现应用完全关闭后的定时任务与通知
针对Android平台
WorkManager本身支持应用关闭后的任务执行,你遇到的问题可通过以下方式修复:
- 确保初始化时机正确:在Android原生
MainApplication的onCreate方法中初始化WorkManager,而非仅在Flutter页面初始化,保证应用首次启动就完成任务注册:override fun onCreate() { super.onCreate() WorkManager.initialize(this, Configuration.Builder().build()) // 此处可提前调度周期性任务 } - 规避系统后台限制:国产ROM(小米、华为等)存在严格的后台管控,需引导用户将应用加入后台白名单,可通过代码跳转至电池优化设置页:
val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) intent.data = Uri.parse("package:" + packageName) startActivity(intent) - 正确配置周期性任务:设置
persist: true保证设备重启后任务不丢失,同时遵循Android最短15分钟的周期限制:final periodicTask = PeriodicWorkRequest( myTask, repeatInterval: Duration(hours: 24), initialDelay: Duration(minutes: 1), constraints: Constraints(networkType: NetworkType.none), ); await Workmanager().registerPeriodicTask( 'daily_db_check', 'dailyTask', existingWorkPolicy: ExistingWorkPolicy.replace, persist: true, );
针对iOS平台
iOS后台执行机制更严格,需依赖BGTaskScheduler配合WorkManager实现:
- 配置后台权限:在Xcode的
Signing & Capabilities中添加Background Modes,勾选Background fetch和Background processing,或直接在Info.plist中添加UIBackgroundModes数组包含对应项。 - 原生侧注册任务:在
AppDelegate中完成后台任务的注册与调度,确保应用启动时就完成配置:import UIKit import Flutter import workmanager import BackgroundTasks @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { GeneratedPluginRegistrant.register(with: self) WorkmanagerPlugin.registerTask(withIdentifier: "dailyTask") BGTaskScheduler.shared.register(forTaskWithIdentifier: "dailyTask", using: nil) { task in self.handleBackgroundTask(task: task as! BGAppRefreshTask) } self.scheduleNextTask() return super.application(application, didFinishLaunchingWithOptions: launchOptions) } func handleBackgroundTask(task: BGAppRefreshTask) { WorkmanagerPlugin.sharedPlugin?.executeTask(withIdentifier: "dailyTask", input: nil, completionHandler: { success in task.setTaskCompleted(success: success) }) self.scheduleNextTask() } func scheduleNextTask() { let request = BGAppRefreshTaskRequest(identifier: "dailyTask") request.earliestBeginDate = Date(timeIntervalSinceNow: 24*60*60) do { try BGTaskScheduler.shared.submit(request) } catch { print("调度任务失败: \(error)") } } } - 注意iOS限制:iOS无法保证任务精确执行,系统会根据设备电量、使用场景调度,应用完全关闭后仅在系统允许后台唤醒时触发任务。
跨平台通用要点
- 数据库路径正确性:后台任务中访问sqflite时,使用绝对路径初始化数据库,避免上下文差异导致的路径错误:
final dbPath = await getDatabasesPath(); final database = await openDatabase(join(dbPath, 'your_db.db')); - 通知权限与渠道配置:Android 8.0+需提前创建通知渠道,iOS需主动请求通知权限,确保后台能正常展示通知:
if (Platform.isAndroid) { const AndroidNotificationChannel channel = AndroidNotificationChannel( 'daily_alert_channel', '每日提醒', description: '数据库检查结果通知', importance: Importance.high, ); final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel); }
内容的提问来源于stack exchange,提问作者Matteo Preda
相关产品推荐
相关产品推荐

