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

Flutter任务应用:应用关闭时如何定时触发Alert Dialog?

解决方案:Flutter任务应用后台/关闭状态下触发弹窗提醒

首先明确核心限制:当应用完全关闭时,Flutter引擎并未运行,无法直接弹出Flutter的Alert Dialog。必须结合系统通知+应用唤起后的弹窗逻辑来实现需求,以下是具体步骤:

1. 依赖配置

添加本地通知和FCM相关依赖到pubspec.yaml:

dependencies:
  flutter_local_notifications: ^16.1.0
  firebase_messaging: ^14.6.5

2. 初始化本地通知与FCM

本地通知用于统一处理前台/后台的通知展示,FCM负责接收云端下发的任务提醒消息。

初始化本地通知

final FlutterLocalNotificationsPlugin _localNotifications = FlutterLocalNotificationsPlugin();
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

Future<void> initLocalNotifications() async {
  // Android初始化配置
  const AndroidInitializationSettings androidSettings =
      AndroidInitializationSettings('@mipmap/ic_launcher');
  // iOS初始化配置(申请权限)
  final DarwinInitializationSettings iosSettings = DarwinInitializationSettings(
    requestAlertPermission: true,
    requestSoundPermission: true,
    requestBadgePermission: true,
  );

  final InitializationSettings settings = InitializationSettings(
    android: androidSettings,
    iOS: iosSettings,
  );

  // 配置通知点击回调
  await _localNotifications.initialize(settings,
      onDidReceiveNotificationResponse: (response) {
    if (response.payload != null) {
      showTaskReminderDialog();
    }
  });
}

配置FCM消息处理

Future<void> setupFirebaseMessaging() async {
  FirebaseMessaging messaging = FirebaseMessaging.instance;

  // 请求通知权限
  await messaging.requestPermission(
    alert: true,
    sound: true,
    badge: true,
  );

  // 前台收到消息:直接弹窗+展示本地通知
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    showTaskReminderDialog();
    _showLocalNotification(message);
  });

  // 后台点击通知唤起应用:弹窗
  FirebaseMessaging.onMessageOpenedApp.listen((_) => showTaskReminderDialog());

  // 应用完全关闭时,点击通知唤起:初始化时检查并弹窗
  RemoteMessage? initialMessage = await messaging.getInitialMessage();
  if (initialMessage != null) {
    showTaskReminderDialog();
  }
}

// 展示本地通知
void _showLocalNotification(RemoteMessage message) async {
  const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
    'task_reminder_channel',
    '任务提醒',
    channelDescription: '定时任务到期通知',
    importance: Importance.max,
    priority: Priority.high,
  );
  const DarwinNotificationDetails iosDetails = DarwinNotificationDetails();
  const NotificationDetails notificationDetails = NotificationDetails(
    android: androidDetails,
    iOS: iosDetails,
  );

  await _localNotifications.show(
    DateTime.now().millisecondsSinceEpoch % 10000,
    message.notification?.title ?? '任务到期',
    message.notification?.body ?? '您的定时任务已到执行时间',
    notificationDetails,
    payload: message.data['task_id'], // 携带任务标识,方便后续处理
  );
}

3. 实现弹窗逻辑

使用全局navigatorKey解决无BuildContext时的弹窗问题:

void showTaskReminderDialog() {
  if (navigatorKey.currentContext == null) return;

  showDialog(
    context: navigatorKey.currentContext!,
    barrierDismissible: false,
    builder: (context) => AlertDialog(
      title: const Text('任务提醒'),
      content: const Text('您设置的任务已到执行时间!'),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('知道了'),
        ),
      ],
    ),
  );
}

4. 应用入口初始化

在main函数中完成所有初始化:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await initLocalNotifications();
  await setupFirebaseMessaging();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,
      title: '任务管理应用',
      home: const HomePage(),
    );
  }
}

关键注意事项

  • 应用完全关闭时,必须通过点击系统通知唤起应用才能触发弹窗,这是系统级限制,无法绕过
  • iOS需在Info.plist中配置通知权限相关字段,Android需在AndroidManifest.xml中注册通知渠道
  • 发送FCM消息时,建议使用数据消息而非纯通知消息,这样可以携带自定义任务标识,方便后续业务处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 06:30:27