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

如何使用flutter_local_notifications包在Flutter本地通知中显示当前日期,并实现无需打开APP的每日自动更新?

实现每日自动更新永久通知的日期(无需打开APP)

嘿,这个需求我之前做类似功能的时候踩过坑,其实结合flutter_local_notifications和后台定时任务插件就能完美解决,给你一步步说清楚怎么弄:

核心思路

要实现APP未启动时自动更新通知,光靠flutter_local_notifications不够——它只负责通知的展示,定时触发得靠专门的后台任务插件(比如workmanager)。我们的流程是:

  1. 用后台任务每天定时触发更新逻辑
  2. 更新时先取消旧的永久通知,再发送带当日日期的新永久通知
  3. 处理好平台权限和配置,确保后台任务能正常运行

步骤1:添加依赖

在pubspec.yaml里添加需要的包:

dependencies:
  flutter_local_notifications: ^16.1.0 # 用最新稳定版即可
  workmanager: ^0.5.1 # 后台任务调度插件
  intl: ^0.18.1 # 日期格式化工具

步骤2:初始化通知插件

先把flutter_local_notifications初始化好,确保能正常发送通知:

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:intl/intl.dart';
import 'package:workmanager/workmanager.dart';
import 'package:flutter/foundation.dart';

final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();

Future<void> _initNotifications() async {
  // Android初始化配置
  const AndroidInitializationSettings androidInitSettings =
      AndroidInitializationSettings('@mipmap/ic_launcher'); // 替换成你的通知图标
  // iOS初始化配置(可选,按需添加)
  const IOSInitializationSettings iosInitSettings = IOSInitializationSettings();
  
  const InitializationSettings initSettings = InitializationSettings(
    android: androidInitSettings,
    iOS: iosInitSettings
  );
  
  // 初始化插件
  await _notificationsPlugin.initialize(initSettings);

  // iOS主动请求通知权限
  if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.iOS) {
    await _notificationsPlugin.requestPermissions(
      alert: true,
      badge: true,
      sound: true,
    );
  }
}

步骤3:配置后台定时任务

用workmanager注册一个每日重复的任务,用来触发通知更新:

// 后台任务的回调函数,必须是顶级函数或静态函数
void _backgroundTaskDispatcher() {
  Workmanager().executeTask((taskName, inputData) async {
    // 执行通知更新逻辑
    await _updateDailyDateNotification();
    return Future.value(true); // 返回true表示任务执行成功
  });
}

Future<void> _initWorkmanager() async {
  await Workmanager().initialize(
    _backgroundTaskDispatcher,
    isInDebugMode: false, // 发布版设为false
  );

  // 注册每日重复任务,比如每天早上8点自动更新
  await Workmanager().registerPeriodicTask(
    'daily_date_notification_task', // 唯一任务ID,不能重复
    'update_date_notification', // 任务标识,和回调内的taskName对应
    frequency: const Duration(days: 1), // 重复周期为1天
    initialDelay: Duration(
      hours: 8 - DateTime.now().hour,
      minutes: -DateTime.now().minute,
      seconds: -DateTime.now().second,
    ), // 计算距离下一个8点的延迟,若已过8点则自动延后到次日
    constraints: const Constraints(
      networkType: NetworkType.not_required, // 无需网络也能执行
    ),
  );
}

步骤4:实现通知更新逻辑

这里要注意:永久通知(ongoing: true)不能直接覆盖,必须先取消旧的,再发送新的:

Future<void> _updateDailyDateNotification() async {
  // 配置Android通知参数,设置为永久不可移除
  const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
    'daily_date_channel_id', // 渠道ID,唯一值
    '每日日期通知', // 渠道名称
    channelDescription: '自动更新当前日期的永久通知',
    importance: Importance.max,
    priority: Priority.high,
    ongoing: true, // 关键:设置为永久不可移除状态
    autoCancel: false,
  );
  // iOS通知配置
  const IOSNotificationDetails iosDetails = IOSNotificationDetails(
    presentAlert: true,
    presentBadge: false,
  );
  
  const NotificationDetails notificationDetails = NotificationDetails(
    android: androidDetails,
    iOS: iosDetails
  );

  // 先取消之前的通知(如果存在)
  await _notificationsPlugin.cancel(0); // 用固定的通知ID,比如0

  // 格式化当前日期,可自定义格式
  String currentDate = DateFormat('yyyy年MM月dd日 EEEE').format(DateTime.now());

  // 发送新的永久通知
  await _notificationsPlugin.show(
    0, // 用同一个ID,确保替换旧通知
    currentDate, // 通知标题显示日期
    '今日日期', // 通知内容
    notificationDetails,
  );
}

步骤5:在APP启动时初始化

在main函数里完成所有初始化,并且第一次启动就显示通知:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化通知和后台任务
  await _initNotifications();
  await _initWorkmanager();
  
  // 首次启动先显示通知
  await _updateDailyDateNotification();

  runApp(const MyApp());
}

平台特殊配置

Android端

在android/app/src/main/AndroidManifest.xml里添加权限和Workmanager配置:

<!-- 添加必要权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

<application ...>
  <!-- 禁用Workmanager的自动初始化,避免冲突 -->
  <provider
      android:name="androidx.startup.InitializationProvider"
      android:authorities="${applicationId}.androidx-startup"
      android:exported="false"
      tools:node="merge">
      <meta-data
          android:name="androidx.work.WorkManagerInitializer"
          android:value="androidx.startup"
          tools:node="remove"/>
  </provider>
  
  <!-- 注册Workmanager服务 -->
  <service
      android:name="be.tramckrijte.workmanager.WorkmanagerService"
      android:permission="android.permission.BIND_JOB_SERVICE"
      android:exported="false"/>
</application>

iOS端

在ios/Runner/Info.plist里添加后台模式权限:

<key>UIBackgroundModes</key>
<array>
  <string>processing</string>
</array>

注意事项

  • 安卓API 26+对后台任务有严格限制,Workmanager会自动适配,但如果APP被用户强制关闭,任务可能暂停。
  • iOS的后台任务触发间隔不一定完全精准,系统会根据设备状态调整,但基本能保证每日更新。
  • 测试后台任务时,安卓可以用Workmanager的调试命令手动触发,iOS可以用Xcode的后台模拟功能。

内容的提问来源于stack exchange,提问作者Mr. ZeroOne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 03:47:27