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

Flutter实现每X小时推送通知时应用启动黑屏卡顿问题排查

Android Flutter定时通知导致应用黑屏卡住的问题排查与修复

问题描述

我尝试在Android通知中每X小时显示一段文本,使用生成的代码后,安装到手机后应用黑屏并卡住。以下是当前代码:

main.dart

final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

Future<void> main() async {
  if (!kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS)) {
    sqfliteFfiInit();
    databaseFactory = databaseFactoryFfi;
  }
  WidgetsFlutterBinding.ensureInitialized();
  tz.initializeTimeZones();

  const AndroidInitializationSettings initializationSettingsAndroid =
      AndroidInitializationSettings('@mipmap/ic_launcher');

  const InitializationSettings initializationSettings =
      InitializationSettings(android: initializationSettingsAndroid);

  await flutterLocalNotificationsPlugin.initialize(initializationSettings);
  if (Platform.isAndroid || Platform.isIOS) {
    await NotificationService().scheduleRepeatingNotification();
  }
  runApp(const MyApp());
}

notification_service.dart

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;

class NotificationService {
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();

  Future<void> scheduleRepeatingNotification() async {
    const AndroidNotificationDetails androidDetails =
        AndroidNotificationDetails(
      'channel_id',
      'channel_name',
      channelDescription: 'description',
      importance: Importance.max,
      priority: Priority.high,
    );

    const NotificationDetails platformDetails = NotificationDetails(
      android: androidDetails,
    );

    final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
    final tz.TZDateTime firstNotification =
        now.add(const Duration(hours: 3)); // Start in 3 hours

    await flutterLocalNotificationsPlugin.zonedSchedule(
      0, // ID of the notification
      'Scheduled Notification',
      'This notification repeats every 3 hours.',
      firstNotification,
      platformDetails,
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.absoluteTime,
      matchDateTimeComponents: DateTimeComponents.time, // To repeat at intervals
      androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, // Add this
    );
  }
}

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.1
  sqflite: ^2.0.3
  path: ^1.8.3
  sqflite_common_ffi: ^2.1.0
  flutter_local_notifications: ^18.0.1
  get: ^4.6.5
  cupertino_icons: ^1.0.8
  timezone: ^0.9.0

问题分析

  1. 重复创建未初始化的通知实例:main函数中已经初始化了FlutterLocalNotificationsPlugin并调用了initialize,但NotificationService内部又新建了一个独立实例,这个实例未经过初始化就执行zonedSchedule,会触发异常导致应用阻塞。
  2. 时区配置缺失:仅调用tz.initializeTimeZones()而未设置本地时区,会导致时间解析逻辑出错,引发异步操作卡住。
  3. 潜在图标资源问题:如果Android项目中不存在@mipmap/ic_launcher对应的图标资源,通知初始化时会抛出异常。

修复方案

1. 复用已初始化的通知实例

修改NotificationService通过构造函数接收已初始化的FlutterLocalNotificationsPlugin实例,避免重复创建未初始化对象:

修改后的notification_service.dart

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;

class NotificationService {
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

  // 通过构造函数传入已初始化的实例
  NotificationService(this.flutterLocalNotificationsPlugin);

  Future<void> scheduleRepeatingNotification() async {
    const AndroidNotificationDetails androidDetails =
        AndroidNotificationDetails(
      'channel_id',
      'channel_name',
      channelDescription: 'description',
      importance: Importance.max,
      priority: Priority.high,
    );

    const NotificationDetails platformDetails = NotificationDetails(
      android: androidDetails,
    );

    final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
    final tz.TZDateTime firstNotification =
        now.add(const Duration(hours: 3));

    await flutterLocalNotificationsPlugin.zonedSchedule(
      0,
      '定时通知',
      '每3小时重复一次的通知',
      firstNotification,
      platformDetails,
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.absoluteTime,
      matchDateTimeComponents: DateTimeComponents.time,
      androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
    );
  }
}

2. 配置本地时区

在main函数中初始化时区后,设置本地时区(根据实际地区调整,示例为亚洲上海):

修改后的main.dart片段

WidgetsFlutterBinding.ensureInitialized();
tz.initializeTimeZones();
// 添加本地时区配置
tz.setLocalLocation(tz.getLocation('Asia/Shanghai'));

同时修改调用NotificationService的代码,传入已初始化的实例:

if (Platform.isAndroid || Platform.isIOS) {
  await NotificationService(flutterLocalNotificationsPlugin).scheduleRepeatingNotification();
}

3. 检查补充必要配置

  • 确认Android项目android/app/src/main/res/mipmap目录下存在ic_launcher.png系列图标,或替换为项目中已有的图标资源。
  • 针对Android 13及以上版本,在AndroidManifest.xml中添加通知权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

内容的提问来源于stack exchange,提问作者Ali.Rashidi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:13:17