Firebase でチャットを作ってみた(iOS) その4 チャット更新時にプッシュ通知を飛ばす
LINE やSkype などでよくある、メッセージ受信時のPush 通知を実装したいと思います。
ただ、これはFirebase だけで実現するのは難しいようなので別のサーバを挟むやり方でやってみます。
今回は Node.js のサーバを使って実装してみます。
1. 端末でプッシュ通知を受信できるようにする。
まずは端末側でプッシュ通知を受信できるように実装します。
少し手順が複雑ですが、Firebase の公式ページに詳しく記載があるのでこちらを参照ください。
https://firebase.google.com/docs/cloud-messaging/ios/first-message
こちらの「SDKを追加する」以降の手順を行い、Firebase コンソールからプッシュ通知を送信できるようにします。
ちなみに iOSアプリのプッシュ通知は、そのアプリがフォアグラウンドの状態にある時は通知センターに表示されないので、試す際はアプリをバックグラウンドにするか、端末をスリープ状態にしておく必要があります。
2. トピックへ登録
Firebase からプッシュ通知を送る方法としては、1. で登録した際に得られる端末ごとのトークン情報を指定して送信する方法と、トピックを指定して通知を送信する方法などがあります。
トピックの使い方としては、予め通知を受信したい端末からトピックに登録しておくと、
そのトピックに対して送信されたメッセージをプッシュ通知で受信できるようになります。
こちらも公式の説明に詳細があるので参考になるかと思います。
https://firebase.google.com/docs/cloud-messaging/ios/topic-messaging?hl=ja
今回はこのトピックを使ってプッシュ通知を受信する機能を実現することにします。
まずは下記コードでアプリからトピックへの登録を行います。
1 2 |
import FirebaseMessaging |
1 2 |
FIRMessaging.messaging().subscribe(toTopic: "/topics/test") |
トピックは存在しない名称のものを指定すると自動的に作成されます。
この時点で、このトピックに対してのメッセージがプッシュ通知として届くようになっています。
試しにトピックにメッセージを送信してみます。
Firebase コンソールからトピックを指定してメッセージを送信することもできますが、新規に作成したトピックがFirebase コンソールから見えるようになるには、少し時間がかかるらしいです。
ここでは、curl を使って HTTP リクエストを投げてトピックにメッセージを投げてみます。
下記のような curl コマンドを送ります。
1 2 3 4 5 |
curl --header "Authorization: key=サーバーキー" \ --header Content-Type:"application/json" \ https://fcm.googleapis.com/fcm/send \ -d "{\"to\": \"/topics/test\",\"priority\":\"high\",\"content_available\":true,\"notification\": {\"body\": \"お知らせ\",\"badge\": \"1\"}}" |
公式ページに書かれているJSON リクエストを投げてみたのですが、どうしても端末に通知が来ませんでした。
下記ページを参考にさせていただき、上記リクエストを送信したら成功しました。
http://qiita.com/gungle/items/ba923016be6d0840ec46
ちなみにサーバーキーは Firebase コンソールから、「プロジェクトの設定」(歯車のアイコンをクリックすると表示される)-> 「クラウドメッセージング」から確認できます。
3. データベース更新タイミングでトピックにメッセージを送信する
前の手順でHTTPリクエストを使ってトピックにメッセージを送信できることは確認できましたので、今度はこれを通常のチャットアプリと同じようにチャットのメッセージ送信と連携するようにしたいと思います。
iOS端末から直接HTTPリクエストを送信することもできなくはないですが、サーバーキーをアプリに内包することになってしまうので、セキュリティ的に問題がありそうです。
そこで、Node.js のサーバーを別で用意して、そちらを経由する方法でプッシュ通知を投げる方法で実現します。
3.1 Firebase + Node.js 環境の構築
まずは公式ページを参照して Node.js用の Firebase 環境を作成します。
https://firebase.google.com/docs/server/setup?hl=ja
上記ページの手順の補足ですが、サービスアカウントを作成する際の役割を「編集者」にしています。役割が未設定のままだと、リアルタイムデータベースへのアクセスができていないように思いました。
3.2 Node.js サーバプログラム作成
ほぼほぼこちらのページの内容をそのまま使わせてもらいました。
http://qiita.com/plasticstraw/items/1c8d8e7f6833528b984f
下記のコードを chatDemoServer.js という名前で作成します。
データベースを監視し、変更があれば 2.の HTTP リクエストを投げる、というコードになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
var https = require('https'); var firebase = require('firebase'); var fs = require('fs') var config = JSON.parse(fs.readFileSync('config.json', 'utf8')); firebase.initializeApp({ serviceAccount: "serviceAccountCredentials.json", databaseURL: config.databaseUrl }) var db = firebase.database(); var ref = db.ref() ref.once("value", function(snapshot) { const numChildren = snapshot.numChildren(); var counter = 0; ref.on("child_added", function(addedSnapshot) { if( counter < numChildren ){ // skip data before the server launched. counter++; return; } // notifies new message. sendNotification(); }); }); function sendNotification(){ var postData = JSON.stringify({ "to": "/topics/test", "priority" : "high", "content_available": true, "notification" : { "body" : "おしらせ", "badge": "1" } }); var options = { hostname: 'fcm.googleapis.com', path: '/fcm/send', method: 'POST', headers: { "Content-Type": "application/json", "Authorization" : "key=" + config.apiKey } }; var req = https.request(options, (res) => { console.log("OK"); }); req.on('error', (e) => { console.error("problem with request: " + e.message); }); req.write(postData); req.end(); } |
APIキーなどの非公開の情報は別ファイルにしてます。下記のようなファイルを config.json という名前で同じ上記 chatDemoServer.js と同じディレクトリに配置します。
1 2 3 4 5 |
{ "databaseUrl": "データベースのURL", "apiKey": "サーバーキー" } |
とりあえず手元で Node.js で動かして動作確認しておきます。
1 2 |
node chatDemoServer.js |
この状態でアプリでチャットを更新すると、プッシュ通知が届くはずです。
3.3 Node.js ホスティングサービスへ登録
後はできた javascript を Node.js をホスティングしているサービスへ登録します。
私は IBM の Bluemix を使いました。計算上は 512M のメモリ割り当てをしておけば24時間動かしていても無料で利用できそうでしたので。
手順は下記の公式ページを参考にしました。
https://www.ibm.com/developerworks/jp/cloud/library/j_cl-bluemix-nodejs-app/
ただし、今回作成した javascript はポートをLISTEN するサーバプログラムではないので、死活管理、URLの割り当ては不要です。cf push は以下のようにオプション付きで実行しました。こうしないと死活管理でシャットダウンさせられてしまいました。
1 2 |
cf push ChatDemo -u none --no-route |
できたコード
Github で管理しているのでそちらを参照してください。
https://github.com/ryuta46/ChatDemo
今回はデータベース更新タイミングでプッシュ通知を送るだけのプログラムですが、本来であれば更新された内容(チャットのメッセージ)をプッシュ通知に含めることも可能です。
次回以降でもう少し全体を整理したアプリを作成していこうかと思います。
最後まで読んでいただきありがとうございます。 このブログを「いいな」と感じていただけましたら、Twiter にてフォローいただけるとうれしいです。ブログ更新情報などもお届けします。
Follow @ryuta461
この記事をシェアする