42
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FirebaseのFirestore更新をトリガーにFunctionsでプッシュ通知

Last updated at Posted at 2019-12-09

繋がらないマッチングプラットフォーム「FLAPTALK」を運営する株式会社OneSmallStep@_takeshi_24です。

この記事は「Nuxt.jsとFirebaseとCloudFunctionsでWebアプリ開発」シリーズとして、連載していきます。
Nuxt.jsとFirebaseなどを使ってWebアプリケーション開発にチャレンジしたい方、是非Qiitaアカウントかtwitterをフォローしていただき、ツッコミやいいね!お願いします!

今回はアプリケーションにプッシュ通知を送るための、Firebase Cloud Messagingについて説明します。
Webアプリケーションにもプッシュ通知可能ですが、iOSのWebアプリケーションは対象外になります。

今回は、RealtimeDatabase、Firestoreの更新をトリガーに、CloudFunctionsの関数を実行し、特定のユーザーにCloudMessagingでプッシュ通知を送る方法について記載します。

はじめに

こちらの記事は、「Nuxt.jsとFirebaseとCloudFunctionsでWebアプリ開発」シリーズとして連載していますので、「diffeasyCTO西の24(にし)日連続投稿チャレンジ Advent Calendar 2019」の過去の記事もご覧ください。

CloudMessagingの準備はこちら「Nuxt.jsアプリにFirebase Cloud Messagingでプッシュ通知」に記載していますので、CloudMessagingの準備がまだの方は、まずこちらの記事で準備をお願いします。

##FirestoreをトリガーにCloudFunctions実行
まずは、Firestoreのデータが更新されたら、特定のユーザーにプッシュ通知を送る処理について説明していきます。

###トリガーのもととなるFirestore更新の画面
まずは、トリガーを発生させるFirestore更新のサンプルを実装します。
メッセージ入力欄と、ユーザー一覧とユーザーごとに「プッシュ通知」ボタンを配置し、「プッシュ通知」ボタンをクリックしたら、対象のユーザー宛てにメッセージ入力欄の内容を通知するサンプルです。
スクリーンショット 2019-12-05 7.59.51.png

画面のソースは以下の通りです。

/pages/users/index.vue
<template>
  <section class="container">
    <v-text-field v-model="message"></v-text-field>
    <v-row v-for="(user, key, index) in users" :key="index">
      <v-col>
        <p>{{ user.data.familyName }} {{ user.data.firstName }}</p>
      </v-col>
      <v-col>
        <v-btn @click="sendMessage(user.uid)">プッシュ通知</v-btn>
      </v-col>
    </v-row>
  </section>
</template>
<script>
import firebase from "firebase";
const db = firebase.firestore();

export default {
  data() {
    return {
      message: "",
      users: []
    };
  },
  created() {
    this.getUsers();
  },
  methods: {
    async getUsers() {
      const snapShot = await db.collection("users").get();
      this.users = snapShot.docs.map(doc => {
        const obj = { uid: doc.id, data: doc.data() };
        return obj;
      });
    },
    sendMessage(uid) {
      db.collection("messages")
        .doc(uid)
        .set({
          message: this.message
        });
      this.message = "";
    }
  }
};
</script>

解説していきます。
1.created()のなかで、getUsers()を実行し、Firestoreからユーザーの一覧を取得しています。データの内容は以下のような形です。FirebaseAuthenticationのUIDをusersのIDに設定していて、fcmTokenにFirebase Cloud Messagingのトークンがセットされます。
(参照:Nuxt.jsアプリにFirebase Cloud Messagingでプッシュ通知
スクリーンショット 2019-12-05 21.28.11.png

2.sendMessage()で、対象のuidのmessagesコレクションに、テキストのメッセージをセットします。
スクリーンショット 2019-12-05 21.34.35.png

3.Firestoreのルールを追加します。

firestore.rules
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow update, delete: if request.auth.uid == userId;
      allow read, create: if request.auth.uid != null;
    }
    match /messages/{userId} {
      allow create, read, update, delete: if request.auth.uid != null;
    }
  }
}

###更新をトリガーにCloudFunctionsを実行
messagesコレクションのデータが更新されると、それをトリガーにCloudFunctionsの関数が実行されます。

1.functionsのindex.jsに以下の関数を追加します。

index.js
exports.sendPushMessage = firestore
  .document("messages/{userId}")
  .onWrite(async (change, context) => {
    const data = change.after.data();
    const previousData = change.before.data();

    // uidから通知先のユーザー情報を取得
    const userRef = await admin
      .firestore()
      .collection("users")
      .doc(context.params.userId);
    const userDoc = await userRef.get();

    if (userDoc.exists) {
      const user = userDoc.data();
      // 通知のタイトルと本文を設定
      const payload = {
        notification: {
          title: `${user.familyName} ${user.firstName}さんへ`,
          body: data.message
        }
      };

      /// プッシュ通知を送信
      if (user.fcmToken) {
        admin.messaging().sendToDevice(user.fcmToken, payload);
      } else {
        console.error("No Firebase Cloud Messaging Token.");
      }
    } else {
      console.error("No User.");
    }

    return true;
  });

ここでは、onWriteを使って、ドキュメントに書き込み、更新があったときに関数を呼び出しています。
その他、以下のようなトリガーが利用できます。

| イベントタイプ | トリガー |
|:--|:--|| onCreate | ドキュメントが最初に書き込まれたときにトリガーされます。 |
| onCreate | ドキュメントが最初に書き込まれたときにトリガーされます。 |
| onUpdate | すでに存在するドキュメントの値が変更されたときにトリガーされます。 |
| onDelete | データを含むドキュメントが削除されたときにトリガーされます。 |
| onWrite | onCreate、onUpdate または onDelete がトリガーされたときにトリガーされます。 |

Cloud Firestore トリガーより

2.ローカルのエミュレーターではプッシュ通知は送れませんので、Firebaseにデプロイします。

$ firebase deploy

3.画面からメッセージを入力し、通知を送るユーザーの「プッシュ通知」ボタンをクリックします。
スクリーンショット 2019-12-05 22.03.50.png

4.CloudFunctionsが起動されます。Firebaseのコンソールでログを監視できます。
スクリーンショット 2019-12-05 22.18.49.png

5.通知が表示されます。Android端末だと、待ち受けにも通知が表示されます。
スクリーンショット 2019-12-05 22.18.49.png

##RealtimeDatabaseをトリガーにCloudFunctionsを実行
RealtimeDatabaseでも以下の通り、Firestoreと同じようにデータの更新をトリガーにCloudFunctionsを実行できます。

exports.sendPushMessage = functions.database
  .ref("/messages/{pushId}/original")
  .onCreate((snapshot, context) => {
      // ・・・ 
  });
イベントタイプ トリガー
onWrite Realtime Database 内でデータが作成、更新、削除されるとトリガーされます。
onCreate Realtime Database 内で新しいデータが作成されるとトリガーされます。
onUpdate Realtime Database 内でデータが更新されるとトリガーされます。
onDelete Realtime Database 内でデータが削除されるとトリガーされます。
Database トリガーより

##最後に
この記事は「Nuxt.jsとFirebaseとCloudFunctionsでWebアプリ開発」シリーズとして、連載していきます。
続きはアドベントカレンダー「diffeasyCTO西の24(にし)日連続投稿チャレンジ Advent Calendar 2019」に掲載していきます。

Nuxt.jsとFirebaseなどを使ってWebアプリケーション開発にチャレンジしたい方、是非Qiitaアカウントかtwitterをフォローしていただき、ツッコミやいいね!お願いします!

#advent_24のハッシュタグでフィードバックいただけると嬉しいです!

42
30
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
42
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?