flutterawesome-notifications

How to work with ActionType.SilentBackgroundAction in awesome notification?


When using NotificationActionButton type by ActionType.SilentBackgroundAction, clicking on the action button, I am getting this error "A background message could not be handled in Dart because there is no dart background handler registered.". How to fix it?

My notification controller is as followed,

class NotificationService {
  static ReceivedAction? initialAction;
  static Future<void> initializeNotification() async {
    await initializeIsolateReceivePort();
    await AwesomeNotifications().initialize(
      null,
      [
        NotificationChannel(
          channelGroupKey: NotificationConstants.timerChannelGroup,
          channelKey: NotificationConstants.timerChannel,
          channelName: NotificationConstants.timerChannel,
          channelDescription: NotificationConstants.timerChannelDescription,
          importance: NotificationImportance.High,
          channelShowBadge: true,
          onlyAlertOnce: true,
          playSound: true,
        )
      ],
      channelGroups: [
        NotificationChannelGroup(
          channelGroupKey: NotificationConstants.timerChannelGroup,
          channelGroupName: 'Group 1',
        )
      ],
    );

    // await AwesomeNotifications().isNotificationAllowed().then(
    //   (isAllowed) async {
    //     if (!isAllowed) {
    //       await AwesomeNotifications().requestPermissionToSendNotifications();
    //     }
    //   },
    // );

    await AwesomeNotifications().setListeners(
      onActionReceivedMethod: onActionReceivedMethod,
      onNotificationCreatedMethod: onNotificationCreatedMethod,
      onNotificationDisplayedMethod: onNotificationDisplayedMethod,
      onDismissActionReceivedMethod: onDismissActionReceivedMethod,
    );

    await interceptInitialCallActionRequest();
  }

  static ReceivePort? receivePort;
  static Future<void> initializeIsolateReceivePort() async {
    receivePort = ReceivePort('Notification action port in main isolate');
    receivePort!.listen((serializedData) {
      safePrint("received in background $serializedData");
      final receivedAction = ReceivedAction().fromMap(serializedData);
      handleNavigation(rootNavigatorKey.currentContext ,receivedAction);
    });

    // This initialization only happens on main isolate
    IsolateNameServer.registerPortWithName(
        receivePort!.sendPort,
        'notification_action_port');
  }

  static Future<void> interceptInitialCallActionRequest() async {
    initialAction = await AwesomeNotifications().getInitialNotificationAction();
    safePrint("Initial Action ${initialAction?.payload}");
  }

  /// Use this method to detect when a new notification or a schedule is created
  @pragma("vm:entry-point")
  static Future<void> onNotificationCreatedMethod(ReceivedNotification receivedNotification) async {
    safePrint('onNotificationCreatedMethod');
  }

  /// Use this method to detect every time that a new notification is displayed
  @pragma("vm:entry-point")
  static Future<void> onNotificationDisplayedMethod(ReceivedNotification receivedNotification) async {
    safePrint('onNotificationDisplayedMethod');
  }

  /// Use this method to detect if the user dismissed a notification
  @pragma("vm:entry-point")
  static Future<void> onDismissActionReceivedMethod(ReceivedAction receivedAction) async {
    safePrint('onDismissActionReceivedMethod');
  }

  /// Use this method to detect when the user taps on a notification or action button
  @pragma("vm:entry-point")
  static Future<void> onActionReceivedMethod(ReceivedAction receivedAction) async {
    safePrint('onActionReceivedMethod');
    if (receivePort != null) {
      handleNavigation(rootNavigatorKey.currentContext, receivedAction);
    } else {
      safePrint('onActionReceivedMethod was called inside a parallel dart isolate, where receivePort was never initialized.');
      SendPort? sendPort = IsolateNameServer
          .lookupPortByName('notification_action_port');

      if (sendPort != null) {
        safePrint('Redirecting the execution to main isolate process in listening...');
        dynamic serializedData = receivedAction.toMap();
        sendPort.send(serializedData);
      }
    }
    // safePrint("payload ${receivedAction.payload}, button key ${receivedAction.buttonKeyPressed.length}");
    // handleNavigation(rootNavigatorKey.currentContext, receivedAction);
  }

  static void handleNavigation(BuildContext? context, ReceivedAction receivedAction) async {
    ForegroundService service = serviceLocator.get();
    if (receivedAction.payload != null) {
      //some logic for navigation and background function
    }
  }

  static Future<void> showNotification({
    required final String title,
    required final String body,
    final Map<String, String>? payload,
    final List<NotificationActionButton>? actionButtons
  }) async {

    await AwesomeNotifications().createNotification(
      content: NotificationContent(
        id: NotificationConstants.timerChannelNotificationId,
        channelKey: NotificationConstants.timerChannel,
        title: title,
        body: body,
        payload: payload,
      ),
      actionButtons: actionButtons,
    );
  }
}

The main function

Future<void> main() async {
  ...
  await Future.wait([
    Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform),
    NotificationService.initializeNotification()
  ]);
  FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
  runApp(const TeamTrace());
}

Solution

  • I fixed the issue simply by using the latest awesome_notifications: ^0.9.3+1. I was previously using awesome_notifications: ^0.8.2