invertase / react-native-firebase

šŸ”„ A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.72k stars 2.22k forks source link

[Android][Notification] Notification goes to tray silently when app in background/close #1274

Closed johnsonsu closed 6 years ago

johnsonsu commented 6 years ago

Issue

How can I present remote notifications received in a "head up" notification instead of going to the tray silently?

When app is running in the background or closed, remote notifications received from FCM goes to notification tray. There is no way/instruction to show as a "head up" notification (dropdown box from top of device). In the Notification Introduction document, it wrote:

Delivered to the notification tray when the app is in the background or closed.

How can I change this behaviour and have the the notification pop out from the top when it is received?

This is my payload posted to FCM, where priority is already set to 'high'

  const body = {
    priority: 'high',
    to: ...,
    data: ...,
    notification: {
      body: text,
      title,
      badge: 1,
    },
  }
  ...
  await http.sendRequest({
    url: 'https://fcm.googleapis.com/fcm/send',
    headers: { Authorization: `key=${fcmKey}` },
    body,
  })

I have also tried posting with android_channel_id and creating a channel as instructed in Android Channels doc.

Similar issues #500 and #357 have been closed but there were no solutions.

Thank you for your help!

Environment

  1. Application Target Platform: Android

  2. Development Operating System: macOS Sierra

  3. Build Tools: Android build tools 27.0.3

  4. React Native version: 0.55.4

  5. React Native Firebase Version: 4.2.0

  6. Firebase Module: Messaging and Notification

  7. Are you using typescript? no


Loving react-native-firebase? Please consider supporting their open collective:

šŸ‘‰ https://opencollective.com/react-native-firebase/donate

haseebnaseem commented 6 years ago

Having the same issue. Also can you share how you are creating a heads up notification in the foreground. Its kind of a hit and miss for me, sometimes the pop up appears and sometimes it does not.

johnsonsu commented 6 years ago

@haseebnaseem, we are currently using a custom foreground notification banner, not the system one. For that, we just listen to firebase.notifications().onNotification() and present our own notification base on the notification data we received.

For your case on foreground notification, I believe firebase.notifications().displayNotification(notification) should do the job if it works as expected. I think you would also need to create a channel and do notification.android.setChannelId('channelId') before you can display it on Android.

yangnana11 commented 6 years ago

Hello,

Do you have any head up for this? Mine also goes to silent mode, it's silent, not show for background and foreground mode in Samsung galaxy note 5, and only problem with foreground mode with Samsung galaxy s7. And by the way, I applied this and it can't get the body info (I've got undefined) but if foreground it's correct.

       this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
            // Get the action triggered by the notification being opened
            const action = notificationOpen.action;
            // Get information about the notification that was opened
            const notification: Notification = notificationOpen.notification;
            alert(notification.body);
            firebase.notifications().removeDeliveredNotification(notification.notificationId);
        });
johnsonsu commented 6 years ago

@yangnana11 I'm not sure about the body, but notificationOpen.notification.data is working fine for me.

Is there any react-native-firebase dev looking into this at the moment? Perhaps @Salakar or @chrisbianca?

anderswag commented 6 years ago

o_O

image

haseebnaseem commented 6 years ago

The only thing that helped me was to use a remote message instead of a notification and add a headless service as mentioned in the docs to create a notification, when the app is in the background or closed, using that message.

yangnana11 commented 6 years ago

@anderswag I don't have permission to do that thing... I wonder why... because I replied I think.. @haseebnaseem Thanks, I think that is a good solution. @johnsonsu If you test with firebase console cloud message tool, you use android channel and it display as head up, then the problem is your notification. I tested it and it show up my head-up notification

haseebnaseem commented 6 years ago

@yangnana11 it's not really a good solution because in ios, onMessage handlers are not called and payload needs to only have the notification object instead of the data object in case of messages. So currently the situation i am facing is as follows: For Android: When the app is closed, a notification message does not show heads. When the app is in background, a notification message does not show heads. So for both of these and for the sake of consistency, we have to use the data message and create the notification on our own. For ios: when the app is closed, data messages are not received. when the app is in the background, data messages are received using which we can create the notification. when the app is in foreground, data messages are received and we can use them to create notifications. If you've understood, just because of the heads up messages we are forced to use the data only messages instead of notification message but they do not work when the app is closed in ios.

horstleung commented 6 years ago

@haseebnaseem where should I create the notification for showing the heads when the app is in the background or not opened?

haseebnaseem commented 6 years ago

@fattomhk use a headless js service, as mentioned in the docs, to intercept data only messages, and create a notification just like you do when the app is in foreground.

nickarora commented 6 years ago

We are having trouble with this as well.

const displayNotification = (notification: RNFirebase.notifications.Notification) => {
  firebase.notifications().displayNotification(notification)
}

firebase.notifications().onNotification(displayNotification)

const notification = new firebase.notifications.Notification()
    .setTitle(strings.titleText)
    .setBody(strings.bodyText)
    .setNotificationId(someId)
    .setData({ someData })
    .android.setChannelId(ourId) // previously created
    .android.setSmallIcon('ic_launcher')
    .android.setLargeIcon('ic_launcher')

firebase.notifications().scheduleNotification(notification, {
    fireDate: date.getTime(),
})

The app remains in the foreground the entire time.
This notification goes directly to the system tray.
No heads up display. This only happens on android; on iOS things work perfectly.

EDIT: I was able to resolve this issue by using ensuring the notification's priority was HIGH and the sound was set to default (.setSound('default')) when creating a notification. Depending on your device's API level, priority level, sound settings, and vibration pattern will affect whether or not you see a heads up notification.

see here for more information: https://developer.android.com/guide/topics/ui/notifiers/notifications#Heads-up

kevinEsherick commented 6 years ago

I am having this same or similar issue but on iOS. Notifications show in the tray and on the lock screen but nowhere else (i.e. anywhere that would use a notification banner). It was happening on 4.1, so I upgraded to 4.3 hoping that would fix it but have found so such luck. I've tried to apply the fix suggested by every related problem I've found on here and Stack Overflow and none have worked. If anyone has ideas I would really appreciate it, I don't want to have to switch packages.

Salakar commented 6 years ago

https://rnfirebase.io/docs/v4.3.x/notifications/android - see the Yellow information box at the top. Explains a little and links to the official Android documentation for notifications - which explains in detail the conditions/platform versions that will trigger a notification to display as a heads-up notification.

Specifically:


Example conditions that might trigger heads-up notifications include the following:


Ensure you've met those conditions when creating your notification - e.g. setting a sound, vibration and importance.


Loving react-native-firebase and the support we provide? Please consider supporting us with any of the below:

kevinEsherick commented 6 years ago

@Salakar the issue is occurring for me on iOS so none of these fixes work. Can you reopen this or should I create a new issue explicitly for iOS? EDIT: Well to make it even weirder, I just tested on a beta user's iPhone and it works fine. I made sure that notifications are allowed in settings and permissionEnabled returns true. So I guess ignore me for now.

Salakar commented 6 years ago

@kevinEsherick if it's still an issue then please make a separate issue and tag it as iOS, have also replied to you on discord. Thanks

ngoclieu1996vn commented 5 years ago

Can't use setbadge when app in close ?? please help me [Android]

lorenc-tomasz commented 5 years ago

@Salakar The same issue with latest RN-firebase https://github.com/invertase/react-native-firebase/issues/1930

lorenc-tomasz commented 5 years ago

@Salakar The same issue with latest RN-firebase https://github.com/invertase/react-native-firebase/issues/1930

andreshsingh commented 4 years ago

I'be been stuck in this also for quite some time.

The solution is quite easy.

You just have to setup the notification channel id in the manifest and add the same channel id in push params which is triggered from the backend.

By default, firebase sets the channel id as default(miscellaneous) which doesn't show pop up!

fobtracker commented 4 years ago

I'be been stuck in this also for quite some time.

The solution is quite easy.

You just have to setup the notification channel id in the manifest and add the same channel id in push params which is triggered from the backend.

By default, firebase sets the channel id as default(miscellaneous) which doesn't show pop up!

Can you share an example of how you did it? I get an error that the value from the manifest file is used and needs to be replaced

andreshsingh commented 4 years ago

I'be been stuck in this also for quite some time. The solution is quite easy. You just have to setup the notification channel id in the manifest and add the same channel id in push params which is triggered from the backend. By default, firebase sets the channel id as default(miscellaneous) which doesn't show pop up!

Can you share an example of how you did it? I get an error that the value from the manifest file is used and needs to be replaced

Make sure you have this AndroidManifest.xml

      <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id"
      />

Strings.xml
<string name="default_notification_channel_id">YOUR_CHANNEL_ID</string>

And in the push notification payload from backend make sure you have priority as 1 and not 'high' and set channel Id to YOUR_CHANNEL_ID for android.

If you dont send channel id from backend while triggering the push, the default channelId would be used (Miscellaneous).

fobtracker commented 4 years ago

I'be been stuck in this also for quite some time. The solution is quite easy. You just have to setup the notification channel id in the manifest and add the same channel id in push params which is triggered from the backend. By default, firebase sets the channel id as default(miscellaneous) which doesn't show pop up!

Can you share an example of how you did it? I get an error that the value from the manifest file is used and needs to be replaced

Make sure you have this AndroidManifest.xml

      <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id"
      />

Strings.xml <string name="default_notification_channel_id">YOUR_CHANNEL_ID</string>

And in the push notification payload from backend make sure you have priority as 1 and not 'high' and set channel Id to YOUR_CHANNEL_ID for android.

If you dont send channel id from backend while triggering the push, the default channelId would be used (Miscellaneous).

On the server, I specified the channel identifier and added priority.

            const message = {
                notification: notificationData.notify,
                tokens: [notification.fcm_token],
                data: notificationData.data,
                android: {
                    priority: 1,
                    channel_id: 'MainChannel',
                    notification: {
                        title: notificationData.notify.title,
                        body: notificationData.notify.body,
                    },
                },
                apns: {
                    payload: {
                        aps: {
                            alert: {
                                title: notificationData.notify.title,
                                body: notificationData.notify.body,
                            },
                        },
                    },
                },
            };

            await admin.messaging().sendMulticast(message);

But I get an error from ts

Argument of type '{ notification: { readonly title: string; readonly body: string; }; tokens: string[]; data: { readonly loadId: string; }; android: { priority: number; channel_id: string; notification: { title: string; body: string; }; }; apns: { ...; }; }' is not assignable to parameter of type 'MulticastMessage'.
  The types of 'android.priority' are incompatible between these types.
    Type 'number' is not assignable to type '"high" | "normal"'.ts(2345)

I added what you said, and my project is not going to

error Failed to install the app. Make sure you have the Android development environment set up: https://reactnative.dev/docs/environment-setup. Run CLI with --verbose flag for more details.
Error: Command failed: ./gradlew app:installDebug -PreactNativeDevServerPort=8081
/home/user/driver/android/app/src/debug/AndroidManifest.xml:21:95-150 Error:
        Attribute meta-data#com.google.firebase.messaging.default_notification_channel_id@value value=(@string/default_notification_channel_id) from AndroidManifest.xml:21:95-150
        is also present at [:react-native-firebase_messaging] AndroidManifest.xml:39:13-29 value=().
        Suggestion: add 'tools:replace="android:value"' to <meta-data> element at AndroidManifest.xml:21:7-153 to override.
andreshsingh commented 4 years ago

I'be been stuck in this also for quite some time. The solution is quite easy. You just have to setup the notification channel id in the manifest and add the same channel id in push params which is triggered from the backend. By default, firebase sets the channel id as default(miscellaneous) which doesn't show pop up!

Can you share an example of how you did it? I get an error that the value from the manifest file is used and needs to be replaced

Make sure you have this AndroidManifest.xml

      <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id"
      />

Strings.xml <string name="default_notification_channel_id">YOUR_CHANNEL_ID</string> And in the push notification payload from backend make sure you have priority as 1 and not 'high' and set channel Id to YOUR_CHANNEL_ID for android. If you dont send channel id from backend while triggering the push, the default channelId would be used (Miscellaneous).

On the server, I specified the channel identifier and added priority.

            const message = {
                notification: notificationData.notify,
                tokens: [notification.fcm_token],
                data: notificationData.data,
                android: {
                    priority: 1,
                    channel_id: 'MainChannel',
                    notification: {
                        title: notificationData.notify.title,
                        body: notificationData.notify.body,
                    },
                },
                apns: {
                    payload: {
                        aps: {
                            alert: {
                                title: notificationData.notify.title,
                                body: notificationData.notify.body,
                            },
                        },
                    },
                },
            };

            await admin.messaging().sendMulticast(message);

But I get an error from ts

Argument of type '{ notification: { readonly title: string; readonly body: string; }; tokens: string[]; data: { readonly loadId: string; }; android: { priority: number; channel_id: string; notification: { title: string; body: string; }; }; apns: { ...; }; }' is not assignable to parameter of type 'MulticastMessage'.
  The types of 'android.priority' are incompatible between these types.
    Type 'number' is not assignable to type '"high" | "normal"'.ts(2345)

I added what you said, and my project is not going to

error Failed to install the app. Make sure you have the Android development environment set up: https://reactnative.dev/docs/environment-setup. Run CLI with --verbose flag for more details.
Error: Command failed: ./gradlew app:installDebug -PreactNativeDevServerPort=8081
/home/user/driver/android/app/src/debug/AndroidManifest.xml:21:95-150 Error:
        Attribute meta-data#com.google.firebase.messaging.default_notification_channel_id@value value=(@string/default_notification_channel_id) from AndroidManifest.xml:21:95-150
        is also present at [:react-native-firebase_messaging] AndroidManifest.xml:39:13-29 value=().
        Suggestion: add 'tools:replace="android:value"' to <meta-data> element at AndroidManifest.xml:21:7-153 to override.

Looks like in js you have to use ('high')[https://firebase.google.com/docs/reference/admin/node/admin.messaging.AndroidConfig#optional-priority] and not number.

can you share your manifest ?

make sure the meta-data is inside your tag.

fobtracker commented 4 years ago

high

I replaced the number with the value 'high'

priority: 'high',

But I still get an error from ts

Argument of type '{ notification: { readonly title: string; readonly body: string; }; tokens: string[]; data: { readonly loadId: string; }; android: { notification: { title: string; body: string; channel_id: string; priority: string; }; }; apns: { ...; }; }' is not assignable to parameter of type 'MulticastMessage'.
  The types of 'android.notification.priority' are incompatible between these types.
    Type 'string' is not assignable to type '"high" | "min" | "low" | "default" | "max"'.ts(2345)

Here is my manifest file

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="app.driver.app">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-feature android:name="android.hardware.location.gps"/>

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
     <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/default_notification_channel_id"  />
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="${authHost}"
            android:pathPrefix="/android/${applicationId}/callback"
            android:scheme="${applicationId}" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

</manifest>
mikehardy commented 4 years ago

@fobtracker that's a classic typescript error, stackoverflow will guide you in how to use enumerated types, I went through this in the past - follow stackoverflow suggestions while playing with the solutions offered there and you'll get it

Joshuauzor commented 1 month ago

I'be been stuck in this also for quite some time. The solution is quite easy. You just have to setup the notification channel id in the manifest and add the same channel id in push params which is triggered from the backend. By default, firebase sets the channel id as default(miscellaneous) which doesn't show pop up!

Can you share an example of how you did it? I get an error that the value from the manifest file is used and needs to be replaced

Make sure you have this AndroidManifest.xml

      <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id"
      />

Strings.xml <string name="default_notification_channel_id">YOUR_CHANNEL_ID</string>

And in the push notification payload from backend make sure you have priority as 1 and not 'high' and set channel Id to YOUR_CHANNEL_ID for android.

If you dont send channel id from backend while triggering the push, the default channelId would be used (Miscellaneous).

worked for me šŸ™