1
4

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 5 years have passed since last update.

RN(expo)でNotification

Last updated at Posted at 2019-09-22

ひさいぶりにexpoのNotificationを調べたら、前のコードでは動かなくなっていたので再度メモ。
ついでに、送信をCloud functionsから行ってみる。

以前との変更

  • Permissionsがexpoから切離され、expo-permissionsを別途インストール、importする必要がある。

注意点(私の環境に依存)

  • firebase関連の設定を外部の./config/Firebase.jsで行っている(firebaseとdbを設定してるだけ)。
  • 既にfirestoreへ接続できる状態になっている。

実装:ReactNative側

特に難しいことはない。

App.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { Notifications } from 'expo';
import * as Permissions from 'expo-permissions'; //呼び出し方変わってる
import Firebase, { db } from './config/Firebase';
import firebase from 'firebase';

export default class App extends React.Component {

    registerForPushNotificationsAsync = async () => {

        try {
            //現在のNotificationパーミッション状況取得
            const { status: existingStatus } = await Permissions.getAsync(
                Permissions.NOTIFICATIONS
            );
            let finalStatus = existingStatus;

            //statusが許可じゃなければ(許可済みなら何もしない)
            if (existingStatus !== 'granted') {
                //許可を尋ねる
                const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
                finalStatus = status;
            }

            //それでも許可されてなかったら何もしない
            if (finalStatus !== 'granted') {
                return;
            }

            //token取得
            const token = await Notifications.getExpoPushTokenAsync();

            //保存
            await this.saveDeviceToken(token);

            //表示
            alert("token=" + token);
            console.log(token);

        } catch (e) {
            console.log(e);
        }
    }

    saveDeviceToken = async (token) => {
        try {
            const docRef = await db.collection('tokens').add({
                token: token,
                created_at: firebase.firestore.FieldValue.serverTimestamp(),
                user: 'sample',
            })
        } catch (e) {
            console.log(e);
        }
    }

    handleNotification = (notification) => {
        if (notification.origin === 'selected') {
            //何もしなくても通知される
        } else if (notification.origin === 'received') {
            //jsonで{"message":"ほげほげ"}が送られていることが前提なら、下記のように書ける。
            //alert('通知が来たようです。内容は:' + notification.data.message + "です。");
            alert('通知が来たようです。');
        }
    }

    componentDidMount = () => {
        //リスナー登録
        this.notificationSubscription = Notifications.addListener(this.handleNotification);
    }

    componentWillUnmount = () => {
        //これを入れないと、起動時に通知が来る
        this.notificationSubscription.remove();
    }

    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>App</Text>
                <Button
                    title="get Notification token"
                    onPress={this.registerForPushNotificationsAsync}
                />
            </View>
        );
    }
}

実装:Cloud Functions側

とりあえず、ピンポイントにdocumentを指定してtokenを取得し、そのtokenを利用して(一人)にNotificationを送信している。

index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();

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



exports.helloExpo = functions.region('asia-northeast1').https.onRequest(async (request, response) => {

    //とりあえずdocを指定してtokenを取得
    const docRef = db.collection('tokens').doc('omMCYVMGnzcxIySy2DSo');
    const snapshot = await docRef.get().catch(e => console.log(e));
    const token = snapshot.data().token;

    //メッセージ組み立て
    const message = {
        to: token,
        sound: 'default',
        title: 'test',
        body: 'hello',
        data: { name: 'foo', message: 'test' }
    }

    //メッセージをまとめる
    const chunks = expo.chunkPushNotifications([message]);
    const tickets = [];

    //ループ
    chunks.forEach(async chunk => {
        //送る
        const ticketChunk = await expo.sendPushNotificationsAsync(chunk).catch(e => console.log(e));
        tickets.push(...ticketChunk);
    });

    response.send('send notificaiton.')
});

課題

  • フォワグラウンドのときにNotificationが届いたときの処理についてもう少し調べる必要がある。
1
4
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
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?