4
votes

I am developing Angular 2 web app and want to register Firebase Messaging and obtain token.

I am using angularfire2 for Angular 2. I use Angular ng serve local development environment. Unfortunatelly the browser console shows me below errors:

V browserErrorMessage : "Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script." code : "messaging/failed-serviceworker-registration" message : "Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. (messaging/failed-serviceworker-registration)." stack : "FirebaseError: Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. (messaging/failed-serviceworker-registration).↵ at http://localhost:4200/vendor.bundle.js:96468:225↵ at ZoneDelegate.invoke (http://localhost:4200/vendor.bundle.js:102953:26)↵ at Object.onInvoke (http://localhost:4200/vendor.bundle.js:33052:37)↵ at ZoneDelegate.invoke (http://localhost:4200/vendor.bundle.js:102952:32)↵ at Zone.run (http://localhost:4200/vendor.bundle.js:102824:43)↵ at http://localhost:4200/vendor.bundle.js:103246:57↵ at ZoneDelegate.invokeTask (http://localhost:4200/vendor.bundle.js:102986:35)↵ at Object.onInvokeTask (http://localhost:4200/vendor.bundle.js:33043:37)↵ at ZoneDelegate.invokeTask (http://localhost:4200/vendor.bundle.js:102985:40)↵ at Zone.runTask (http://localhost:4200/vendor.bundle.js:102862:47)↵ at drainMicroTaskQueue (http://localhost:4200/vendor.bundle.js:103144:35)" proto : Error

Below is the code of my service.

import { Inject, Injectable } from "@angular/core";
import { FirebaseApp } from "angularfire2";
import * as firebase from 'firebase';

@Injectable()
export class FirebaseMessagingService {

  private messaging: firebase.messaging.Messaging;

  constructor( @Inject(FirebaseApp) private firebaseApp: firebase.app.App) {
    console.log("FirebaseMessagingService init...");
    this.messaging = firebase.messaging(this.firebaseApp);
    
  }


  init() {

    

    this.messaging.requestPermission()
      .then(() => {
        this.onFirebaseInitialized();
      })
      .catch((error) => {
        console.log("FirebaseMessagingService requestPermission error:" + error);

      });
  }

  private onFirebaseInitialized() {
    console.log("FirebaseMessagingService initialized");

    /*this.messaging.setBackgroundMessageHandler(message => {
      
    })*/

    this.getToken();


    // Callback fired if Instance ID token is updated.
    this.messaging.onTokenRefresh(() => {
      this.getToken();
    });

    

    this.messaging.onMessage((payload) => {
      console.log("Message received. ", payload);
      // ...
    });
    


  }

  getToken() {
    this.messaging.getToken()
      .then((currentToken) => {
        console.log('getToken() received');
        if (currentToken) {
          this.sendTokenToServer(currentToken);
          this.updateUIForPushEnabled(currentToken);
        } else {
          // Show permission request.
          console.log('No Instance ID token available. Request permission to generate one.');
          // Show permission UI.
          this.updateUIForPushPermissionRequired();
          this.setTokenSentToServer(false);
        }
      })
      .catch(function (err) {
        console.log('An error occurred while retrieving token. ', err);
        //this.showToken('Error retrieving Instance ID token. ', err);
        //this.setTokenSentToServer(false);
      });
  }


  sendTokenToServer(token) {

  }

  updateUIForPushEnabled(token) {

  }

  updateUIForPushPermissionRequired() {

  }

  setTokenSentToServer(isSent: boolean) {

  }

  

}
3

3 Answers

1
votes

You need to register a ServiceWorker:

  1. Create a web app manifest as described here: https://firebase.google.com/docs/cloud-messaging/js/client
  2. Create a service worker file, as described in the following section Receive Messages.
  3. Load the two files. For example, in index.html:

      <link rel="manifest" href="/manifest.json">
    
      <script>
        if ('serviceWorker' in navigator) {
          navigator.serviceWorker.register('/firebase-messaging-sw.js').then(function(registration) {
            // Registration was successful
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
          }).catch(function(err) {
            // registration failed :(
            console.log('ServiceWorker registration failed: ', err);
          });
        }
       </script>
    

This blog post helped me in the process: https://houssein.me/progressive-angular-applications

Note: be aware that Chrome has some issues regarding firebase messaging. If you don't see a response from firebase.messaging(firebaseApp).getToken() try opening the Service Workers section in the dev tools under Application tab, unregister the application's service worker, and reload. On Firefox there shouldn't be an issue.

0
votes

Most likely the firebase-messaging-sw.js is missing in the compiled app code:

  • Make sure you have a file named firebase-messaging-sw.js in the src folder. Can be an empty file.
  • Make sure when you run your app this file can be served from '/', if using angular cli modify the content of the .angular-cli.json file to include the firebase-messaging-sw.js in the compile code:
// ..... .angular-cli.json
"apps": [{
    "root": "src",
    "outDir": "dist",
    "assets": [
      "assets",
      "favicon.ico",
      "firebase-messaging-sw.js" // this will copy this file in the root path of the compilation folder
    ],
// ..... more config options
0
votes

You must add firebase-messaging-sw.js in www dir, because the page looks for http://localhost/firebase-messaging-sw.js instead of our project dir.