Push Notifications Background Handler

At the moment I am using Firebase and Capacitor APIs for Push and Local Notifications.
After reading into the subject of notifications and the differences between Data & Display notifications I am at a roadblock.

What I would like to achieve is to send a data notification from a Cloud Function on Firebase that is then presented to the user when the app is in the background (dead or inactive), a key feature being that a user can reply inline with this notification - like you can do on any chat application.

I can partially achieve this by sending data notifications, listening for them with with Push Notification API

PushNotifications.addListener('pushNotificationReceived' => (notification: PushNotification) => {})

And then displaying them with the local notification API.

async showNativeNotification(data: any) {

        if ((await App.getState()).isActive) {
            console.log('Application Open - Notification Suppressed', data);
            return;
        }

        let notifTitle = 'Knapsack';
        const prefColour = await this.prefService.getPreferences();
        if (data.location) {
            notifTitle = `${data.location.topic.name} - ${data.location.workspace.name}`;
        }

        LocalNotifications.schedule({
            notifications: [{
                id: 1,
                title: notifTitle,
                body: `${data.sender ? `${data.sender.name}: ` : ''}${data.message.snippet}`,
                attachments: null,
                iconColor: prefColour.userPrefs.theme ? UtilityHelper.themePropToHex(prefColour.userPrefs.theme.properties.primary) : '#f74258',
                actionTypeId: 'chat_message',
                extra: data
            }],

        });
    }

Actions Being Registered Earlier in the App:

LocalNotifications.registerActionTypes({
                types: [
                    {
                        id: 'chat_message',
                        actions: [
                            {
                                id: 'mute',
                                title: 'Mute',
                                destructive: true,
                                foreground: true
                            },
                            {
                                id: 'reply',
                                title: 'Reply',
                                input: true,
                                destructive: true,
                                foreground: false,
                                inputPlaceholder: 'Ab',
                                inputButtonTitle: 'Send'
                            }
                        ]
                    }
                ]
            });

This produces the exact thing I would like when the app is in the background somewhere.
However the issue is as it’s a data notification this function never fires when the app is completely killed.

If i send a display notification however then this comes through fine when the app is inactive & when the app has been killed, however to my knowledge there is no way of allowing input onto these, and registering events. Am I missing something or is this purley something that doesn’t exist at the moment?

I can make to with the boring un-interactive notifications but would love more flexibility. Any information or help on this topic would be much appreciated.

I’ve spent countless hours trying to get this to work and from all I’ve researched, it appears that data notifications currently don’t function in the background. Hopefully this is either not the case or it gets fixed soon!

2021 and I am also at this roadblock. I get want I want when the app is in the foreground but not in the background.

Really want those action buttons to appear on my push notification.

Yes, I encountered the same problem. I believe the only way to get around this is to drop down to Java native code and write your own FirebaseMessagingService implementation where you place the required logic.

Unless there’s a way to activate the app ‘fully’ from the FirebaseMessagingService.onMessageReceived() callback so that it goes through the entire initialization process where the PushNotifications event handlers are registered and thereafter they are invoked with the incoming RemoteMessage.

I suppose there are some technical challenges to doing this. Otherwise I’m sure Ionic would’ve implemented it out-of-the box.

In a PWA, the service worker handles this correctly on Android. iOS & web SDK does not work (as you are mentioning Java native code)

Capacitor team is aware of this issue and a fix is on the way. See here.

1 Like

Some information that helped me.
Disclaimer: may not apply to the issue here, but some people browsing here like me could benefit…

For me, too, background notifications where not working. I learnt the hard way that it was an error how I implemented sending the messages in the background. According to this explanation there is a difference between notifications and data messages.

Data messages are handled by the client, ie. when app in foreground.

When App is in background, usually no background tasks are listening to messages (as I thought) but the operating system takes over. This is where Notifications come into play.

All I needed to to is to extend my message payload to this in backend:

const notificationPayload = {
    tokens: tokens,
    data: {
        title: "My Message Title",
        body: "This is a great content."
    },
    notification: {
        title: "My Message Title",
        body: "This is a great content."
    }
};

The data part is for handling in the foreground (client).
The notification part is for handling in the background (OS).

@AntoniusGolly do you have this working for iOS and Android?

End of 2021, anyone managed to add buttons to Firebase&Cordova nofitications?

it’s weird.
Try this code, maybe it can help (it works correctly both with app killed or in background)

import { Injectable } from '@angular/core';
import {
  ActionPerformed,
  PushNotificationSchema,
  PushNotifications,
  Token,
} from '@capacitor/push-notifications';
import { Device } from '@capacitor/device';
import { AlertController } from '@ionic/angular';
import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';

@Injectable({
  providedIn: 'root'
})
export class PushNotificationService {
  pushNotificationToken: any; // I save the token to database because i need it in my backend code.

  constructor(
    private alertController: AlertController,
    private iab: InAppBrowser) {

  }

  initPush() {
    Device.getInfo().then(res => {
      if (res.platform !== 'web') {
        this.registerPush();
      }
    });
  }

  private registerPush() {
    PushNotifications.requestPermissions().then((permission) => {
      if (permission.receive) {
        // Register with Apple / Google to receive push via APNS/FCM
        PushNotifications.register();
      } else {
        // No permission for push granted
      }
    });

    PushNotifications.addListener(
      'registration',
      (token: Token) => {
        //console.log('My token: ' + JSON.stringify(token));
        this.pushNotificationToken = JSON.stringify(token.value);
      }
    );

    PushNotifications.addListener('registrationError', (error: any) => {
      //console.log('Error: ' + JSON.stringify(error));
    });

    PushNotifications.addListener(
      'pushNotificationReceived',
      async (notification: PushNotificationSchema) => {
 
        const data = notification;

        const alert = await this.alertController.create({
          header: JSON.stringify(notification.title).substring(1, JSON.stringify(notification.title).length - 1),
          message: JSON.stringify(notification.body).substring(1, JSON.stringify(notification.body).length - 1),
          buttons: [
            {
              text: 'OK',
              handler: () => {
                if (data.data.url != '' && data.data.url != undefined) {
                  const browser = this.iab.create(data.data.url, '_blank', { location: 'no' });
                }
              }

            }
          ]
        });
        await alert.present();
      }
    );



    PushNotifications.addListener(
      'pushNotificationActionPerformed',
      async (notification: ActionPerformed) => {
        const data = notification.notification.data;
        // console.log('Action performed: ' + JSON.stringify(notification.notification));

        if (data.url) {
          if (data.url != '' && data.url != undefined) {
            const browser = this.iab.create(data.url, '_blank', { location: 'no' });
          }
        }
  
      }
    );
  }

  resetBadgeCount() {
    Device.getInfo().then(res => {
      if (res.platform !== 'web') {
        PushNotifications.removeAllDeliveredNotifications();
      }
    });
  }
}

The downside of this though is that FCM notification messages are collapsable by default. I.e, if a couple of different notifications are sent when the device is offline only the latest message will be displayed when the device goes online.

can you send the payload, which server is sending to your app or can you mention does it have ‘notification’ object in payload.

Coz in new capacitor, if I don’t “notification” in data payload from server, it wont show tray notification for the app.

i send the notification with Firebase messaging

are you able to see what’s payload its sending from firebase?

I was able to send it even with my ionic all, I will give you an example asap

thanks that would be helpful

to multiple users
      postData = {
        "registration_ids": usersToken[i],
        "collapse_key": "type_a",
        "data": {
          "url": this.pushUrl
        },
        "notification": {
          "body": this.pushBody,
          "title": this.pushTitle,
          "image": this.pushImage,
        }
      }
 
 

to a single user:


      postData = {
        "to": this.userToken,
        "collapse_key": "type_a",
        "data": {
          "url": this.pushUrl
        },
        "notification": {
          "body": this.pushBody,
          "title": this.pushTitle,
          "image": this.pushImage,
        }
      }

1 Like

Thanks for valuable info, I had doubts on payload, yours is correct one.

Glad to be helpful, let me know if you need anything else

1 Like