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

Flutter本地通知每日重复相同内容问题求助

解决Flutter每日本地通知内容不更新的问题

你的问题核心在于使用了periodicallyShow方法——这个方法会一次性将初始传入的标题和内容缓存,后续重复推送时只会复用这些固定值,不会重新执行随机获取内容的逻辑。要实现每日不同的通知内容,需要改用定时触发任务+单次通知的方案,具体步骤如下:

1. 替换periodicallyShow为单次通知方法

首先修改你的NotificationService,添加一个单次显示通知的方法(原showNotification可以保留,但不再用它做周期推送):

Future<void> showSingleNotification(int id, String title, String body) async {
  await flutterLocalNotificationsPlugin.show(
    id,
    title,
    body,
    const NotificationDetails(
      android: AndroidNotificationDetails('main_channel', 'Main Channel',
          channelDescription: "notfi",
          importance: Importance.max,
          priority: Priority.max),
      iOS: DarwinNotificationDetails(
        sound: 'default.wav',
        presentAlert: true,
        presentBadge: true,
        presentSound: true,
      ),
    ),
    androidAllowWhileIdle: true,
  );
}

2. 使用后台定时任务触发每日通知

由于需要在App可能关闭的情况下仍能触发每日通知,推荐使用workmanager插件处理后台定时任务(支持Android和iOS)。

步骤2.1 添加依赖

在pubspec.yaml中添加:

dependencies:
  workmanager: ^0.5.1
  shared_preferences: ^2.2.2 # 用来存储userPost,后台任务无法直接访问widget属性

步骤2.2 初始化Workmanager并编写任务回调

在main.dart中初始化Workmanager,编写后台任务的回调逻辑(这里会重新生成随机内容并显示通知):

import 'package:workmanager/workmanager.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    // 1. 初始化通知插件(后台任务中需重新初始化)
    final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
        FlutterLocalNotificationsPlugin();
    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('@mipmap/ic_launcher');
    const DarwinInitializationSettings initializationSettingsIOS =
        DarwinInitializationSettings();
    const InitializationSettings initializationSettings =
        InitializationSettings(
            android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
    await flutterLocalNotificationsPlugin.initialize(initializationSettings);

    // 2. 随机获取通知内容
    final List<String> names = ["内容1", "内容2", "内容3", "内容4"]; // 替换为你的列表
    final random = Random();
    final randomName = names[random.nextInt(names.length)];

    // 3. 读取userPost(从本地存储获取,后台无法访问widget)
    final prefs = await SharedPreferences.getInstance();
    final userPost = prefs.getString('user_post') ?? '';

    // 4. 显示单次通知
    await flutterLocalNotificationsPlugin.show(
      1,
      '$randomName$userPost',
      randomName,
      const NotificationDetails(
        android: AndroidNotificationDetails('main_channel', 'Main Channel',
            channelDescription: "notfi",
            importance: Importance.max,
            priority: Priority.max),
        iOS: DarwinNotificationDetails(
          sound: 'default.wav',
          presentAlert: true,
          presentBadge: true,
          presentSound: true,
        ),
      ),
      androidAllowWhileIdle: true,
    );

    return Future.value(true);
  });
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化Workmanager
  await Workmanager().initialize(
    callbackDispatcher,
    isInDebugMode: false, // 发布版本设为false
  );
  runApp(const MyApp());
}

步骤2.3 注册每日定时任务

修改按钮点击事件,将原来调用periodicallyShow的逻辑替换为注册每日任务(同时存储userPost到本地):

onPressed: () async {
  showToast();
  
  // 1. 将userPost存储到本地,供后台任务读取
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString('user_post', widget.userPost);

  // 2. 取消之前的任务(避免重复注册)
  await Workmanager().cancelAll();

  // 3. 注册每日任务,比如每天早上8点触发
  final now = DateTime.now();
  DateTime scheduledTime = DateTime(now.year, now.month, now.day, 8, 0, 0);
  if (scheduledTime.isBefore(now)) {
    scheduledTime = scheduledTime.add(const Duration(days: 1));
  }
  final initialDelay = scheduledTime.difference(now);

  await Workmanager().registerPeriodicTask(
    'daily_notification_task', // 任务唯一标识
    'daily_notification', // 任务名称(需和回调中对应)
    frequency: const Duration(days: 1), // 周期1天
    initialDelay: initialDelay, // 第一次触发的延迟时间
    constraints: const Constraints(
      networkType: NetworkType.not_required, // 不需要网络
    ),
  );
},

3. 平台适配注意事项

  • Android:需在AndroidManifest.xml中添加后台权限和配置,确保应用在后台能被唤醒,具体参考workmanager官方文档。
  • iOS:在Info.plist中添加UIBackgroundModes,包含fetch和remote-notification;另外iOS的系统限制可能会影响定时任务的精准度,需要实际测试验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:06:13