React Native + ExpoでPush通知を試す
React Native + Expo で Push 通知を試した時のメモ。
参考にしたドキュメント
前提
expo-cliはインストール済み。バージョンは4.7.3- iOS アプリ
Expo Goで動作確認。バージョンは2.21.3
expo-cli を更新
なんかexpo-cliが古かったので新しいバージョンに更新。
Expo Go も最新に更新。
$ yarn add -g expo-cliプロジェクト作成
まずはプロジェクトを作成する。
$ expo i -t blank起動方法について
Expo の起動はexpo start、yarn startどちらでも OK。
動作確認の方法について
Expo 起動でブラウザに管理コンソール的なものが表示されるので、 PC とスマホが同じ Wifi に接続されていることを確認して、QR コードを読み取れば Expo Go アプリ上で作ったアプリが起動する。
ちなみに、Expo Go を開いている時にシェイクするとメニューが表示されるので、そこからアプリの Reload ができる。
ライブラリを追加
$ yarn add expo-constants
$ yarn add expo-notificationsソースコード
以下のコードを App.js にコピペ。Expo Document の Usage そのままでいいと思う。
import Constants from "expo-constants";
import * as Notifications from "expo-notifications";
import React, { useState, useEffect, useRef } from "react";
import { Text, View, Button, Platform } from "react-native";
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
export default function App() {
const [expoPushToken, setExpoPushToken] = useState("");
const [notification, setNotification] = useState(false);
const notificationListener = useRef();
const responseListener = useRef();
useEffect(() => {
registerForPushNotificationsAsync().then((token) =>
setExpoPushToken(token)
);
// This listener is fired whenever a notification is received while the app is foregrounded
notificationListener.current =
Notifications.addNotificationReceivedListener((notification) => {
setNotification(notification);
});
// This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
responseListener.current =
Notifications.addNotificationResponseReceivedListener((response) => {
console.log(response);
});
return () => {
Notifications.removeNotificationSubscription(
notificationListener.current
);
Notifications.removeNotificationSubscription(responseListener.current);
};
}, []);
return (
<View
style={{
flex: 1,
alignItems: "center",
justifyContent: "space-around",
}}
>
<Text>Your expo push token: {expoPushToken}</Text>
<View style={{ alignItems: "center", justifyContent: "center" }}>
<Text>
Title: {notification && notification.request.content.title}{" "}
</Text>
<Text>Body: {notification && notification.request.content.body}</Text>
<Text>
Data:{" "}
{notification && JSON.stringify(notification.request.content.data)}
</Text>
</View>
<Button
title="Press to Send Notification"
onPress={async () => {
try {
await sendPushNotification(expoPushToken);
} catch (error) {
console.log(error);
}
}}
/>
</View>
);
}
// Can use this function below, OR use Expo's Push Notification Tool-> https://expo.io/notifications
async function sendPushNotification(expoPushToken) {
const message = {
to: expoPushToken,
sound: "default",
title: "Original Title",
body: "And here is the body!",
data: { someData: "goes here" },
};
try {
await fetch("https://exp.host/--/api/v2/push/send", {
method: "POST",
headers: {
Accept: "application/json",
"Accept-encoding": "gzip, deflate",
"Content-Type": "application/json",
},
body: JSON.stringify(message),
});
} catch (error) {
console.log(error);
}
}
async function registerForPushNotificationsAsync() {
let token;
try {
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("Failed to get push token for push notification!");
return;
}
token = (await Notifications.getExpoPushTokenAsync()).data;
console.log(token);
} else {
alert("Must use physical device for Push Notifications");
}
if (Platform.OS === "android") {
Notifications.setNotificationChannelAsync("default", {
name: "default",
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#FF231F7C",
});
}
} catch (error) {
console.log(error);
}
return token;
}ハマったこと
以下のエラーが発生して expo push token が取得できなかった。
エラーメッセージ通り、サーバー起動前にexpo loginしたら、無事に Push 通知の確認ができた。
Error encountered while fetching Expo token, expected an OK response, received: 400 (body: ”{“errors”:[{“code”:“VALIDATION_ERROR”,“message”:“The Expo push notification service is supported only for Expo projects. Ensure you are logged in to your Expo developer account on the computer from which you are loading your project.”,“isTransient”:false}]}”).