推送通知故障排除和常见问题解答

有关 Expo 推送通知服务的常见问题集。


关于使用 expo-notifications 库和 Expo 推送通知服务设置推送时常见问题和常见问答的合集。

🌐 A collection of common issues and FAQs when setting up push notifications with the expo-notifications library and Expo push notification service.

Expo 推送通知服务常见问题解答

🌐 Expo push notification service FAQ

推送通知服务的费用

🌐 Cost of the push notification service

通过 Expo 推送通知服务发送通知没有任何成本。

🌐 There is no cost associated with sending notifications through Expo push notification service.

发送通知的限制

🌐 Limit of sending notifications

每个项目每秒最多可以发送 600 条通知。如果超过此速率,后续请求将会失败,直到速率再次降到每秒 600 条以下。

🌐 There is a limit of 600 notifications per second per project that can be sent. If you exceed this rate, subsequent requests will fail until the rate falls below 600 per second again.

为了获得最佳效果,我们建议你在服务器中添加节流(在 expo-server-sdk-node 中会自动处理)和重试逻辑。

🌐 For best results, we recommend you add throttling (which is handled automatically in the expo-server-sdk-node) and retry logic to your server.

使用 Expo 推送通知服务不是强制性的

🌐 Using Expo push notification service is not mandatory

你可以在 Expo 项目中使用任何推送通知服务。expo-notificationsgetDevicePushTokenAsync 方法 允许你获取原生设备推送令牌,然后你可以将其用于其他服务,或者甚至通过 FCM 和 APNs 直接发送通知

🌐 You can use any push notification service for Expo projects. The getDevicePushTokenAsync method from expo-notifications allows you to get the native device push token, which you can then use with other services, or even send your notifications directly through FCM and APNs.

与通知服务的连接已加密

🌐 Connections to notification service are encrypted

Expo 与 Apple 和 Google 的连接已加密并使用 HTTPS。

🌐 Expo's connections to Apple and Google are encrypted and use HTTPS.

通知的内容不被存储

🌐 Contents of the notification are not stored

Expo 不会将推送通知的内容存储超过将其传递给 Google 和 Apple 运营的推送通知服务所需的时间。通知仅存储在内存和消息队列中,而不会存储在数据库中。

🌐 Expo doesn't store the contents of push notifications any longer than it takes to deliver them to the push notification services operated by Google and Apple. Notifications are stored only in memory and in message queues, not in databases.

Expo 工作线程可以看到通知内容

🌐 Contents of the notifications may be seen by Expo staff

如果 Expo 团队正在积极调试推送通知服务,我们可能会看到通知内容(例如,在断点处),但 Expo 否则无法看到推送通知内容。

🌐 If the Expo team is actively debugging the push notifications service, we may see notification contents (for example, at a breakpoint) but Expo cannot see push notification contents otherwise.

交货保证

🌐 Delivery guarantees

Expo 尽最大努力将通知发送到由 Google 和 Apple 运营的推送通知服务。Expo 的基础设施设计为至少一次发送到底层推送通知服务。在某些情况下,通知可能会被多次发送到 Google 或 Apple,或者根本未发送,尽管这种情况很少发生。

🌐 Expo makes the best effort to deliver notifications to the push notification services operated by Google and Apple. Expo's infrastructure is designed for at-least-once delivery to the underlying push notification services. In some cases, a notification may be delivered to Google or Apple more than once or not at all, although these cases are rare.

在通知已交给底层推送通知服务后,Expo 会创建一个“推送回执”,记录交付是否成功。推送回执表明底层推送通知服务是否收到了该通知。

🌐 After a notification has been handed off to an underlying push notification service, Expo creates a "push receipt" that records whether the handoff was successful. A push receipt denotes whether the underlying push notification service received the notification.

最后,来自 Google 和 Apple 的推送通知服务遵循自己的政策将通知传递给设备。

🌐 Finally, the push notification services from Google and Apple follow their policies to deliver the notification to the device.

ExpoPushToken 什么时候以及为什么会改变

🌐 When and why does the ExpoPushToken change

ExpoPushToken 在应用升级过程中保持不变。在 Android 上,重新安装应用可能会导致令牌发生变化。在 iOS 上,即使卸载应用后再重新安装,令牌也会保持不变。

🌐 The ExpoPushToken remains the same across app upgrades. On Android, reinstalling the app may result in the token changing. On iOS, the token also remains the same even after uninstalling the app and reinstalling it.

如果你更改你的applicationIdexperienceId(通常是@expoUsername/projectSlug),它也会发生变化。

🌐 It also changes if you change your applicationId or experienceId (usually @expoUsername/projectSlug).

ExpoPushToken 永不过期。但是,如果你的某个用户卸载了应用,你将从 Expo 服务器收到 DeviceNotRegistered 错误。这意味着你应该停止向该令牌发送通知。

🌐 The ExpoPushToken never expires. However, if one of your users uninstalls the app, you'll receive a DeviceNotRegistered error back from Expo's servers. This means you should stop sending notifications to this token.

推送通知故障排除

🌐 Push notifications troubleshooting

通知不起作用

🌐 Notifications aren't working

推送通知涉及很多环节,因此可能由各种原因引起。为了缩小范围,请检查 推送工单推送收据 中的错误信息。

🌐 Push notifications have a lot of moving parts, so this can be due to a wide variety of reasons. To narrow things down, check the push ticket and push receipt for error messages.

你还可以通过在应用中测试本地通知来进一步缩小范围。这可以确保你所有的客户端逻辑都是正确的,并将问题缩小到服务器端或应用凭证。

🌐 You can also narrow things even further by testing local notifications in your app. This ensures all of your client-side logic is correct, and narrow things down to the server side or app credentials.

请查看这里的一些快捷终端命令,用于获取推送回执
  1. 发送通知:
curl -H "Content-Type: application/json" -X POST "https://exp.host/--/api/v2/push/send" -d '{ "to": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]", "title":"hello", "body": "world" }'
  1. 使用生成的票据 id 来请求推送收据:
curl -H "Content-Type: application/json" -X POST "https://exp.host/--/api/v2/push/getReceipts" -d '{ "ids": [ "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" ] }'

通知在开发模式下可以工作,但在发布模式下无法使用

🌐 Notifications work in development, but not in release mode

这表明你在生产应用中要么错误配置了凭据,要么根本没有配置。在 SDK 53 及更高版本中,Expo Go 不支持推送通知功能,因此要测试推送通知,你应该使用开发构建。在 SDK 52 及更早版本中,Expo Go 使用的是 Expo 的凭据,这允许在开发过程中无需设置自己的凭据即可使用推送通知。

🌐 This indicates that you have either misconfigured your credentials or didn't configure them at all in your production app. In SDK 53 and later, Expo Go does not support push notifications functionality, so to test push you should use a development build. In SDK 52 and earlier, Expo Go used Expo's credentials, which allowed push notifications to work in development without setting up your own credentials.

当你为应用商店构建应用时,你需要生成并使用自己的凭证。在 Android 上,请按照此指南操作。在 iOS 上,这由你的推送密钥处理(撤销与你的应用关联的推送密钥会导致通知无法送达。为解决此问题,请使用 eas credentials 添加一个新的推送密钥)。

🌐 When you build your app for the app stores, you need to generate and use your own credentials. On Android, follow this guide. On iOS, this is handled by your push key (revoking the push key associated with your app results in your notifications failing to be delivered. To fix that, add a new push key with eas credentials).

有关更多信息,请参见 应用签名

🌐 For more information, see app signing.

在安卓手机上通知有时会停止接收

🌐 Notifications occasionally stop coming through on Android

这可能是由于你发送的通知的 priority 级别所致。你可以了解更多关于 Android 优先级 的信息。Expo 接受四种优先级

🌐 This is likely due to the priority level of the notifications you're sending. You can learn more about Android priority. Expo accepts four priorities:

  • default:手动映射到 Apple 和 Google 文档中记录的默认优先级
  • high:映射到 Apple 和 Google 文档中记录的高优先级
  • normal:映射到 Apple 和 Google 文档中记录的普通优先级水平
  • (优先级省略):处理方式与指定 default 完全相同

将优先级设置为 high 可以最大程度地提高 Android 显示通知的可能性。

🌐 Setting the priority to high gives your notification the greatest likelihood that Android will display the notification.

处理过期的推送通知凭证

🌐 Handle expired push notification credentials

当你的推送通知凭证已过期时,运行 eas credentials,选择 iOS 和一个构建配置文件,然后删除你的推送通知密钥并生成一个新的。

🌐 When your push notification credentials have expired, run eas credentials, choose iOS and a build profile, then remove your push notification key and generate a new one.

iOS 未找到有效的 aps-environment 权限字符串错误

🌐 No valid aps-environment entitlement string found error for iOS

如果你尚未为你的 iOS 项目设置推送通知密钥,就会出现此错误。要检查,请访问 项目凭证页面

🌐 This error occurs if you haven't set up a push notification key for your iOS project. To check, go to the Project Credentials page.

要生成新的推送通知密钥,请通过运行以下命令触发新的构建:

🌐 To generate a new push notification key, trigger a new build by running:

Terminal
eas build --profile [profile] --platform ios

有关视觉指南,请参见 使用 EAS 的 Expo 通知视频

🌐 For a visual guide, see the Expo Notifications with EAS video.

发送通知时的错误消息

🌐 Error message when sending a notification

查看返回的推送票据或收据的 details 属性以获取更多信息。阅读此处了解常见错误代码响应及其对应的解决方案。

🌐 Check the details property of the returned push ticket or receipt for more information. Read this for common error code responses and their associated solutions.

在 iOS 上获取推送令牌需要很长时间

🌐 Fetching a push token takes a long time on iOS

getDevicePushTokenAsyncgetExpoPushTokenAsync 在 iOS 上有时可能需要较长时间才能解决。这超出了 expo-notifications 的控制范围,正如苹果在其 推送通知故障排除 技术说明中所述:

这不一定是一个错误情况。系统可能完全没有网络连接,因为它处于任何移动基站或 Wi-Fi 接入点的覆盖范围之外,或者可能处于飞行模式。你的应用不应将其视为错误,而应继续正常运行,仅禁用依赖推送通知的功能。

以下是我们社区成员解决此问题的一些方法:

🌐 Here are some ways our community members have resolved this issue:

阅读苹果关于推送通知故障排除的技术说明

阅读苹果关于推送通知故障排除的技术说明!这是关于这个问题的最可靠信息来源。为了帮助你理解他们的建议:

🌐 Read Apple's Technical Note on troubleshooting push notifications! This is the single most reliable source of information on this problem. To help you grasp what they're suggesting:

请稍后再试
在你的设备上禁用网络共享

你可能需要禁用网络共享,因为正如这个 Stack Overflow 答案所建议的,这可能会影响注册。

🌐 You may need to disable network sharing as this may impact the registration as suggested by this Stack Overflow answer.

重新启动你的设备

如果你只是更改了应用应该注册的 APNS 服务器(通过在同一设备上安装 TestFlight 版本覆盖 Xcode 版本),你可能需要像 这篇 Stack Overflow 回答 建议的那样重启设备。

🌐 If you just changed the APNS servers where the app should be registering (by installing a TestFlight build over an Xcode build on the same device) you may need to restart your device as suggested by this Stack Overflow answer.

使用 SIM 卡设置你的设备

如果你遇到此问题的设备没有安装 SIM 卡,看起来按照 这个 Stack Overflow 答案 的建议进行配置可能有助于缓解这个错误。

🌐 If the device you're experiencing this on hasn't been setup with a SIM card it looks like configuring it may help mitigate this bug as suggested by this Stack Overflow answer.

各种各样的

🌐 Miscellaneous

直接通过 FCM 和 APN 发送通知

🌐 Sending notifications directly through FCM and APNs

如果你不使用 Expo 推送通知服务,而是希望直接与 Google 和 Apple 通信,请参见 使用 FCM 和 APNs 发送通知

🌐 If you are not using Expo push notification service and instead, would like to communicate with Google and Apple directly, see Send notifications with FCM and APNs.

Android 上的通知图标是灰色或白色方形

🌐 Notification icon on Android is a gray or white square

这表明你提供的图片资源存在问题。图片应完全为白色且具有透明背景(这是 Google 要求并强制执行的,而不是 Expo)。更多信息,请参见 这篇文章

🌐 This indicates an issue with the image asset you're providing. The image should be all white with a transparent background (this is required and enforced by Google, not Expo). For more information, see this article.