0
2

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.

ExpoとCloud Functions for Firebaseで通知機能の実装

Posted at

はじめに

expoでメッセージ機能がついたアプリを作る際、通知機能は必須ということで、Cloud Functions for Firebaseを使って通知機能を実装します。

プッシュトークンを取得する

↑を参考にユーザから通知の許可を取り、プッシュトークンを取得します。

index.tsx
const registerForPushNotificationsAsync = async () => {
    if (Constants.isDevice) {
      const {
        status: existingStatus
      } = await Notifications.getPermissionsAsync();
      let finalStatus = existingStatus;
      if (existingStatus !== "granted") {
        const { status } = await Notifications.requestPermissionsAsync();
        finalStatus = status;
      }
      if (finalStatus !== "granted") {
        //alert("プッシュ通知のプッシュトークンを取得できませんでした.");
        return;
      }
      //const token = (await Notifications.getExpoPushTokenAsync()).data;
      //console.log(token);
    } else {
      //alert("プッシュ通知には物理デバイスを使用する必要があります");
      return;
    }

    if (Platform.OS === "android") {
      Notifications.setNotificationChannelAsync("default", {
        name: "default",
        importance: Notifications.AndroidImportance.MAX,
        vibrationPattern: [0, 250, 250, 250],
        lightColor: "#FF231F7C"
      });
    }
  };

プッシュトークンを保存する

今回は複数端末に通知を送ることができるように、以下のようにプッシュトークンをCloud Firestoreに保存します。
ログイン時やログアウト時にプッシュトークンを追加・削除するようにしています。

db.ts
export const db = firebase.firestore();

export const addPushToken = async (uid: string) => {
  if (Constants.isDevice) {
    const pushToken = await Notifications.getExpoPushTokenAsync();
    await db.collection("users").doc(uid).update({
      pushToken: firebase.firestore.FieldValue.arrayUnion(pushToken.data)
    });
  }
};

export const removePushToken = async (uid: string) => {
  if (Constants.isDevice) {
    const pushToken = await Notifications.getExpoPushTokenAsync();
    await db.collection("users").doc(uid).update({
      pushToken: firebase.firestore.FieldValue.arrayRemove(pushToken.data)
    });
  }
};

メッセージ機能の実装

↑を使い、メッセージページを作りました。
onSendにて以下をFirestoreに保存します。

{
  id,
  uid,        // 送信者のuid
  friendId,   // 受信者のuid
  createdAt,
  text     // メッセージ内容
}

Cloud Functionsの実装

新しいメッセージが保存されることをトリガーにしています。

↑を参考にしています。

メッセージ送信にて保存した受信者のidからpush tokenを取得し、送信者のidから送信者名を取得し、通知を送信します。

index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();

const { Expo } = require("expo-server-sdk");
const expo = new Expo();

exports.sendNotification = functions
  .region("asia-northeast1")
  .firestore.document("messages/{messageId}")
  .onCreate(async (snap, context) => {
    const messageData = snap.data();

    // 受信者のpush tokenの取得
    const recipientId = messageData.friendId;
    const recipientSnapshot = await db
      .collection("users")
      .doc(recipientId)
      .get();
    const recipientData = recipientSnapshot.data();
    if (!userData.pushToken) {
      functions.logger.log("push tokenを取得できませんでした。");
    } else {
      const pushTokenList = userData.pushToken;

      // 送信者の名前の取得
      const senderId = messageData.uid;
      const senderSnapshot = await db
        .collection("users")
        .doc(senderId)
        .get();
      const senderData = senderSnapshot.data();
      const senderName = senderData.name;

      // プッシュ通知用のメッセージオブジェクトを作成
      let messages = [];
      for (let pushToken of pushTokenList) {
        if (!Expo.isExpoPushToken(pushToken)) {
          functions.logger.error(
            `Push token ${pushToken} is not a valid Expo push token`
          );
        }
        messages.push({
          to: pushToken,
          title: senderName,
          body: messageData.text
        });
      }

      const chunks = expo.chunkPushNotifications(messages);
      const tickets = [];
      (async () => {
        // Expo Push API をリクエスト
        for (let chunk of chunks) {
          try {
            const ticketChunk = await expo.sendPushNotificationsAsync(chunk);
            tickets.push(...ticketChunk);
          } catch (error) {
            functions.logger.error(error);
          }
        }
      })();
    }
  });
0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?