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

Flutter安卓应用:实现未启动一周才触发每周通知

实现仅当应用一周未打开时触发的每周通知(Android)

核心思路

放弃原有的固定重复通知方案,改用「后台定时检查+条件触发」的逻辑:

  1. 持久化存储应用最后活跃时间
  2. 用后台任务每周检查一次时间差
  3. 仅当时间差≥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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:46:15