1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Flutter] Flutter: Android local notifications to launch app using Work Manager / Question...

Discussão em 'Mobile' iniciado por Stack, Outubro 9, 2024 às 09:03.

  1. Stack

    Stack Membro Participativo

    I am working on a code that will check a list of items that are loaded from a json file, managed with Riverpod state management, and send local notifications. I read the official documentation on local notifications plugin. I wish to use notifications to inform about the items that are within due date in 3 days. App is working fine but the notification feature. I understand that I need to initialize on main and use the work manager to manage notifications while the app is in deep sleep/not running, but with below approach I am not quite seeing how that would work because the items list is not initialized with riverpod state management yet, but I don't know where to approach to this. Besides running the app gives below error:

    main.dart:

    @pragma('vm:entry-point')
    void callbackDispatcher() {
    Workmanager().executeTask((task, inputData) async {
    await NotificationService().checkDueDate();
    return Future.value(true);
    });
    }

    Future<void> main() async {
    WidgetsFlutterBinding.ensureInitialized();
    NotificationService().initialize();
    Workmanager().initialize(callbackDispatcher);
    Workmanager().registerPeriodicTask(
    "dueDateChecker",
    "dueDateCheckerTask",
    frequency: const Duration(days: 1),
    );
    storage = Storage();
    runApp(ProviderScope(child: MyApp()));
    }


    NotificationService.dart:

    class NotificationService {
    static final NotificationService _instance = NotificationService._internal();
    factory NotificationService() {
    return _instance;
    }
    FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

    NotificationService._internal();
    Future<void> initialize() async {
    const AndroidInitializationSettings initializationSettingsAndroid =
    AndroidInitializationSettings('app_icon');

    const InitializationSettings initializationSettings =
    InitializationSettings(
    android: initializationSettingsAndroid,
    );
    //iOS: initializationSettingsDarwin);

    await flutterLocalNotificationsPlugin.initialize(
    initializationSettings,
    onDidReceiveNotificationResponse: notificationTapForeground,
    onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
    );

    flutterLocalNotificationsPlugin
    .getNotificationAppLaunchDetails()
    .then((NotificationAppLaunchDetails? details) {
    if (details != null && details.didNotificationLaunchApp) {
    print("tapped when app is not running");
    navigatorKey.currentState?.context.push("/inventory");
    // TODO: Handle notification that caused the app to launch
    // You can access details.notificationResponse.payload here
    }
    });
    }
    Future<void> _showNotification(List<Item> items) async {
    const AndroidNotificationDetails androidNotificationDetails =
    AndroidNotificationDetails('0', 'Impending Due Date',
    channelDescription: 'Impending Due Date Notification',
    actions: <AndroidNotificationAction>[
    AndroidNotificationAction('0', 'Go to Inventory'),
    AndroidNotificationAction('1', 'Close'),
    ],
    importance: Importance.max,
    priority: Priority.high,
    ticker: 'ticker');
    const NotificationDetails notificationDetails =
    NotificationDetails(android: androidNotificationDetails);
    String dueItems = items.map((item) => item.name).join(', ');
    await flutterLocalNotificationsPlugin.show(
    0, 'Impending Due Date', 'Your $dueItems is due soon!',
    notificationDetails,
    payload: 'item x');
    }

    Future<void> notificationTapBackground(
    NotificationResponse notificationResponse) async {
    switch (notificationResponse.actionId) {
    case '0':
    navigatorKey.currentState?.context.push("/inventory");
    print('Action 1 was pressed');
    break;
    case '1':
    print('Action 2 was pressed');
    break;
    default:
    // Handle the main notification tap (if the notification itself was tapped, not an action button)
    //print('Notification tapped, payload: ${notificationResponse.payload}');
    }
    }

    Future<void> notificationTapForeground(
    NotificationResponse notificationResponse) async {
    switch (notificationResponse.actionId) {
    case '0':
    navigatorKey.currentState?.context.push("/inventory");
    print('Action 1 was pressed');
    break;
    case '1':
    print('Action 2 was pressed');
    break;
    default:
    // Handle the main notification tap (if the notification itself was tapped, not an action button)
    //print('Notification tapped, payload: ${notificationResponse.payload}');
    }
    }

    Future<void> checkDueDate() async {
    final currentItemList = ProviderContainer().read(jsonInventoryServiceNotifierProvider);
    late var dueDateList;
    currentItemList.when(
    data: (item) {
    dueDateList = item
    .where((element) =>
    element.dueDate != null &&
    element.calculateDueDate() <=
    3)
    .toList();
    },
    loading: () => print("loading.."),
    error: (e, st) => print("error.."),
    );
    _showNotification(dueDateList);
    }
    }


    Error on running the app:

    The backgroundHandler needs to be either a static function or a top level function to be accessible as a Flutter entry point.

    Continue reading...

Compartilhe esta Página