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

编辑页面

关于 Expo 推送通知服务的常见问题汇总。


For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.

设置 expo-notifications 库和 Expo 推送通知服务时常见问题及常见问答。

Expo 推送通知服务 FAQ

推送通知服务的费用

通过 Expo 推送通知服务发送通知不收取任何费用。

发送通知的限制

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

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

使用 Expo 推送通知服务不是必须的

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

到通知服务的连接是加密的

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

不会存储通知内容

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

Expo 员工可能会看到通知内容

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

投递保证

Expo 会尽最大努力将通知传递给由 Google 和 Apple 运营的推送通知服务。Expo 的基础设施旨在至少向底层推送通知服务投递一次。在某些情况下,通知可能会被发送到 Google 或 Apple 多次,或者根本未送达,不过这些情况很少见。

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

最后,Google 和 Apple 的推送通知服务会按照各自的策略将通知投递到设备。

ExpoPushToken 何时以及为何会变化

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

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

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

推送通知故障排查

通知无法正常工作

推送通知涉及很多环节,因此原因可能很多。为了缩小问题范围,请查看 push ticketpush receipt 中的错误信息。

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

在这里查看一些可用于获取推送回执的快速终端命令
  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. 使用返回的 ticket id 请求推送回执:
curl -H "Content-Type: application/json" -X POST "https://exp.host/--/api/v2/push/getReceipts" -d '{ "ids": [ "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" ] }'

开发环境可用,但正式版不可用

这表明你的凭证配置有误,或者在生产应用中根本没有配置凭证。在 SDK 53 及更高版本中,Expo Go 不支持推送通知功能,因此要测试推送,你应该使用 开发构建。在 SDK 52 及更早版本中,Expo Go 使用的是 Expo 的凭证,因此无需配置你自己的凭证也能在开发环境中正常使用推送通知。

当你为应用商店构建应用时,需要生成并使用自己的凭证。在 Android 上,请参照本指南。在 iOS 上,这由你的 push key 处理(吊销与你的应用关联的 push key 会导致通知投递失败。要修复它,请使用 eas credentials 添加新的 push key)。

更多信息请参见 应用签名

Android 上通知偶尔停止推送

这很可能与你发送的通知的 priority 级别有关。你可以了解更多关于 Android 优先级 的信息。Expo 支持四种优先级

  • default:手动映射为 Apple 和 Google 文档中定义的默认优先级
  • high:映射为 Apple 和 Google 文档中定义的高优先级
  • normal:映射为 Apple 和 Google 文档中定义的普通优先级
  • (未省略 priority):完全按指定 default 处理

将优先级设置为 high 会让你的通知在 Android 上显示的可能性最大。

处理已过期的推送通知凭证

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

iOS 上出现 No valid aps-environment entitlement string found 错误

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

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

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

如需可视化指南,请查看 Expo Notifications with EAS 视频

发送通知时的错误信息

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

在 iOS 上获取推送令牌耗时很长

getDevicePushTokenAsyncgetExpoPushTokenAsync 在 iOS 上有时可能需要很长时间才能完成。这不在 expo-notifications 的控制范围内,正如 Apple 的 Troubleshooting Push Notifications 技术说明中所述:

这不一定代表错误状态。系统可能根本没有互联网连接,因为它超出了任何基站或 Wi‑Fi 接入点的范围,或者处于飞行模式。应用不应将其视为错误,而应继续正常运行,只禁用依赖推送通知的功能。

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

阅读 Apple 关于排查推送通知问题的技术说明

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

稍后再试一次
  • 设备附近的 APNS 服务器可能宕机了,如此论坛帖子所示。出去走走,稍后再试!
  • 按照此 GitHub 评论 的建议,几天后再试。
在设备上关闭网络共享

你可能需要关闭网络共享,因为按此 Stack Overflow 回答所述,这可能会影响注册。

重启你的设备

如果你刚刚更改了应用应注册到的 APNS 服务器(例如,在同一设备上用 TestFlight 构建覆盖了 Xcode 构建),按此 Stack Overflow 回答所述,你可能需要重启设备。

使用 SIM 卡设置你的设备

如果出现此问题的设备尚未使用 SIM 卡完成设置,根据此 Stack Overflow 回答 的说法,配置它可能有助于缓解此 bug。

其他

直接通过 FCM 和 APNs 发送通知

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

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

这表明你提供的图片资源存在问题。图片应当为纯白色,并带有透明背景(这是 Google 的要求,并由其强制执行,不是 Expo 的要求)。有关更多信息,请参阅 这篇文章