firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.72k stars 3.97k forks source link

iOS ALWAYS shows push notifications even in foreground #6210

Closed vytautas-pranskunas- closed 2 years ago

vytautas-pranskunas- commented 3 years ago

iOS device shows notification in foreground Expected behaviour would be that foreground notifications are left for user to control and showing (if needed) with local notifications.

I am building chat and to receive push notifications in foreground is annoying.

I am on 9.1.4 version of firebase_messaging

p.s. even in your example for some reason you are invoking showNotification only for android... https://pub.dev/packages/firebase_messaging/example

darshankawar commented 3 years ago

@vytautas-pranskunas- Did you start noticing this behavior recently or has always been the case ?

Also, just making sure your ios setup is as mentioned in the document, https://firebase.flutter.dev/docs/messaging/apple-integration

Can you try the latest plugin version and see if you get same behavior ?

vytautas-pranskunas- commented 3 years ago

Hi, i have noticed it yesterday because I started to test on ios device.

I am using 10.0.0 version so it is latest

Yes I followed that guide for ios setup

darshankawar commented 3 years ago

@vytautas-pranskunas- If I understand correctly, the notifications are triggered only when app is in foreground, so onLaunch and onResume are not called ? and not receiving in background or app is closed ?

vytautas-pranskunas- commented 3 years ago

No, notifications are triggered always. Expected bahaviour would be - notifications should not be triggered when app in foreground

On Mon, May 24, 2021, 11:27 AM darshankawar @.***> wrote:

@vytautas-pranskunas- https://github.com/vytautas-pranskunas- If I understand correctly, the notifications are triggered only when app is in foreground, so onLaunch and onResume are not called ? and not receiving in background or app is closed ?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/FirebaseExtended/flutterfire/issues/6210#issuecomment-846875010, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA54ZF54W4Y7YNZQDCOJFTLTPIEXLANCNFSM45IYQU6A .

Ehesp commented 3 years ago

Have you tried to call setForegroundNotificationPresentationOptions?

Oddly enough, this is not default iOS behaviour and presenting in the foreground has to explicitly be set. Have you called this method before with true, since it persists.

vytautas-pranskunas- commented 3 years ago

Yes i am doing it

await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
        alert: true, // Required to display a heads up notification
        badge: true,
        sound: true,
      );

because it is written in your example: https://pub.dev/packages/firebase_messaging/example

however it should not show foreground notifications i should be able to control notification showup anyway like in your example you are doing for android. Because now, I am building chat and all pushes, when someone has sent me a message, are shown in foreground. So for android I am doing this:

_configureLocalNotifications() async {
    FirebaseMessaging.onMessage.takeUntil(_unsubscriber!).listen((RemoteMessage message) {
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;

      if (message.data['type'] != null &&
          message.data['type'] == EnumToString.convertToString(PushNotificationType.ChatMessageAdded)) {
        return;
      }

      if (notification != null && android != null) {
        _localNotifications.showNotification(
          title: notification.title,
          body: notification.body,
          payload: new LocalNotificationPayload(LocalNotificationType.push, message.data),
        );
      }
    });

but iOS notification show before onMessage.

p.s. if I am not mistaking i was trying to comment setForegroundNotificationPresentationOptions but behaviour was the same.

So there is 2 problems: 1) iOS messages are shown before onMessage and should be controlled in same maner like android 2) foreground notifications showed up even without setForegroundNotificationPresentationOptions

Ehesp commented 3 years ago

If you have called this:

await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
        alert: true, // Required to display a heads up notification
        badge: true,
        sound: true,
      );

These settings will persist for the device, you need to explicitly call false on the options to disable them.

because it is written in your example: pub.dev/packages/firebase_messaging/example

Without this in the example, users wouldn't see notifications. Make sure you read the docs for the methods.

vytautas-pranskunas- commented 3 years ago

@Ehesp I understand this. I want that users would be able to see foreground notifications all correc. But problem is that iOS notifications fires before onMessage fires. I would expect same behaviour like in android that i can control when to show heads up notification.

darshankawar commented 3 years ago

Keeping this open for further insights and investigation.

vytautas-pranskunas- commented 3 years ago

While keeping this open can someone tell me how to show heads up notifications conditionally on ios? I cannot release an app without this. Because now there are 2 options:

  1. Not to show heads up at all
  2. Show all heads ups meaning that in chat user will see messages + heads ups

Neither is good option

Ehesp commented 3 years ago

We don't have control of how the OS handles notifications, only hook onto events. If conditionally displaying a heads-up notification is your goal, then I'd suggest going with this approach:

  1. Disable any foreground FCM based notifications - e.g. make sure you turn off setForegroundNotificationPresentationOptions options, and don't send the payload with any "high priority" fields set to true, or a channel on Android which is high priority, since the OS might force display it in the foreground.
  2. When you want to send an FCM message (e.g. via Firebase admin SDK), send both a notification object AND data payload. In the background, the OS will use the notification object to display a notification, but in the foreground you'll need to build your own (conditionally) using the flutter_local_notifications library.
vytautas-pranskunas- commented 3 years ago

@Ehesp but interesting fact is that on Android onMessage is hit first and i can show foreground notification using flutter_local_notifications after. But on iOS foreground notification is shown upfront onMessage hit...

Ehesp commented 3 years ago

But on iOS foreground notification is shown upfront onMessage hit...

But it shouldn't be showing as heads up if you have disabled the options? That's my confusion.

vytautas-pranskunas- commented 3 years ago

Ok so i atchieved it easily. I think your example is misleading and can be improved. this setForegroundNotificationPresentationOptions is not nessecary at all and creates fork in buiess logic forcing to add if(android) check. Without it android check can be removed and headsup gets displayed for both platforms anyway.

_configureLocalNotifications() async {
    FirebaseMessaging.onMessage.takeUntil(_unsubscriber!).listen((RemoteMessage message) {
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;

      if (notification != null && android != null) { <---------- REMOVE
        _localNotifications.showNotification(
          title: notification.title,
          body: notification.body,
          payload: new LocalNotificationPayload(LocalNotificationType.push, message.data),
        );
      }
    });

then it works as has to be on both platforms meaning neithe ron Android neither in iOS headsup are not showed by default but fluter_local_notifications takes care of this. This way onMessage life cycle is correct too and foreground notifications can be controlled easily

if (message.data['type'] != null &&
          message.data['type'] == EnumToString.convertToString(PushNotificationType.ChatMessageAdded)) {
        return;
      }
vinothvino42 commented 3 years ago

While keeping this open can someone tell me how to show heads up notifications conditionally on ios? I cannot release an app without this. Because now there are 2 options:

  1. Not to show heads up at all
  2. Show all heads ups meaning that in chat user will see messages + heads ups

Neither is good option

Remove the notification object from the payload and add title, description, priority and content_available in the data object. So that FCM will not display notification by default (because now it's data message type). You've to manually invoke flutter local notification with the data object based on your conditions.

russellwheatley commented 2 years ago

Closing this as there is nothing to action.