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

[Flutter] Flutter FCM notification tap does not call `getInitialMessage()`

Discussão em 'Mobile' iniciado por Stack, Outubro 25, 2024 às 19:52.

  1. Stack

    Stack Membro Participativo

    I've been working on a Flutter app where it needs to support being able to tap a notification and it takes you somewhere in the app. However, when the notification is tapped, it doesn't invoke any of the callbacks that I create. It just opens the app normally to the home page. I send notifications from an Node.js backend and I use the firebase-admin npm package to send a notification.

    I send a notification like this:

    /**
    * Trigger sending a notification
    */
    const sendNotification = async ({
    title,
    body,
    data,
    notificationType,
    topic,
    sendTo,
    mediaUrl,
    }) => {
    let tokens = [];
    if (sendTo) {
    console.log(`sending targeted notitification to: ${sendTo}`);
    tokens = await getUserFCMTokens(sendTo);
    }
    const notification = {
    data: {
    ...data,
    notificationType: NOTIFICATION_TYPE[notificationType].toString(),
    title: title,
    body: body,
    },
    ...(topic && { topic: topic }),
    ...(tokens.length > 0 && { tokens }),
    apns: {
    headers: {
    'apns-priority': '5',
    },
    payload: {
    aps: {
    contentAvailable: true,
    },
    },
    },
    android: {
    priority: 'high',
    notification: {
    click_action: 'FLUTTER_NOTIFICATION_CLICK',
    priority: 'high',
    sound: 'default',
    },
    },
    };

    console.log(notification);

    try {
    if (tokens.length > 0) {
    // Send to multiple devices
    const response = await admin
    .messaging()
    .sendEachForMulticast(notification);
    console.log(
    `Successfully sent message to ${response.successCount} devices`
    );
    if (response.failureCount > 0) {
    console.log(
    `Failed to send message to ${response.failureCount} devices`
    );
    response.responses.forEach((resp, idx) => {
    if (!resp.success) {
    console.log(
    `Failed to send to token at index ${idx}: ${resp.error}`
    );
    }
    });
    }
    } else if (topic) {
    // Send to topic
    const response = await admin.messaging().send(notification);
    console.log('Successfully sent message:', response);
    } else {
    console.log('No valid recipients (tokens or topic) specified');
    }
    } catch (error) {
    console.error('Error sending notification:', error);
    }
    };


    a notification might look like this when it is printed out:

    {
    data: {
    group: '6716a89768497667e665546c',
    media: '',
    message: '6716a8d868497667e66554a4',
    notificationType: '3',
    title: 'title goes here',
    body: '@zh22: Message goes here '
    },
    topic: 'group_6716a89768497667e665546c',
    apns: { headers: { 'apns-priority': '5' }, payload: { aps: [Object] } },
    android: {
    priority: 'high',
    notification: {
    click_action: 'FLUTTER_NOTIFICATION_CLICK',
    priority: 'high',
    sound: 'default'
    }
    }
    }


    Then, inside main.dart on the client side, I initialize the Firebase background handler and also set the getInitialMessage callback to open to a certain screen in the app when the notification is clicked.

    void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

    await AppData.initiate();

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    print("onMessage: $message");
    });

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    print("onMessageOpenedApp: $message");
    NotificationHandler.handleNotificationOnTap(message);
    });

    FirebaseMessaging.onBackgroundMessage(_onBackgroundMessage);

    FirebaseMessaging.instance
    .getInitialMessage()
    .then(NotificationHandler.handleNotificationOnTap);

    runApp(
    ShowCaseWidget(builder: (context) {
    return const MyApp();
    }),
    );
    }

    @pragma("vm:entry-point")
    Future<void> _onBackgroundMessage(RemoteMessage message) async {
    print("onBackgroundMessage: $message");
    print("data: ${message.data}");

    final NotificationRepository notificationRepository =
    NotificationRepositoryImpl();

    final FlutterLocalNotificationsPlugin localNotificationsPlugin =
    FlutterLocalNotificationsPlugin();
    // show notification
    const AndroidNotificationDetails androidNotificationDetails =
    AndroidNotificationDetails(
    "basecamp_notifications", "Basecamp Notifications",
    importance: Importance.max,
    priority: Priority.high,
    ticker: 'ticker');

    const DarwinNotificationDetails iosNotificationDetails =
    DarwinNotificationDetails(
    presentAlert: true,
    presentSound: true,
    interruptionLevel: InterruptionLevel.active);

    int notificationId = 1;

    const NotificationDetails platformSpecifics = NotificationDetails(
    android: androidNotificationDetails, iOS: iosNotificationDetails);

    await localNotificationsPlugin.initialize(
    const InitializationSettings(
    android: AndroidInitializationSettings("@mipmap/ic_launcher"),
    iOS: DarwinInitializationSettings(),
    ),
    onDidReceiveNotificationResponse: (NotificationResponse details) {

    if (details.payload != null) {
    final data = json.decode(details.payload!);
    final message = RemoteMessage(data: Map<String, String>.from(data));
    NotificationHandler.handleNotificationOnTap(message);
    }
    },
    );

    final title = message.data["title"];
    final body = message.data["body"];

    await localNotificationsPlugin.show(
    notificationId, title, body, platformSpecifics,
    payload: message.data.toString());

    }

    @pragma('vm:entry-point')
    void notificationTapBackground(NotificationResponse notificationResponse) {
    print(notificationResponse);
    // NotificationHandler.handleNotificationOnTap();
    }


    I tried setting NotificationHandler.handleNotificationTap() as the callback on both the local notification plugin's onDidReceiveNotificationResponse attribute and also with FirebaseMessaging.onBackgroundHandler. Neither are being called when I tap the notification received on the physical device.

    When I get a notification from the backend, the output on the app side looks like this:

    flutter: onBackgroundMessage: Instance of 'RemoteMessage'
    flutter: data: {body: @zh22: Message goes here, message: 6716a8d868497667e66554a4, title: @title goes here, group: 6716a89768497667e665546c, notificationType: 3, media: }
    flutter: remoteMessage: null


    notice that remoteMessage: null also is printed when a notification is received, which I think is strange.

    Finally, when I tap a notification, nothing is printed, leading me to believe that getInitialMessage is being not called at the right time, andonMessageOpenedApp doesn't seem to be called at all. I also have a print statement inside NotificationHandler.handleNotificationTap() that is never printed in this whole process, leading me to believe that the function is never entered.

    Currently running this on iOS. Made sure to include the Push Notification capability and Xcode. FirebaseAppDelegateProxyEnabled is set to NO. Why is it that none of these callbacks are working when I tap a notification?

    Continue reading...

Compartilhe esta Página