tag:crieit.net,2005:https://crieit.net/tags/FirebaseCloudMessaging/feed
「FirebaseCloudMessaging」の記事 - Crieit
Crieitでタグ「FirebaseCloudMessaging」に投稿された最近の記事
2020-05-24T17:18:35+09:00
https://crieit.net/tags/FirebaseCloudMessaging/feed
tag:crieit.net,2005:PublicArticle/15909
2020-05-24T17:18:35+09:00
2020-05-24T17:18:35+09:00
https://crieit.net/posts/Nuxt-Firebase-Cloud-Messaging-FCM-Web
Nuxt+Firebase Cloud Messaging(FCM)でWebプッシュ通知を送る
<p>WebでもFCMが使えるようになったので、試してみたときの備忘録。<br />
これでSafari以外には、通知が送れるようになる(<em>´ω`</em>)</p>
<h3 id="使い方"><a href="#%E4%BD%BF%E3%81%84%E6%96%B9">使い方</a></h3>
<p>構成は、@nuxtjs/pwaでPWA化している感じ。</p>
<h4 id="コンソール側"><a href="#%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E5%81%B4">コンソール側</a></h4>
<p>Settingsでウェブプッシュ証明書を作成して、鍵ペアを取得する。</p>
<p><img width="973" alt="スクリーンショット_2020-05-24_17_06_33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/d17f3a0e-e6df-73a7-d57b-a6ff36e7c79f.png"></p>
<p>これを、PUBLIC_VAPID_KEYという環境変数に設定しておく。</p>
<h4 id="クライアント側"><a href="#%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E5%81%B4">クライアント側</a></h4>
<h5 id="firebaseの初期化"><a href="#firebase%E3%81%AE%E5%88%9D%E6%9C%9F%E5%8C%96">firebaseの初期化</a></h5>
<p><code>~/plugins/firebase.ts</code>というファイルを用意し、firebaseを初期化</p>
<pre><code class="typescript">// ~/plugins/firebase.ts
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import "firebase/messaging";
if (!firebase.apps.length) {
// まずは、firebaseの初期化
firebase.initializeApp({
apiKey: process.env.API_KEY,
authDomain: process.env.AUTH_DOMAIN,
databaseURL: process.env.DATABASE_URL,
projectId: process.env.PROJECT_ID,
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID,
appId: process.env.APP_ID,
measurementId: process.env.MEASUREMENT_ID
});
// Push通知をサポートしているかをチェック
// サポートしていないと、firebase.messaging()を呼んだときに例外が発生
const isSupported = firebase.messaging.isSupported();
// コンソールで発行した、ウェブプッシュ証明書の鍵ペアを取得
const publicVapidKey = process.env.PUBLIC_VAPID_KEY;
if (!!publicVapidKey && process.client && !!isSupported) {
// FCMの初期化。鍵ペアを設定する
const messaging = firebase.messaging();
messaging.usePublicVapidKey(publicVapidKey);
// @nuxtjs/pwaが生成するsw.jsと、
// 後で作成するFCM受信処理用のsw-firebase-messaging.jsを統合するための設定
navigator.serviceWorker
.register("/sw.js")
.then(registration => messaging.useServiceWorker(registration))
.catch(err => console.error(err));
}
}
export default firebase;
</code></pre>
<h5 id="トークンの取得"><a href="#%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97">トークンの取得</a></h5>
<p>Push通知を送る際の宛先として、トークンを指定しないといけないので取得。<br />
トークンは端末ごとに取得する必要があるので、注意が必要。<br />
※PCとスマホだとそれぞれトークンが違う</p>
<pre><code class="typescript">import firebase from "~/plugins/firebase";
// トークンの取得
public async getToken(user: User) {
const isSupported = firebase.messaging.isSupported();
if (!isSupported) return;
const token = await firebase.messaging().getToken();
// firestoreにトークンを保存しておく処理(中身は略)
await saveToken(user, token);
}
</code></pre>
<p>Firestoreなどへユーザごとにトークンを保存しておく。</p>
<p><code>firebase.messaging().getToken();</code>を呼んだ際に、<br />
通知の設定が「確認」だと、許可を求めるダイアログが表示される。</p>
<p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/e9976414-8418-09c1-8846-25211a949776.png" alt="スクリーンショット 2020-05-24 16.30.23.png" /></p>
<p>これが許可されていないと、トークンも取得できない。</p>
<p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/c21078c8-38d0-04c7-133a-b5402611443d.png" alt="スクリーンショット 2020-05-24 16.30.35.png" /></p>
<h5 id="メッセージを受け取ったときの処理"><a href="#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E5%8F%97%E3%81%91%E5%8F%96%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E5%87%A6%E7%90%86">メッセージを受け取ったときの処理</a></h5>
<p>メッセージを受信したときに受け取る関数は2つあり、</p>
<ul>
<li>フォアグラウンド(画面を見ている時) ... onMessage</li>
<li>バックグラウンド(画面を見ていない時) ... setBackgroundMessageHandler</li>
</ul>
<p>・【参考】<a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/cloud-messaging/js/receive#handle_messages_when_your_web_app_is_in_the_background">JavaScript クライアントでメッセージを受信する | Firebase</a></p>
<p>今回はバックグラウンドのときに通知を送りたいので、<br />
<code>setBackgroundMessageHandler</code>を設定していく。</p>
<p>こんな感じ。</p>
<p>ドキュメントを見ると、『<code>firebase-messaging-sw.js</code>というファイル名で作成』と書かれているけど、<br />
その名前にすると、自動で読み込まれてしまう。。</p>
<p>開発用と本番用で切り替えたいときなどもあるので、@nuxtjs/pwaが生成するsw.jsと統合できるように、<br />
<code>sw-firebase-messaging.js</code>という名前でファイルを作成しておく。</p>
<p>ファイル名を変更したので、上で書いている「firebaseの初期化」の部分で、<br />
<code>messaging.useServiceWorker(registration)</code>を呼んでいる形。</p>
<pre><code class="javascript">// ~/static/sw-firebase-messaging.js
importScripts("https://www.gstatic.com/firebasejs/7.14.2/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.14.2/firebase-messaging.js");
// Firebaseの初期化
firebase.initializeApp({
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "...",
});
// [START background_handler]
const isSupported = firebase.messaging.isSupported();
if (!!isSupported) {
const messaging = firebase.messaging();
// バックグラウンド時の処理
messaging.setBackgroundMessageHandler(function(payload) {
// 受け取ったFCMの内容を取得
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: payload.notification.icon,
};
// 通知を作成する
return self.registration.showNotification(notificationTitle, notificationOptions);
});
}
// [END background_handler]
</code></pre>
<h5 id="nuxt.config.tsでPWA関連の設定をする"><a href="#nuxt.config.ts%E3%81%A7PWA%E9%96%A2%E9%80%A3%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E3%81%99%E3%82%8B">nuxt.config.tsでPWA関連の設定をする</a></h5>
<p>作成した<code>sw-firebase-messaging.js</code>を取り込む設定と、<br />
@nuxtjs/pwaが生成するmanifest.jsonに、gcm_sender_idを追加する設定を追加</p>
<pre><code class="typescript">import { Configuration } from "@nuxt/types";
const config: Configuration = {
// 略
modules: [
"@nuxtjs/pwa",
],
workbox: {
// sw-firebase-messaging.jsをimportするように追加
importScripts: [
"sw-firebase-messaging.js"
]
},
pwa: {
manifest: {
// manifest.jsonにgcm_sender_idを追加
gcm_sender_id: process.env.MESSAGING_SENDER_ID || ""
}
},
};
export default config;
</code></pre>
<p>これでクライアント側はOK!</p>
<h4 id="サーバ側: メッセージを送信する"><a href="#%E3%82%B5%E3%83%BC%E3%83%90%E5%81%B4%3A+%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B">サーバ側: メッセージを送信する</a></h4>
<p>メッセージの送信は、firebase-adminでできる。<br />
・<a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/cloud-messaging/send-message?hl=ja">アプリサーバーからの送信リクエストを作成する | Firebase</a></p>
<p>firestoreを利用しているので、Cloud Functionsのfirestoreトリガーを使い、<br />
ドキュメントが追加されたら通知するようにしている例。</p>
<pre><code class="typescript">import * as functions from "firebase-functions";
import admin from "../common/firebaseAdmin"; // 初期化済みのfirebase-admin
export default functions
.firestore.document("ドキュメントのパス")
.onCreate(async (snap, context) => {
// getTokenで保存しておいたトークンを取得(中身は略)
const token = getToken();
// 通知の送信
const title = "通知するタイトル";
const body = "通知する本文";
const icon = "通知で表示するアイコン画像のURL"
const link = "通知をタップしたときに開くURL"
await admin.messaging().send({
// 送信先の端末のトークン
token: token,
// 通知する内容
notification: {
title: title,
body: body
},
// Web Push向けの通知内容
webpush: {
notification: {
icon: icon
},
fcmOptions: {
link: link
}
}
});
});
</code></pre>
<p>送信はこれだけ!</p>
<h3 id="ほかの小ネタ"><a href="#%E3%81%BB%E3%81%8B%E3%81%AE%E5%B0%8F%E3%83%8D%E3%82%BF">ほかの小ネタ</a></h3>
<h4 id="トークンを削除する"><a href="#%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B">トークンを削除する</a></h4>
<p><code>firebase.messaging().deleteToken();</code>でトークンを無効化できる。</p>
<pre><code class="typescript">// トークンの削除
public async deleteToken(user: User) {
const isSupported = firebase.messaging.isSupported();
if (isSupported) {
const token = await firebase.messaging().getToken();
await firebase.messaging().deleteToken(token);
}
}
</code></pre>
<h4 id="フォアグラウンドで通知を受け取ったときになにかする"><a href="#%E3%83%95%E3%82%A9%E3%82%A2%E3%82%B0%E3%83%A9%E3%82%A6%E3%83%B3%E3%83%89%E3%81%A7%E9%80%9A%E7%9F%A5%E3%82%92%E5%8F%97%E3%81%91%E5%8F%96%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E3%81%AA%E3%81%AB%E3%81%8B%E3%81%99%E3%82%8B">フォアグラウンドで通知を受け取ったときになにかする</a></h4>
<p><code>onMessage</code>を使うと、通知を受け取ったときに呼び出してくれる。</p>
<pre><code class="typescript">firebase.messaging().onMessage(async (payload) => {
// 受け取ったときの処理
});
</code></pre>
<h4 id="トークンが変更されたときになにかする"><a href="#%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%8C%E5%A4%89%E6%9B%B4%E3%81%95%E3%82%8C%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E3%81%AA%E3%81%AB%E3%81%8B%E3%81%99%E3%82%8B">トークンが変更されたときになにかする</a></h4>
<p><code>onTokenRefresh</code>を使うと、トークンが更新されたときに呼び出してくれる。<br />
新しいトークンは再度<code>getToken()</code>を呼ばないといけない。</p>
<pre><code class="typescript">firebase.messaging().onTokenRefresh(async () => {
// トークンが更新されたときの処理
});
</code></pre>
<h4 id="通知の許可状態を確認する"><a href="#%E9%80%9A%E7%9F%A5%E3%81%AE%E8%A8%B1%E5%8F%AF%E7%8A%B6%E6%85%8B%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B">通知の許可状態を確認する</a></h4>
<p>通知の状態は、<code>Notification.permission</code>で確認できるらしい。<br />
・<a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/notification/permission">Notification.permission - Web API | MDN</a></p>
<pre><code class="typescript">if (Notification.permission === "default") {
// 確認(デフォルト)
} else if (Notification.permission === "granted") {
// 許可
} else if (Notification.permission === "denied") {
// 拒否
}
</code></pre>
<p>以上!!</p>
<h3 id="【PR】これをつかって、こんなのつくりました!"><a href="#%E3%80%90PR%E3%80%91%E3%81%93%E3%82%8C%E3%82%92%E3%81%A4%E3%81%8B%E3%81%A3%E3%81%A6%E3%80%81%E3%81%93%E3%82%93%E3%81%AA%E3%81%AE%E3%81%A4%E3%81%8F%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F%EF%BC%81">【PR】これをつかって、こんなのつくりました!</a></h3>
<p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/2f71c56a-0ab2-5910-f203-e1fca191ad69.png" alt="スクリーンショット 2020-05-24 12.44.28.png" /></p>
<p>こんな通知を受け取れます!<br />
<img width="359" alt="スクリーンショット_2020-05-24_13_34_17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/1d4037bf-e662-a15a-4567-91f845ef5142.png"></p>
<p>1週間でWebサービスを作るイベント <a href="https://crieit.net/boards/web1week-202005">web1week</a>への投稿作品です!<br />
よかったら、遊んでみてください(<em>´ω`</em>)</p>
<p>■エアで投げ銭できるWebサービス「エア銭」<br />
URL: <a target="_blank" rel="nofollow noopener" href="https://air-money.netlify.app/">https://air-money.netlify.app/</a></p>
<h1 id="参考にしたサイトさま"><a href="#%E5%8F%82%E8%80%83%E3%81%AB%E3%81%97%E3%81%9F%E3%82%B5%E3%82%A4%E3%83%88%E3%81%95%E3%81%BE">参考にしたサイトさま</a></h1>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://developers.cyberagent.co.jp/blog/archives/9662/">FRESH! における Web プッシュ通知機能 〜実装編〜 | CyberAgent Developers Blog</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/firebase/quickstart-js/blob/bcce38ebc1e5602560e2b76b20f19b7834b8279e/messaging/firebase-messaging-sw.js#L15-L37">quickstart-js/firebase-messaging-sw.js at bcce38ebc1e5602560e2b76b20f19b7834b8279e · firebase/quickstart-js</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/reference/js/firebase.messaging.Messaging#deletetoken">Messaging | JavaScript SDK | Firebase</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/cloud-messaging/js/send-multiple#%E3%83%88%E3%83%94%E3%83%83%E3%82%AF-http-post-%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88">複数のデバイスにメッセージを送信する | Firebase</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#WebpushConfig">REST Resource: projects.messages | Firebase</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/cloud-messaging/send-message">アプリサーバーからの送信リクエストを作成する | Firebase</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/cloud-messaging/js/first-message">バックグラウンド アプリにテスト メッセージを送信する | Firebase</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/cloud-messaging/js/client">JavaScript Firebase Cloud Messaging クライアント アプリを設定する</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/ryo_hisano/items/1171beca22d5a04ed802">Firebase Cloud Messagingで始めるWebプッシュ通知 - Qiita</a></li>
</ul>
きらぷか@積読ハウマッチ/SSSAPIなど