Flutter安卓应用:实现未启动一周才触发每周通知
实现仅当应用一周未打开时触发的每周通知(Android)
核心思路
放弃原有的固定重复通知方案,改用「后台定时检查+条件触发」的逻辑:
- 持久化存储应用最后活跃时间
- 用后台任务每周检查一次时间差
- 仅当时间差≥7天时触发通知
1. 添加必要依赖
在pubspec.yaml中补充依赖:
dependencies: flutter_local_notifications: ^latest_version shared_preferences: ^latest_version workmanager: ^latest_version
2. 记录应用最后活跃时间
在应用入口监听生命周期,每次回到前台时更新最后活跃时间:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); // 首次打开应用时记录当前时间 await updateLastActiveTime(); runApp(const MyApp()); } Future<void> updateLastActiveTime() async { final prefs = await SharedPreferences.getInstance(); await prefs.setInt('last_active_timestamp', DateTime.now().millisecondsSinceEpoch); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // 应用从后台回到前台时更新活跃时间 if (state == AppLifecycleState.resumed) { updateLastActiveTime(); } } @override Widget build(BuildContext context) { return MaterialApp( title: '你的应用', home: const YourHomeScreen(), ); } }
3. 配置后台定时任务(Workmanager)
用Workmanager实现每周一次的后台检查逻辑:
import 'package:workmanager/workmanager.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'notification_service.dart'; void callbackDispatcher() { Workmanager().executeTask((task, inputData) async { await checkAndSendNotification(); return Future.value(true); }); } Future<void> checkAndSendNotification() async { final prefs = await SharedPreferences.getInstance(); final lastActiveTimestamp = prefs.getInt('last_active_timestamp'); if (lastActiveTimestamp == null) return; final lastActiveTime = DateTime.fromMillisecondsSinceEpoch(lastActiveTimestamp); final now = DateTime.now(); final difference = now.difference(lastActiveTime); // 超过7天(604800秒)则触发通知 if (difference.inSeconds >= 604800) { final notificationService = NotificationService(); await notificationService.showReminderNotification(); } } // 初始化Workmanager void initWorkmanager() { Workmanager().initialize( callbackDispatcher, isInDebugMode: false, // 发布版本改为false ); // 注册每周执行的任务 Workmanager().registerPeriodicTask( 'weekly_reminder_task', 'check_app_activity', frequency: const Duration(days: 7), initialDelay: const Duration(days: 7), // 首次执行延迟7天 constraints: Constraints( networkType: NetworkType.not_required, requiresBatteryNotLow: false, ), ); }
在main函数中添加初始化调用:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await updateLastActiveTime(); await NotificationService().initNotification(); initWorkmanager(); runApp(const MyApp()); }
4. 修改NotificationService适配逻辑
替换原有的重复通知方法,改为单次触发的通知:
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; class NotificationService { final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> initNotification() async { const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@drawable/sn_invent'); const InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await notificationsPlugin.initialize(initializationSettings); // 请求必要权限 await notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.requestNotificationsPermission(); await notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.requestExactAlarmsPermission(); } // 满足条件时触发的单次通知 Future<void> showReminderNotification() async { const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails( 'reminder_channel_id', '应用提醒', channelDescription: '当应用一周未打开时发送的提醒', importance: Importance.high, priority: Priority.high, icon: '@drawable/sn_invent', ); const NotificationDetails notificationDetails = NotificationDetails(android: androidNotificationDetails); await notificationsPlugin.show( 0, 'Ziele in Angriff genommen?', 'Schau doch gerne mal wieder deinen Zielplan an', notificationDetails, androidAllowWhileIdle: true, ); } }
关键注意事项
- Android权限配置:在
AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
- 后台任务限制:Android 12+对后台任务有延迟限制,每周一次的任务属于低频率,可正常执行。
- 测试技巧:开发阶段可将Workmanager的
frequency改为几分钟,验证逻辑正常后再改回7天。
内容的提问来源于stack exchange,提问作者user19922759
相关产品推荐
相关产品推荐

