How to handle payload message click
19:04 14 Nov 2025

How to handle notification payload. My app is that when killing the app, you always have to log in again. When receiving notification -> click on notification -> route to logIn screen -> after logging in, it will route to the Home screen. Here I am handling it in onReady().

const _initSettings = InitializationSettings(
  android: AndroidInitializationSettings('@mipmap/ic_launcher'),
  iOS: DarwinInitializationSettings(),
);

const _notificationDetails = NotificationDetails(
  android: AndroidNotificationDetails(
    'channel id',
    'channel name',
    icon: '@mipmap/ic_launcher',
    importance: Importance.max,
    styleInformation: BigTextStyleInformation(''),
  ),
);

@pragma('vm:entry-point')
Future backgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  initFirebase();
  // _configureRemoteMessage(message);
}

void initFirebase() async {
  // final message = await FirebaseMessaging.instance.getInitialMessage();
  await flutterLocalNotificationsPlugin.initialize(
    _initSettings,
    onDidReceiveNotificationResponse: _configurePayloadMessage,
    onDidReceiveBackgroundNotificationResponse: _configurePayloadMessage,
  );
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );
  // FirebaseMessaging.onMessageOpenedApp.listen(_configureRemoteMessage);
  FirebaseMessaging.onMessage.listen(_configureRemoteMessage);
  FirebaseMessaging.onMessageOpenedApp.listen(_configurePayloadMessageClick);
  await _handleInitialMessage();
}

Future _handleInitialMessage() async {
  final RemoteMessage? message =
      await FirebaseMessaging.instance.getInitialMessage();
  if (message != null) {
    // Lưu payload
    AppStateStore().setPushPayload(PushPayloadModel.fromNotification(message));

    if (SdkController.isSessionOpened) {
      handlePayloadNavigation(message.data);
    }
  }
}

@pragma('vm:entry-point')
Future _configurePayloadMessage(NotificationResponse response) async {
  // alwasy get payload from notification
  if (response.payload == null || response.payload!.isEmpty) return;

  final payload = _convertStringToJson(response.payload);

  AppStateStore().setPushPayload(
    PushPayloadModel(
      type: payload['type'] as String?,
      username: payload['username'] as String?,
      data: payload,
    ),
  );

  if (SdkController.isSessionOpened) {
    handlePayloadNavigation(payload);
  }
}

Future _configurePayloadMessageClick(RemoteMessage message) async {
  final payload = message.data;
  if (payload.isEmpty) return;

  AppStateStore().setPushPayload(PushPayloadModel.fromNotification(message));

  if (SdkController.isSessionOpened) {
    handlePayloadNavigation(payload);
  }
}

void handlePayloadNavigation(Map payload) {
  if (payload['type'] == NotificationEnum.authorization.value) {
    final authRequest = _convertStringToJson(payload['authorizationRequest']);
    Get.toNamed(
      AppRoutes.routeAuthorize,
      arguments: Authorize.fromJson(authRequest),
    );
  } else if (payload['type'] == NotificationEnum.signing.value) {
    final signRequest = _convertStringToJson(payload['signingRequest']);
    Get.toNamed(
      AppRoutes.routeConfirmSign,
      arguments: Sign.fromJson(signRequest),
    );
  }
}

Future _configureRemoteMessage(RemoteMessage message) async {
  final notification = message.notification;
  if (GetPlatform.isAndroid && notification != null) {
    flutterLocalNotificationsPlugin.show(
      message.hashCode,
      notification.title,
      notification.body,
      _notificationDetails,
      payload: jsonEncode(message.data),
    );
  }
}

Map _convertStringToJson([String? data]) {
  return Map.from(jsonDecode(data ?? '{}'));
}
class HomeController extends BaseRefreshGetxController with GetSingleTickerProviderStateMixin {
@override
void onReady() {
  getTotal();
  _handlePushPayload(); 
 super.onReady();
}

  void _handlePushPayload() {
    final payload = state.pushPayloadModel;
    if (payload == null ||
        payload.type == null ||
        payload.username != state.userInfoModel.login) {
      return;
    }
    handlePayloadNavigation(payload.data!);
    state.clearPushPayload();
  }
}
class AppStateStore {
PushPayloadModel? pushPayloadModel;
  void setPushPayload(PushPayloadModel payload) {
    pushPayloadModel = payload;
  }

  void clearPushPayload() {
    pushPayloadModel = null;
  }
}

I am working on push notification handling in Flutter and I am facing a problem with FirebaseMessaging.getInitialMessage().

My app uses flutter_local_notifications to display notifications manually when a Firebase data message arrives.
The notification opens the app correctly, but getInitialMessage() always returns NULL, even when the app is fully terminated and launched by tapping the notification.

This is the log I get every time:

I/flutter: 🔵 [FIREBASE] getInitialMessage: NULL

I/flutter: 🔵 [FIREBASE] _handleInitialMessage - message: NULL

Expected behavior

When the app is killed and the user taps a notification, getInitialMessage() should return the notification data so I can navigate to a specific screen.

Actual behavior

getInitialMessage() returns NULL every time.

flutter dart notifications firebase-cloud-messaging payload