web-dev-qa-db-fra.com

Enregistrement de la messagerie sur le cloud PWA et Firebase d'Ionic 3

Je suivais cet article ici (qui n’est malheureusement pas complet) pour tenter de savoir comment se faire un ami avec PWA et Firebase Cloud Messaging sur Ionic 3: Notifications push avec FCM

Ce que j'ai fait:

  1. comme indiqué dans l'article, les bibliothèques FCM ont été ajoutées à service-worker.js:

'use strict';
importScripts('./build/sw-toolbox.js');
importScripts('https://www.gstatic.com/firebasejs/4.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.9.0/firebase-messaging');

firebase.initializeApp({
  // get this from Firebase console, Cloud messaging section
  'messagingSenderId': '47286327412'
});

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler((payload) => {
  console.log('Received background message ', payload);
  // here you can override some options describing what's in the message; 
  // however, the actual content will come from the service sending messages
  const notificationOptions = {
    icon: '/assets/img/appicon.png'
  };
  return self.registration.showNotification(notificationTitle, notificationOptions);
});

self.toolbox.options.cache = {
  name: 'ionic-cache'
};

// pre-cache our key assets
self.toolbox.precache(
  [
    './build/main.js',
    './build/vendor.js',
    './build/main.css',
    './build/polyfills.js',
    'index.html',
    'manifest.json'
  ]
);

// dynamically cache any other local assets
self.toolbox.router.any('/*', self.toolbox.cacheFirst);

// for any other requests go to the network, cache,
// and then only use that cached resource if your user goes offline
self.toolbox.router.default = self.toolbox.networkFirst;

  1. Ensuite, créez le fournisseur basé sur la messagerie Firebase ici:

import { Injectable } from "@angular/core";
import * as firebase from 'firebase';
import { Storage } from '@ionic/storage';

@Injectable()
export class FirebaseMessagingProvider {
  private messaging: firebase.messaging.Messaging;
  private unsubscribeOnTokenRefresh = () => {};

  constructor(
    private storage: Storage
  ) {
    this.messaging = firebase.messaging();
  }

  public enableNotifications() {
    console.log('Requesting permission...');
    return this.messaging.requestPermission().then(() => {
        console.log('Permission granted');
        // token might change - we need to listen for changes to it and update it
        this.setupOnTokenRefresh();
        return this.updateToken();
      });
  }

  public disableNotifications() {
    this.unsubscribeOnTokenRefresh();
    this.unsubscribeOnTokenRefresh = () => {};
    return this.storage.set('fcmToken','').then();
  }

  private updateToken() {
    return this.messaging.getToken().then((currentToken) => {
      if (currentToken) {
        // we've got the token from Firebase, now let's store it in the database
        return this.storage.set('fcmToken', currentToken);
      } else {
        console.log('No Instance ID token available. Request permission to generate one.');
      }
    });
  }

  private setupOnTokenRefresh(): void {
    this.unsubscribeOnTokenRefresh = this.messaging.onTokenRefresh(() => {
      console.log("Token refreshed");
      this.storage.set('fcmToken','').then(() => { this.updateToken(); });
    });
  }
    
}

Et maintenant, lors de l'initialisation de l'application, j'appelle enableNotifications () et reçois une erreur indiquant que le service worker par défaut est introuvable (404):

Un code de réponse HTTP incorrect (404) a été reçu lors de l'extraction du script .___: 8100/firebase-messaging-sw.js Échec du chargement de la ressource: net :: ERR_INVALID_RESPONSE

Si je déplace des éléments liés à service-worker.js firebase vers un agent de service par défaut dans un dossier WWW, l'erreur d'erreur générale vient de Firebase (Erreur, impossible d'enregistrer l'agent de service).

QUESTIONS. J'ai regardé le tutoriel sur Angular mais je ne vois pas comment faire de même dans Ionic 3.

6
Sergey Rudenko

UPDATE: les informations ci-dessous sont valables à compter d'aujourd'hui (02/12/2018) et seront probablement moins pertinentes une fois que AngularFire2 aura pris en charge le module de messagerie. Donc, prenez le ci-dessous avec cette hypothèse ...

OK, j'ai fait des recherches et je l'ai finalement fait fonctionner sur mon IWA 3 PWA. Je poste donc la solution ici:

  1. Conditions préalables:
    • J'ai créé l'application vide ionique (juste une page d'accueil)
    • installé angularfire2 et firebase ("angularfire2:: 5.0.0-rc.4", "firebase": "4.9.1") à l’aide de npm install, j’ai utilisé spécifiquement 5.0.0-rc.4 "car j’ai eu des problèmes de stabilité avec Le dernier;(
    • créé config (nom de fichier environment.ts dans le dossier src):

export const firebaseConfig = {
    apiKey: "Your Stuff Here from FB",
    authDomain: "YOURAPPNAME.firebaseapp.com",
    databaseURL: "https://YOURAPPNAME.firebaseio.com",
    projectId: "YOURAPPNAME",
    storageBucket: "YOURAPPNAME.appspot.com",
    messagingSenderId: "FROMFIREBASECONEOLE"
};

  1. J'ai modifié app.module.ts pour ajouter firebase et angularfire2 comme suit:

...
import { AngularFireModule } from 'angularfire2';
import 'firebase/messaging'; // only import firebase messaging or as needed;
import { firebaseConfig } from '../environment';
import { FirebaseMessagingProvider } from '../providers/firebase-messaging';
...

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(firebaseConfig),
    IonicStorageModule.forRoot()
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    FirebaseMessagingProvider,
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Ici, nous importons également notre fournisseur dont le code est ci-dessous:

  1. dans le dossier des fournisseurs, j'ai créé firebase-messaging.ts comme ceci:

import { Injectable } from "@angular/core";
import { FirebaseApp } from 'angularfire2';
// I am importing simple ionic storage (local one), in prod this should be remote storage of some sort.
import { Storage } from '@ionic/storage';

@Injectable()
export class FirebaseMessagingProvider {
  private messaging;
  private unsubscribeOnTokenRefresh = () => {};

  constructor(
    private storage: Storage,
    private app: FirebaseApp
  ) {
    this.messaging = app.messaging();
    navigator.serviceWorker.register('service-worker.js').then((registration) => {
    this.messaging.useServiceWorker(registration);
    //this.disableNotifications()
    this.enableNotifications();
});
  }

  public enableNotifications() {
    console.log('Requesting permission...');
    return this.messaging.requestPermission().then(() => {
        console.log('Permission granted');
        // token might change - we need to listen for changes to it and update it
        this.setupOnTokenRefresh();
        return this.updateToken();
      });
  }

  public disableNotifications() {
    this.unsubscribeOnTokenRefresh();
    this.unsubscribeOnTokenRefresh = () => {};
    return this.storage.set('fcmToken','').then();
  }

  private updateToken() {
    return this.messaging.getToken().then((currentToken) => {
      if (currentToken) {
        // we've got the token from Firebase, now let's store it in the database
        console.log(currentToken)
        return this.storage.set('fcmToken', currentToken);
      } else {
        console.log('No Instance ID token available. Request permission to generate one.');
      }
    });
  }

  private setupOnTokenRefresh(): void {
    this.unsubscribeOnTokenRefresh = this.messaging.onTokenRefresh(() => {
      console.log("Token refreshed");
      this.storage.set('fcmToken','').then(() => { this.updateToken(); });
    });
  }
    
}

Veuillez noter que je lance l'application firebase puis, dans le constructeur, nous enregistrons le service worker par défaut d'ionic (service-worker.js) qui contient les éléments suivants juste après tout ce qui se trouve par défaut:

  1. service-worker.js:

// firebase messaging part:
importScripts('https://www.gstatic.com/firebasejs/4.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.9.0/firebase-messaging.js');

firebase.initializeApp({
  // get this from Firebase console, Cloud messaging section
  'messagingSenderId': 'YOURIDFROMYOURFIREBASECONSOLE' 
});

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler(function(payload) {
  console.log('Received background message ', payload);
  // here you can override some options describing what's in the message; 
  // however, the actual content will come from the Webtask
  const notificationOptions = {
    icon: '/assets/images/logo-128.png'
  };
  return self.registration.showNotification(notificationTitle, notificationOptions);
});

À ce stade, vous devez également vous assurer que vous avez activé votre application en tant que PWA. Il existe un bon guide de Josh Morony et, aujourd’hui, un flux vidéo sur youtube la couvre. Dans TLDR, vous devez supprimer le commentaire dans votre index.html:

  1. index.html in src uncomment:

 <!-- un-comment this code to enable service worker -->
  <script>
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('service-worker.js')
        .then(() => console.log('service worker installed'))
        .catch(err => console.error('Error', err));
    }
  </script>

  1. OK, presque la dernière chose - votre manifeste.json (dans src) devrait avoir la ligne exacte: "Gcm_sender_id": "103953800507"

Ceci conclut les choses initiales sur le client. Veuillez noter que je n'ai pas encore implémenté quoi que ce soit pour gérer les notifications lorsque l'utilisateur est dans l'application elle-même. Pensez pour l'instant qu'il gère uniquement les messages envoyés depuis un serveur lorsque votre onglet n'est pas actif (c'est ce que j'ai testé).

  1. Vous souhaitez maintenant accéder à votre console Firebase et obtenir la clé du serveur (cliquez sur l'icône d'engrenage de réglage, puis reportez-vous à la section relative à la messagerie dans le cloud). Copier la clé du serveur. Exécutez également le client (service ionique et capture de votre jeton local (je viens de le consigner.), Essayez maintenant de vous envoyer le message à l’aide d’une méthode POST. (Je l’ai fait avec Postman).

// method: "POST",
//url: "https://fcm.googleapis.com/fcm/send",
    // get the key from Firebase console
    headers: { Authorization: `key=${fcmServerKey}` }, 
    json: {
        "notification": { 
            "title": "Message title",
            "body": "Message body",
            "click_action": "URL to your app?"
        },
        // userData is where your client stored the FCM token for the given user
        // it should be read from the database
        "to": userData.fcmRegistrationKey
    }

Donc, en faisant tout cela, j'ai pu m'envoyer un message fiable alors que l'application était en arrière-plan. Je n'ai pas encore pris en charge le premier plan, mais cette question SO concerne la procédure à suivre pour initier le prestataire de services par défaut et le marier avec FCM.

J'espère que cela aidera certains apprenants à l'avenir.

10
Sergey Rudenko

J'ai réussi à mettre en œuvre le processus et à obtenir une réponse positive aux appels d'API. Mais aucune notification popup à venir sur mon navigateur. Une idée?

api:https://fcm.googleapis.com/fcm/send

réponse obtenu:

{"multicast_id": 6904414188195222649, "success": 1, "échec": 0, "canonical_ids": 0, "résultats": [{"message_id": "0: 1545375125056264% e609af1cf9fd7ecd"]]]]

cheth l'URL jointe de ma console: enter image description here

0
Arindam Mojumder