Banner notification on background firebase

Hey !

I have troubles using Firebase plugin and Ionic 4.
Well, I just want to display a banner notification when user receive a notification and the app is running in background (or is kill).

Actually, I get the small icon in the top bar, and the notification is display in the notifications’s center.
But I want to display it like a banner.

So this is my code : app.component.ts :

this.platform.ready().then(() => {
    if (this.platform.is('cordova')) {
        this.notifications.initPushNotification();
    }
});

push-notification.component.ts :

import { Injectable } from '@angular/core';
import { environment } from 'src/environments/environment';
import { UserService } from 'src/app/user/user.service';
import { User } from '../interfaces/user';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Firebase } from '@ionic-native/firebase/ngx';
import { AngularFirestore } from 'angularfire2/firestore';
import { ToastController, Platform } from '@ionic/angular';
import { FirebaseApp } from 'angularfire2';
import { LocalNotifications } from '@ionic-native/local-notifications/ngx';


@Injectable({
  providedIn: 'root'
})

export class PushNotificationService {

  token: string;

  constructor(
    private http: HttpClient,
    private users: UserService,
    private toastController: ToastController,
    private firebase: Firebase,
    private afs: AngularFirestore,
    private platform: Platform,
    private app: FirebaseApp,
    private localNotifications: LocalNotifications
  ) { }

  initPushNotification() {
    console.log('initPushNotification');

    if (this.platform.is('cordova')) {
      // Initialize push notification feature
      this.platform.is('ios') ? this.initializeFireBaseIos() : this.initializeFireBaseAndroid();
    } else {
      console.log('Push notifications are not enabled since this is not a real device');
    }
  }

  initializeFireBaseAndroid(): Promise<any> {
    return this.firebase.getToken()
      .then(token => {
        console.log(`The token is ${token}`);
        this.token = token;
        this.subscribeToPushNotificationEvents();
      })
      .catch(error => console.error('Error getting token :', error));
  }

  initializeFireBaseIos(): Promise<any> {
    return this.firebase.grantPermission()
      .catch(error => console.error('Error getting permission', error))
      .then(() => {
        this.firebase.getToken()
          .catch(error => console.error('Error getting token', error))
          .then(token => {
            console.log(`The token is ${token}`);
            this.subscribeToPushNotificationEvents();
          });
      });
  }

  subscribeToPushNotificationEvents() {
    // Handle token refresh
    this.firebase.onTokenRefresh().subscribe(
      token => {
        console.log(`The new token is ${token}`);
        this.saveToken(token);
      },
      error => console.error('Error refreshing token', error));

    // Handle incoming notifications
    this.firebase.onNotificationOpen()
    .subscribe(
      async notification => {
        !notification.tap
          ? console.log('The user was using the app when the notification arrived...')
          : console.log('The app was closed when the notification arrived...');
        console.log('Notification received :', notification);

        this.localNotifications.schedule({
          title: notification.title,
          text: notification.body,
          foreground: true,
        });
      },
      error => {
        console.error('Error getting the notification', error);
      });
  }

  private saveToken(token: any): Promise<any> {
    // Send the token to the server
    this.token = token;
    this.saveTokenToFirestore(token);
    return Promise.resolve(true);
  }

  private saveTokenToFirestore(token: string): Promise<void> {
    const devicesRef = this.afs.collection('devices');
    const docData = {
      token,
      userId: this.users.get()
    };
    return devicesRef.doc(token).set(docData);
  }

  displayBannerNotification(message: string, interlocutor: User) {
    console.log('sendBannerNotification ----------------------------------------');
    const options = new HttpHeaders()
      .set('Content-Type', 'application/json')
      .set('Authorization', `key=${environment.firebase.serverKey}`);

    const body = {
      'notification': {
        'title': interlocutor.nickname,
        'body': message,
        'click_action': 'FCM_PLUGIN_ACTIVITY'
      },
      'to': 'DEVICE TOKEN'
    };

    this.http.post('https://fcm.googleapis.com/fcm/send', JSON.stringify(body), { headers: options })
      .subscribe(data => { console.log('Message envoyé ! ', data); });
  }
}

The fact is that onNotificationOpened is not trigger when the app run in background.

Have I missed something ?

I’m not sure what you mean by “display it like a banner”? Can you describe more what you want to see?

Of course. Look at this pictures. This is what I want to display on Android, and for IOS

1 Like

Note that this code is currently working on IOS, but not on Android (tested on v6)

Did you get it buddy? i’m trying to do the same, firestore new document -> alert everyone!

I have the same problem. I received notification (little icon on top and full notification on the the screen when I push down the screen) but there is no banner on top of the main screen. I only did tests on Android (dev and prod).

In my package.json:

"@ionic-native/firebase-x": "^5.19.0",
...
"cordova-plugin-androidx": "^1.0.2",
"cordova-plugin-androidx-adapter": "^1.1.0",
"cordova-plugin-firebasex": "^7.0.1",

Hi everyone,

I think i found how we can do this. Maybe this solution can be improve, let me know =).
So let’s do some JAVA here :
I your MainActivity.java after super.onCreate(savedInstanceState); put this following code.

// Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      String channelID = "YOUR_UNIQUE_APP_ID";
      CharSequence name = "CHANNEL_NAME";
      String description = "CHANNEL_DESCRIPTION";
      int importance = NotificationManager.IMPORTANCE_HIGH;
      NotificationChannel channel = new NotificationChannel(channelID, name, importance);
      channel.setDescription(description);
      // Register the channel with the system; you can't change the importance
      // or other notification behaviors after this
      NotificationManager notificationManager = getSystemService(NotificationManager.class);
      notificationManager.createNotificationChannel(channel);
    }

In your AndroidManifest.xml in application tag

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

This code work for me =), hope it will help you !