LoginSignup
5
3

More than 3 years have passed since last update.

firebase FCM と ionic4 で Web Push を実装してみる

Last updated at Posted at 2019-07-23

ionic 弄り始めて約2ヶ月ですが firebase との組み合わせでうまく動いているので
SPA(Single Page Application) での WebPush 実装方法をまとめてみました。

環境

各環境を整える

  • ionic4
    Webテクノロジー(HTML、CSS、JavaScript)を使って、高性能かつ高品質なモバイルとデスクトップアプリケーションをつくるためのオープンソースのUIフレームワーク

  • firebase
    モバイルおよびWebアプリケーション開発プラットフォーム
    Firebase Cloud Messaging(FCM)

  • Visual Studio Code
    クラウド開発用の強力かつ軽量なコード エディター

サンプルコード

firebase プロジェクト 初期設定

firebase コンソールでプロジェクトを作成し
適当な作業ディレクトリを作り初期化する。

mkdir ionic-webpush-sample
cd ionic-webpush-sample
firebase init

#Functions と Hosting を有効にする
● Functions
● Hosting

#Functions は TypeScript を有効に。
? What language would you like to use to write Cloud Functions? 
  JavaScript 
❯ TypeScript 

#後は適当に…

ionic プロジェクト 初期設定

firebase プロジェクト 初期設定したディレクトリで ionic 初期設定をして firebase.json を一部書き換える。

cd ionic-webpush-sample
ionic start ionicapp blank --type=angular
firebase.json
  "hosting": {
    "public": "ionicapp/www", <- public ディレクトリではなく ionicapp/www に変更
  ...

ionic 仮ビルド

ionicapp ディレクトリをビルドして ionicapp/www を生成してみる。

cd ionicapp
ionic build

firebase ローカル実行で設定確認

firebase.json 設定が正しく設定されているか確認してみる。

firebase serve
# functions のエラーが表示されるがココでは無視していいです。
http://localhost:5000/

起動後 http://localhost:5000/ にアクセスして Ionic Blank が表示されていれば
firebase.json の設定は成功しています。
スクリーンショット 2019-07-24 0.00.12.png

ココまでの設定で firebaseionic を利用する初期設定が終わりました。
続いて ionic 内で firebase を利用する設定を行います。


ionic に firebase SDK を組み込む

ionic 初期化したディレクトリに移動しえ firebase SDK を組み込みます。

cd /ionic-webpush-sample/ionicapp
npm install --save firebase

アプリにFirebaseの設定をする。

environments を修正する。
cofig の値は firebaseコンソール プロジェクトの設定 全般 → マイアプリ → 構成 で 取得することができます。

スクリーンショット 2019-07-24 0.36.42.png

src/environments/environment.ts
export const environment = {
  production: false,
  config:{
    apiKey: "AIzaSy...",
    authDomain: "ionic-webpush-sample.firebaseapp.com",
    databaseURL: "https://ionic-webpush-sample.firebaseio.com",
    projectId: "ionic-webpush-sample",
    storageBucket: "ionic-webpush-sample.appspot.com",
    messagingSenderId: "2986...",
    appId: "1:298684318675:web:3..."
  }
};
src/environments/environment.prod.ts
export const environment = {
  production: true,
  config:{
    apiKey: "AIzaSy...",
    authDomain: "ionic-webpush-sample.firebaseapp.com",
    databaseURL: "https://ionic-webpush-sample.firebaseio.com",
    projectId: "ionic-webpush-sample",
    storageBucket: "ionic-webpush-sample.appspot.com",
    messagingSenderId: "2986...",
    appId: "1:298684318675:web:3..."
  }
};

アプリ内で firebase SDK 初期化処理を記載する

app.component.ts を修正して firebase SDK を初期化する

src/app/app.component.ts
  import * as firebase from 'firebase';
  import { environment } from '../environments/environment';
...
  initializeApp() {
    ...
    firebase.initializeApp(environment.config);
  }

ココまでの設定で ionic アプリ内で firebase sdk を利用できるようになりました。
続いて最低限の ブラウザプッシュ受け取り 処理を書いていきます。


プッシュ通知 受信の為 サービスワーカーの初期設定をする。

app.component.ts に 処理を追加する。
あわせて assets ディレクトリに firebase-messaging-sw.js を追加する。

src/app/app.component.ts
  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });

    //firebase 初期化
    firebase.initializeApp(environment.config);

    //プッシュ通知 受信の為のサービスワーカー利用設定
    navigator.serviceWorker.register('assets/script/firebase-messaging-sw.js')
    .then((registration) => {
      firebase.messaging().useServiceWorker(registration);
    });
  }

YOUR-SENDER-IDfirebase コンソール で確認する事ができます。

assets/script/firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/6.3.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/6.3.1/firebase-messaging.js');

firebase.initializeApp({
    'messagingSenderId': 'YOUR-SENDER-ID'
});

const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  // Customize notification here
  const notificationTitle = payload.notification.title;
  const notificationOptions = {
      body: payload.notification.body,
      icon: payload.notification.icon
    };
  return self.registration.showNotification(notificationTitle,notificationOptions);
});

プッシュ通知パーミッション 確認処理を追加する

home に 処理を追加する。

src/app/home/home.page.html
# ボタンと トークン表示 欄を追加する
<ion-content>
  <ion-item>
    <ion-button (click)="clickBtnPushPermission()">パーミッション確認</ion-button>
  </ion-item>
  <ion-item>
      <ion-label>token</ion-label>
      <ion-text>{{token}}</ion-text>
  </ion-item>
</ion-content>
src/app/home/home.page.ts
import * as firebase from 'firebase';
...
export class HomePage {
...
 token: string = "";

  clickBtnPushPermission() {
    //console.log("clickBtnPushPermission");
    const _self = this;
    firebase.messaging().requestPermission()
      .then(function () {
        //ユーザー毎のトークンを取得して画面に表示する
        firebase.messaging().getToken()
          .then(function (token) {
            _self.token = token;
          })
          .catch(function (err) {
            console.error('Unable to retrieve refreshed token ', err);
          });
      })
      .catch(function (err) {
        console.error('Unable to get permission to notify.', err);
      });
  }
}

プッシュ通知 許可と トークン取得 確認

ココまでの設定で プッシュ通知 許可と トークン取得ができるようになっている筈なので
ionic ローカル環境を起動して確認してみる。

cd ionicapp
ionic serve

パーミッション確認 ボタンを押すと 確認ダイアログが表示され許可すると トークンが取得され画面に表示される。

スクリーンショット 2019-07-24 1.58.16.png

ココまでの設定で トークンが取得できた筈。
続いて Cloud Functions の 関数を定義して 関数経由で プッシュ通知を送る処理を書いていきます。


プッシュ通知送信のための ボタンを 追加する

home に プッシュ通知送信の為のボタンと処理を追加

src/app/home/home.page.html
<ion-content>
  <ion-item>
    <ion-button (click)="clickBtnPushPermission()">パーミッション確認</ion-button>
  </ion-item>
...
  <ion-item>
    <ion-button (click)="clickBtnPush()">プッシュ通知 送信</ion-button>
  </ion-item>
</ion-content>
src/app/home/home.page.ts
 clickBtnPush(){
    //functions に 定義した関数にパラメータを送って実行する
    //TODO token は Realtime Database or Cloud Firestore に保存して
    //     他に漏れないように処理する必要がある / プッシュなりすまし等の対策
    const value = {
      title:"たいとる",
      body:"ほんぶん",
      icon:"star",
      token:this.token 
    };
    const sendNotification = firebase.functions().httpsCallable("send_notification");
    sendNotification(value).then(result => {
      console.log("sendNotification","result",result);
    });
  }

プッシュ通知 受信時の処理

app.component.ts に 受信時に トーストを表示する処理を追加する。

src/app/app.component.ts
import { ToastController } from '@ionic/angular';
 constructor(
    ...
    private toastController: ToastController
  ) {
...

  initializeApp() {
  ...
   //プッシュ通知 受信時の処理
    const _self = this;
    firebase.messaging().onMessage(function (payload) {
      //トーストを表示してみる
      _self.showNotificationToast(payload);
    });
  }

  //トーストを表示
  async showNotificationToast(payload:any) {
    let _self = this;
    //payload.notification.icon
    const toast = await this.toastController.create({
      header: payload.notification.title,
      message: payload.notification.body,
      position: 'top',
      buttons: [
        {
          side: 'start',
          icon: payload.notification.icon,
          handler: () => {
            console.log(payload);
          }
        }
      ]
    });
    toast.present();
  }

WebPushを送信する処理を実装

home に書いた firebase.functions().httpsCallable で呼び出させれる関数を functions/src/index.ts に実装する。
serviceAccountKey.jsonfirebase コンソールの プロジェクト設定 で取得できる。

functions/src/index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

/*
admin.initializeApp({
    credential: admin.credential.applicationDefault(),
    databaseURL: "https://ionic-webpush-sample.firebaseio.com"
});
*/
admin.initializeApp();

//プッシュ通知するAPI
exports.send_notification = functions.https.onCall((data, context) => {
    console.log("data",data);
    //プッシュ送信
    const value = {
        notification: {
            title: data.title,
            body: data.body
        },
        webpush: {
            headers: {
                TTL: "60"
            },
            notification: {
                icon: data.icon,
                click_action: data.click_action
            }
        },
        token: data.token
    };

    return admin.messaging().send(value)
                        .then((response: any) => {
                            console.log('Successfully sent message:', response);
                            return Promise.resolve(response);
                        })
                        .catch((error: any) => {
                            console.log('Error sending message:', error);
                            return Promise.reject(error);
                        });
});

functions デプロイ してみる

functions を デプロイして実行してみる。

cp functions
npm run deploy
cd ../ionicapp
ionic serve

プッシュ通知が動作するか確認

http://localhost:8100/home にアクセスして トークン取得後に プッシュ通知送信 ボタンを押して見る。 画像のようなトーストが表示されれば成功です。

スクリーンショット 2019-07-24 10.33.51.png

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3