Expo 推送通知设置

编辑

学习如何设置推送通知,获取开发和生产的凭证,并发送测试推送通知。


要利用 Expo 推送通知服务,您必须通过安装一组库来配置您的应用程序,实现处理通知的功能,并为 Android 和 iOS 设置凭证。

完成本指南中列出的步骤,或按照以下更详细的视频进行操作。最后,您将能够发送推送通知并在设备上接收它。

使用 EAS 的 Expo 通知 | 完整指南
使用 EAS 的 Expo 通知 | 完整指南

学习如何在 Expo 项目中设置推送通知。此视频涵盖在 Android 上配置 Firebase 以供 FCM v1 使用、在 EAS 上设置 Android 和 iOS 凭证、使用 EAS Build 构建以及使用 Expo 通知工具进行测试。


要准备好客户端以接收推送通知,需要以下事项:

  • 用户的许可,以便向他们发送推送通知。
  • 应用的 ExpoPushToken

您想直接使用 FCM / APNs,而不是 Expo 推送通知服务吗?

如果您需要对通知进行更细致的控制,则可能需要直接与 FCM 和 APNs 进行通信。Expo 并未限制您使用 Expo 应用程序服务,expo-notifications API 是独立于推送服务的。了解如何 "使用 FCM 和 APNs 发送通知"

先决条件

重要: Android 模拟器和 iOS 模拟器不支持推送通知。需要真实设备。

本指南中描述的步骤使用 EAS Build。这是设置通知的最简单方法,因为您的 EAS 项目还将包含 通知凭证。不过,您也可以通过在 本地构建项目 时使用 expo-notifications 库,而无需 EAS Build。

1

安装库

运行以下命令以安装 expo-notificationsexpo-deviceexpo-constants 库:

Terminal
npx expo install expo-notifications expo-device expo-constants
  • expo-notifications 库用于请求用户的许可并获取用于发送推送通知的 ExpoPushToken
  • expo-device 用于检查应用是否在物理设备上运行。
  • expo-constants 用于从应用配置中获取 projectId 值。

2

添加配置插件

在您的 应用配置plugins 数组中添加 expo-notifications 插件:

app.json
{ "expo": { %%placeholder-start%%... %%placeholder-end%% "plugins": [ %%placeholder-start%%... %%placeholder-end%% "expo-notifications" ] } }

3

添加最小工作示例

以下代码展示了如何在 React Native 应用中注册、发送和接收推送通知的工作示例。将其复制并粘贴到您的项目中:

App.tsx
import { useState, useEffect, useRef } from 'react'; import { Text, View, Button, Platform } from 'react-native'; import * as Device from 'expo-device'; import * as Notifications from 'expo-notifications'; import Constants from 'expo-constants'; Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldPlaySound: true, shouldSetBadge: true, shouldShowBanner: true, shouldShowList: true, }), }); async function sendPushNotification(expoPushToken: string) { const message = { to: expoPushToken, sound: 'default', title: 'Original Title', body: 'And here is the body!', data: { someData: 'goes here' }, }; 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), }); } function handleRegistrationError(errorMessage: string) { alert(errorMessage); throw new Error(errorMessage); } async function registerForPushNotificationsAsync() { if (Platform.OS === 'android') { await Notifications.setNotificationChannelAsync('default', { name: 'default', importance: Notifications.AndroidImportance.MAX, vibrationPattern: [0, 250, 250, 250], lightColor: '#FF231F7C', }); } if (Device.isDevice) { const { status: existingStatus } = await Notifications.getPermissionsAsync(); let finalStatus = existingStatus; if (existingStatus !== 'granted') { const { status } = await Notifications.requestPermissionsAsync(); finalStatus = status; } if (finalStatus !== 'granted') { handleRegistrationError('Permission not granted to get push token for push notification!'); return; } const projectId = Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId; if (!projectId) { handleRegistrationError('Project ID not found'); } try { const pushTokenString = ( await Notifications.getExpoPushTokenAsync({ projectId, }) ).data; console.log(pushTokenString); return pushTokenString; } catch (e: unknown) { handleRegistrationError(`${e}`); } } else { handleRegistrationError('Must use physical device for push notifications'); } } export default function App() { const [expoPushToken, setExpoPushToken] = useState(''); const [notification, setNotification] = useState<Notifications.Notification | undefined>( undefined ); useEffect(() => { registerForPushNotificationsAsync() .then(token => setExpoPushToken(token ?? '')) .catch((error: any) => setExpoPushToken(`${error}`)); const notificationListener = Notifications.addNotificationReceivedListener(notification => { setNotification(notification); }); const responseListener = Notifications.addNotificationResponseReceivedListener(response => { console.log(response); }); return () => { notificationListener.remove(); responseListener.remove(); }; }, []); 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 () => { await sendPushNotification(expoPushToken); }} /> </View> ); }

配置 projectId

使用前面的示例,当您注册推送通知时,您需要使用 projectId。此属性用于将 Expo 推送令牌归因于特定项目。对于使用 EAS 的项目,projectId 属性表示该项目的全局唯一标识符(UUID)。

projectId 在创建开发构建时会自动设置。但是,我们建议在项目代码中手动设置它。为此,您可以使用 expo-constants 从应用配置中获取 projectId 值。

const projectId = Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId; const pushTokenString = (await Notifications.getExpoPushTokenAsync({ projectId })).data;

将 Expo 推送令牌归因于您项目的唯一 ID 的一个优点是,当项目在不同帐户之间转移或现有帐户更名时,它不会更改。

4

获取开发版凭证

对于 Android 和 iOS,有不同的要求来设置您的凭证。

对于 Android,您需要配置 Firebase Cloud Messaging (FCM) 以获取凭证,并设置您的 Expo 项目。

请按照 添加 Android FCM V1 凭证 中的步骤来设置您的凭证。

需要付费的 Apple 开发者账户来生成凭证。

对于 iOS,请确保您在要测试的设备上 注册了您的 iOS 设备,然后第一次运行 eas build 命令时。

如果您第一次创建开发构建,系统会询问您启用推送通知。初次提示时,回答以下问题为“是”:

  • 为您的项目设置推送通知
  • 生成新的 Apple 推送通知服务密钥

如果您不使用 EAS Build,请手动运行 eas credentials

5

构建应用

Terminal
eas build

6

使用推送通知工具进行测试

创建并安装开发构建后,您可以使用 Expo 推送通知工具 快速向您的设备发送测试通知。

  1. 启动项目的开发服务器:

    Terminal
    npx expo start
  2. 在您的设备上打开开发构建。

  3. 在生成 ExpoPushToken 后,将该值与其他详细信息(例如消息标题和正文)一起输入到 Expo 推送通知工具中。

  4. 点击 Send a Notification 按钮。

从工具发送通知后,您应该会在设备上看到通知。以下是 Android 设备接收推送通知的示例。