2
votes

In brief: Firebase Notifications sent via Firebase Cloud Functions shows that message is sent. However, message is not received in the device. (Only tested in Android. Don't know about iOS)

Hello, I'm on a Ionic 3 project which uses Firebase Cloud Firestore, Cloud Functions and other Firebase services.

App workflow:

Upon new document creation (as in new reservation), the admin SDK should send push notification to the particular device which should arrive in the device.

Problem:

When checking in the Cloud Functions log, it shows message is successfully sent and the Triggering functions finished without any error. But no message has been received yet. However, when sending message from Firebase Notification Console, each message arrives perfectly.

Code:

index.ts (Cloud Functions)

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp(functions.config().firebase);

exports.notifyOnNewBooking = functions.firestore
    .document('users/{userId}/bookings/{bookingId}')
    .onCreate( event => {
        const bookingData = event.data.data();

        // construct notification message here
        const message = {
            notification: {
                title: 'Reservation confirmed!',
                body: 'Your reservation at someplace at sometime is confirmed',
                icon: 'https://image.ibb.co/iBwekx/icon.png'
            }
        };

        // send notification with message right away
        return admin.messaging().sendToDevice(bookingData.deviceFCMToken, message, {priority: 'high'})
            .then(resp => {
                console.log("sent successfully", resp);
            })
            .catch(err => {
                console.error("could not send notification", err);
            });
    });

app.component.ts (Ionic)

...
// Ionic Native wrapper
import { FCM } from '@ionic-native/fcm';
....

@Component({
  template: `
  ....
  ....
`
})
export class MyApp {
  ...
  constructor(..., private fcm: FCM) {}

  ngOnInit() {
    this.fcm.onNotification()
      .subscribe(resp => {});
  }
}

Firebase Cloud Functions log shows this:

enter image description here

Ionic CLI info

cli packages: (/usr/local/lib/node_modules)

    @ionic/cli-utils  : 1.19.1
    ionic (Ionic CLI) : 3.19.1

System:

    Node : v9.3.0
    npm  : 5.5.1 
    OS   : macOS High Sierra

Misc:

    backend : pro

Cloud Functions package.json dependencies

  "dependencies": {
    "@google-cloud/functions-emulator": "^1.0.0-beta.3",
    "firebase-admin": "~5.8.1",
    "firebase-functions": "^0.8.1",
    "firebase-tools": "^3.17.4",
    "global": "^4.3.2"
  },

config.xml

<plugin name="cordova-plugin-fcm" spec="^2.1.2">
  <variable name="SENDER_ID" value="845539284400" />
</plugin>

Note: There is only one subscription which is at the root component in the app. And I'm on Firebase Spark plan which is free but often notifies in the log that - Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions.

1
Hey yo, I think you are missing important token registration step in FCM plugin initialization: fcm.getToken().then(token=>{ backend.registerToken(token); }) - Sergey Rudenko
basically before you enable notifications you need to obtain token locally, then pass it over to your "backend" so that server side logic could sent notifications - Sergey Rudenko
@SergeyRudenko - no I did not miss. I registered the token somewhere else as my application requires so. I recently tried to send data notifications from Cloud Functions and its being received perfectly. But for normal notification its not being received in the app. On the other hand, data notifications message is being received only in the subscription of the onNotification(), not in the system notification tray which I want. I don't know if this is the intended behavior or what. - somnathbm
Sorry can you clarify if you app is running foreground or background in your scenarios? basically if your app is in FOREGROUND - your app can only get payload specified by "data" obj in the notifications object and there will be no tray based notification. But when your app tab or is in background otherwise - you will get data from your "notification" obj but not from data - makes sense? - Sergey Rudenko

1 Answers

1
votes

Modified the function in Cloud Functions to this below and now notifications is being received in the Notification tray when the app is in Background and in the subscription response when the app is in Foreground.

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp(functions.config().firebase);

exports.notifyOnNewBooking = functions.firestore
    .document('users/{userId}/bookings/{bookingId}')
    .onCreate(event => {
        const bookingData = event.data.data();

        // construct notification message here
        const message: admin.messaging.Message = {
            token: bookingData.deviceFCMToken,
            android: {
                notification: {
                    title: 'Reservation successful',
                    body: `Your reservation at ${bookingData.restaurant_name} is confirmed.`,
                    icon: 'https://image.ibb.co/iBwekx/icon.png'
                }
            },
            apns: {
                headers: {
                    'apns-priority': '10'
                },
                payload: {
                    aps: {
                        alert: {
                            title: 'Reservation successful',
                            body: `Your reservation at ${bookingData.restaurant_name} is confirmed.`,
                        },
                        badge: 1
                    }
                }
            }
        };

        // send notification with message right away
        return admin.messaging().send(message)
            .then(resp => {
                console.log("sent successfully", resp);
            })
            .catch(err => {
                console.error("could not send notification", err);
            });
    });