Smart Communication Design Company
ホーム > ナレッジ > Blog > フロントエンドBlog > 2017年8月 > Firebaseを使って簡単にプッシュ通知を行う方法

フロントエンドBlog

Webのフロントエンドを構成する技術、特にHTMLやCSS、JavaScript、またそれらに関連する話題を扱うBlogです。

Firebaseを使って簡単にプッシュ通知を行う方法

UI開発者 泉口

今月の初め、WebKit Feature StatusにおけるService Workersの項が「Under Consideration」から「In Development」となり、iOSのSafariでもService Workersが実装される可能性が高まりました。iOSでPWAが機能するとなればネイティブアプリへの影響が出る可能性は捨てきれませんが、iOSデバイスのシェアが多い日本ではこれを機にPWAの認知度が高まればと個人的にはとても期待しています。

Service WorkersがWebに与える恩恵はキャッシュによるオフライン化やファイルリクエストのインターセプトだけではありません、プッシュ通知を表示するためのpushイベントもService Workersで実行します。

今回はFirebase用いて簡易的なプッシュ通知を行う方法と、プッシュ通知を行う上での課題点などを記載します。

Firebaseとは

ネイティブアプリ、Webアプリを構築する上で必要なバックエンドを担うBaaSの一種であり、とても一言二言では表せない高機能なプロダクトの集合です。データベース、ホスティング、ユーザー管理、パフォーマンス監視、解析、広告など一通りの機能が揃っていますが、今回はCloud Messagingを使用します。

プッシュ通知の実装

まずはFirebase consoleからプロジェクトを作成し、「ウェブアプリにFirebaseを追加」から次のコードを取得します。

<script src="https://www.gstatic.com/firebasejs/4.3.0/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "<apiKey>",
    authDomain: "<authDomain>",
    databaseURL: "<databaseURL>",
    projectId: "<projectId>",
    storageBucket: "<storageBucket>",
    messagingSenderId: "<messagingSenderId>"
  };
  firebase.initializeApp(config);
</script>

取得したコードを実行するだけで「firebaseオブジェクト」が使用可能になるので、firebase.messaging()からプッシュ通知に関連する「messagingオブジェクト」を取得します。

次にService Workersの登録と、messagingオブジェクトに用意されているメソッドから「通知権限」をリクエストし、許可された場合はトークンを取得します。

これらを簡略化したHTMLファイルは次のようになります。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<link rel="manifest" href="manifest.json">
<title>Push Notification</title>
</head>
<body>
<script src="https://www.gstatic.com/firebasejs/4.3.0/firebase.js"></script>
<script>
var messaging = firebase.initializeApp({
    apiKey: "<apiKey>",
    authDomain: "<authDomain>",
    databaseURL: "<databaseURL>",
    projectId: "<projectId>",
    storageBucket: "<storageBucket>",
    messagingSenderId: "<messagingSenderId>"
}).messaging();
var serviceWorker = navigator.serviceWorker;

messaging.requestPermission();

serviceWorker.register('serviceworker.js').then(() => {
    return serviceWorker.ready;
}).then(regist => {
    messaging.useServiceWorker(regist);
    messaging.requestPermission().then(() => {
        messaging.getToken().then(token => {
            console.log(token);
        });
    });
});
</script>
</body>
</html>

Firebaseによるトークンの取得はPushSubscription(Push API)によるエンドポイントとは異なり、ブラウザに依存しないユーザー単位でのユニークなIDを取得することができます。本来は取得したトークンが新規か更新されたものか判別したり、データベースに保存するなどの工程を経ますが、今回はコンソールに表示するのみとします。

manifest.json

Push通知を送るFirebaseのgcm_sender_idを記載します(基本項目は割愛)、現状このIDは固定値で103953800507となっています。

"gcm_sender_id": "103953800507"
serviceworker.js

次にHTMLファイルで読み込む「serviceworker.js」を作成します。

let baseURL = '/';

self.addEventListener('push', event => {
    let json = event.data.json();

    baseURL = json.data.url;

    event.waitUntil(
        self.registration.showNotification(json.notification.title, {
            'body': json.notification.body,
            'tag': 'request',
            'actions': JSON.parse(json.data.action)
        })
    );
});

self.addEventListener('notificationclick', event => {
    if (event.action === 'select-a') {
        self.clients.openWindow('https://www.mitsue.co.jp/knowledge/blog/');
    } else if (event.action === 'select-b') {
        self.clients.openWindow('https://www.mitsue.co.jp/knowledge/blog/frontend/');
    } else {
        self.clients.openWindow(baseURL);
    }

    event.notification.close();
});

pushイベントが発火した時、eventのデータを適用した通知を表示すると言ったシンプルな内容です。また、表示された通知のクリックnotificationclickでは押下された内容によって遷移先を変更しています。
複数の選択肢を表示するactionは現状Chromeのみで動作します。Firefoxの場合通知は表示しますが、選択肢は表示されません。

ここまでのファイルをサーバーにアップロードし、HTTPS環境で閲覧すると通知確認が出現し、許可することでコンソール上にトークンが表示します。

プッシュ通知の送信

今回はGoogle ChromeアプリのAdvanced REST clientを使ってプッシュ通知を送信します。
それぞれの設定項目と値は次のようになります。

Request URL

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

Methods

POST

Raw headers
Authorization: key=<サーバーキー>  
Content-Type: application/json

サーバーキーは、作成したFirebaseプロジェクトから「プロジェクトの設定」に移動し、クラウドメッセージングタブ内にある「サーバーキー」項目から取得します。

Raw payloads
{
    "registration_ids": [
      "<取得したトークンを記載>"
    ],
    "notification": {
        "title": "こんにちは!通知です!",
        "body": "ブログを読むのは初めてですか?"
    },
    "data": {
        "url": "https://www.mitsue.co.jp/careers/",
        "action": [
            {
                "action": "select-a",
                "title": "はい"
            },
            {
                "action": "select-b",
                "title": "いいえ"
            }
        ]
    }
}

設定が完了したら「Send」を押下し、特にエラーなく送信できた場合、次のような通知が表示します。

Google Chromeで表示するプッシュ通知
運用時の課題

以上が簡易的な実装方法となりますが、この実装には幾つか課題があります。

特定のグループに対してのみプッシュ通知を送信したい場合は何らかの方法でトークンをグルーピングする必要があります、このグルーピング判別を行うためには何らかの値を設定しなければならないため、結果的に「通知の許可」だけでは無い、PHPなどのフォームを実装する必要があります。

データベースの管理についても同じ事が言えます。サーバーに付属しているデータベースにトークンを保存するのか、Firebase Realtime Databaseで保存するのか、どのように継続的に管理していくかを考慮しなければなりません。

そして重要なトークンの管理です。トークンはService Workersが再インストールされた際に更新されるため、ユーザー個人の許可は新規なのか、更新なのかをonTokenRefreshを使って判別し、グルーピングやデータベースと照らし合わせて追加/更新を行う必要があります。

送信内容も注意したい所ですが、運用面を考慮するとやはりトークン管理が複雑になりがちな印象を受けます。
しかし、Firebaseを使用しない場合、エンドポイントの値がブラウザ毎に異なるため、それぞれの分岐条件を作成する必要が無いと言う意味で現状はFirebaseを用いた方法が最も簡単な方法と言えます。