2

I am using flutter_local_notification and workmanager plugins in order to run some background code when a notification is generated (only Android). This is how flutter_local_notification is initialised:

final StreamController<ReceivedNotification> didReceiveLocalNotificationSubject = StreamController<ReceivedNotification>.broadcast();

Future<void> init() async {
    await _configureLocalTimeZone();

    notificationAppLaunchDetails = await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
    if (notificationAppLaunchDetails!.didNotificationLaunchApp) {
      selectedNotificationPayload = notificationAppLaunchDetails!.notificationResponse?.payload;
    }

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

    InitializationSettings initializationSettings = const InitializationSettings(
      android: initializationSettingsAndroid,
    );
    await flutterLocalNotificationsPlugin.initialize(
        initializationSettings,
        onDidReceiveNotificationResponse:
            (NotificationResponse notificationResponse) {
          switch (notificationResponse.notificationResponseType) {
            case NotificationResponseType.selectedNotification:
            case NotificationResponseType.selectedNotificationAction:
              // if (notificationResponse.actionId == navigationActionId) {
                selectNotificationSubject.add(notificationResponse.payload);
                selectedNotificationPayload = notificationResponse.payload;
              // }
                didReceiveLocalNotificationSubject.add(
                  ReceivedNotification(
                    id: notificationResponse.id!,
                    title: notificationResponse.actionId,
                    body: 'stuff',
                    payload: notificationResponse.payload,
                  ),
                );
              break;
          }
      },
      // onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
    );

    _notificationsEnabled = await _isAndroidPermissionGranted();
    _notificationsEnabled = await _requestPermissions();
    _configureDidReceiveLocalNotificationSubject();
  }

and this is the code that gets executed with Workmanager:

void _configureDidReceiveLocalNotificationSubject() {
    didReceiveLocalNotificationSubject.stream
        .listen((ReceivedNotification receivedNotification) async {
          var title = receivedNotification.title ?? 'UNKNOWN';
          Workmanager().registerOneOffTask(
            "my.simpleTask",
            "my.simpleTask",
            inputData: <String, dynamic>{
              'string': title,
            },
          );
        });
  }

Currently I have two problems with that code:

  • the Workmanager's task is run only when the user tap the notification
  • the Workmanager's task won't be executed if the app is terminated by the user first, even if the notification is generated (and tapped)

How can I make the Workmanager's task to be executed as soon as the notification is generated (without the user tapping) with the application terminated or not?

Randomize
  • 8,651
  • 18
  • 78
  • 133

1 Answers1

1

i assume you are scheduled local notification and execute some function in there.

TL:DR

  • first: scheduled local notification not able to execute function in background

eg:

int randomInt = Random().nextInt();
await flutterLocalNotificationsPlugin.zonedSchedule(
    0,
    'scheduled notif with int $randomInt',
     ....

when you are registed this notif, you will get randomInt, and then on the notification it will show the int that you get first time its scheduled. which means, its only show notification,Random().nextInt is not executed.

  • secondly,
void _configureDidReceiveLocalNotificationSubject() {
    didReceiveLocalNotificationSubject.stream

stream function will be terminated too after the apps is killed. except you are bring it into foreground. the stream will keep listening any changes.


How can I make the Workmanager's task to be executed as soon as the notification is generated

I think you are missed on this part. the correct way is: Register Workmanager and then inside the callback function, you can generated local notification.

  • register your WM in your initState
Workmanager().registerOneOffTask(
  "task-identifier",
  simpleTaskKey,
  initialDelay: Duration(minutes: 30), // you can use this delay for scheduling
);

then in the callback funtion generete local notificaiton

@pragma('vm:entry-point')
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) {
   // you function execute here
   // eg: final tempInt = Random.nextInt();
   // then we can use the tempInt 

    show local notification function here
    return Future.value(true);
  });
}
pmatatias
  • 3,491
  • 3
  • 10
  • 30
  • Thank you for the answer. Are you saying that the "scheduler" that drives should be the one from WM and not the one from flutter_local_notification, as only the former can execute tasks when the app is offline? – Randomize Dec 28 '22 at 06:29
  • In that case I do not need to use "zoneSchedule" from f_l_n and show the notification straight away as soon as VM receive the own notification. – Randomize Dec 28 '22 at 06:37
  • yes correct. we need `callback` to execute function in the background. FLN have `onTapHandler`. which means function will execute only when user tap on the notif. – pmatatias Dec 28 '22 at 08:39
  • but different with FCM, the it has a `_firebaseMessagingBackgroundHandler`. with this we can execute function after received notification. – pmatatias Dec 28 '22 at 08:40
  • works thanks! BTW FCM allows you to create more complicated timeframes for scheduling for example: if time is between 8.00AM and 8.00PM and it is Tuesday or Friday then send notification hourly? – Randomize Dec 28 '22 at 09:12