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
问题分析
- 重复创建未初始化的通知实例:
main函数中已经初始化了FlutterLocalNotificationsPlugin并调用了initialize,但NotificationService内部又新建了一个独立实例,这个实例未经过初始化就执行zonedSchedule,会触发异常导致应用阻塞。 - 时区配置缺失:仅调用
tz.initializeTimeZones()而未设置本地时区,会导致时间解析逻辑出错,引发异步操作卡住。 - 潜在图标资源问题:如果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
相关产品推荐
相关产品推荐

