EasyStarter logoEasyStarter

推送通知

在EasyStarter App端完成推送功能配置

推送通知

EasyStarter 默认关闭 App 通知。原因是 iOS 和 Android 都需要先配置各自的推送凭证,未配置时直接开启会导致真机打包或签名失败。

通知功能最好使用真机测试。模拟器很容易收不到推送通知,即使配置正确,也可能无法正常完成测试。

1. 开启通知

打开 packages/app-config/src/app-config.ts,找到 notifications,把 enabled 改为 true

packages/app-config/src/app-config.ts
notifications: {
  enabled: true,
  provider: "expo",
},

保存后,从项目根目录执行:

pnpm -F native prebuild

这个命令会在现有 iOS 和 Android 工程中同步最新配置,并把通知所需的原生配置写进去。

2. 配置 iOS APNs(iOS App 需要设置这个)

推荐同时参考 Expo 官方文档:

在 Apple Developer 开启推送

  1. 打开 Apple Developer Identifiers
  2. 找到与你的 ios.bundleIdentifier 一致的 App ID
  3. 进入 App ID
  4. 勾选 Push Notifications
  5. 点击 Save

模板默认 Bundle ID 是 native.easystarter.dev。如果你已经改成自己的 Bundle ID,请选择自己的 App ID。

配置 APNs Key

先在 Apple Developer 创建 APNs Key:

  1. 打开 Apple Developer Keys
  2. 点击 + 创建新的 Key
  3. 填写 Key 名称,并勾选 Apple Push Notifications service (APNs)
  4. 点击 Continue → Register
  5. 下载 .p8 文件,并保存页面显示的 Key ID
  6. 获取 Apple Team ID:登录 Apple Developer Account,打开 Membership details,复制页面中的 Team ID(由 Apple 分配的 10 位字符串)

.p8 文件只能在 Apple Developer 创建时下载一次,请妥善保存,不要提交到 Git。

方法一:使用 EAS CLI

进入 Native 目录并运行:

cd apps/native
pnpm dlx eas-cli credentials

运行后按下面操作:

  1. 选择 iOS
  2. 选择要使用的构建环境,例如 development
  3. 如果提示登录 Apple Developer,请登录并选择正确的 Team
  4. 选择 Push Notifications: Manage your Apple Push Notifications Key
  5. 选择 Set up your project to use Push Notifications
  6. 如果提示使用已有的 Push Key,请选择 [Add a new push key]
  7. 当出现 Generate a new Apple Push Notifications service key? 时选择 No
  8. Path to P8 file 中填写刚才下载的 .p8 文件路径
  9. 填写凭证信息:

完成后,EAS CLI 会将这个 Push Key 配置到当前项目。

方法二:通过 Expo 网页配置

  1. 登录 Expo Dashboard
  2. 进入 Credentials → Android & iOS credentials → Apple Push Keys
  3. 上传 .p8 文件

完成配置后重新构建 iOS App

无论使用方法一还是方法二,配置完成后都需要重新构建 App。将 iPhone 连接到电脑并在手机上选择信任此电脑,然后在项目根目录运行:

pnpm -F native dev:ios-device

按照提示选择你的 iPhone。命令执行完成后,新构建的 App 会自动安装到手机上。

iOS Provisioning Profile 缺少推送权限

如果构建时提示 Provisioning Profile 缺少 Push Notifications 或 aps-environment,按下面操作:

  1. 找到 apps/native/ios/EasyStarterNative.xcworkspace,使用 Xcode 打开该文件
  2. 在 Xcode 选择 EasyStarterNative Target
  3. 打开 Signing & Capabilities
  4. 开启 Automatically manage signing
  5. 确认 Team 正确。模板默认 Team 是 8622M955TV,使用自己的 Apple 账号时请改成自己的 Team

完成后,等待 Xcode 自动刷新 Provisioning Profile。

3. 配置 Android FCM V1(安卓 App 需要设置这个)

完整操作请参考 Expo 官方文档:FCM V1 Credentials

创建 Firebase Android App

  1. 打开 Firebase Console

  2. 创建或选择一个 Firebase 项目

  3. 添加 Android App

  4. Package Name 填写 apps/native/app.config.ts 中的 android.package

  5. 下载 google-services.json

  6. 将文件放到:

    apps/native/google-services.json
  7. apps/native/app.config.tsandroid 配置中添加:

    apps/native/app.config.ts
    android: {
      googleServicesFile: "./google-services.json",
    },

创建 FCM V1 凭证

  1. 在 Firebase 打开 Project settings → Service accounts

  2. 点击 Generate new private key

  3. 下载 Service Account JSON 文件

  4. 进入 apps/native 并运行:

    pnpm dlx eas-cli credentials
  5. 依次选择:

    • Android
    • production
    • Google Service Account
    • Manage your Google Service Account Key for Push Notifications (FCM V1)
    • Upload a new service account key
  6. 上传刚才下载的 Service Account JSON

Service Account JSON 包含私钥,不要提交到 Git。

重新生成并构建 Android App

回到项目根目录执行:

pnpm -F native prebuild
pnpm -F native dev:android-device

安装新构建的 App 后再测试通知。

4. 配置 Expo Access Token

EasyStarter 发送通知时需要 Expo Access Token。

  1. 登录 Expo Dashboard

  2. 进入 Credentials → Access tokens → Personal access tokens

  3. 点击 Create token

  4. 填写 Token Name,例如 easystarter-push-production,创建后复制 Access Token

  5. 写入本地 Server 环境变量:

    apps/server/.dev.vars
    EXPO_ACCESS_TOKEN=your-expo-access-token
  6. 写入生产 Server 环境变量:

    apps/server/.env.production
    EXPO_ACCESS_TOKEN=your-expo-access-token
  7. 部署生产环境前上传 Secret:

    pnpm -F server secrets:bulk:production

不要把 Access Token 写到 EXPO_PUBLIC_* 变量或 App 代码中。

如果还没有执行最新数据库迁移,运行:

pnpm db:migrate:local
pnpm db:migrate

5. 在 App 中测试通知

真机无法通过 localhost 访问电脑上的 Server,因此真机测试必须使用 ngrok。如果已经配置并正在运行 ngrok,可以跳过下面的 ngrok 配置步骤。

先启动 ngrok:

ngrok http 3001

复制 ngrok 显示的 HTTPS 地址,例如 https://abc123.ngrok-free.app,并修改以下两个文件:

apps/server/.dev.vars
SERVER_URL=https://abc123.ngrok-free.app
apps/native/.env.development.local
EXPO_PUBLIC_SERVER_API_URL=https://abc123.ngrok-free.app

两个地址必须保持一致。免费 ngrok 地址发生变化后,也需要同时更新这两个文件。

保持 ngrok 运行,然后在项目根目录启动 Server:

pnpm -F server dev

再打开一个终端,在项目根目录运行 iOS 真机 App:

pnpm -F native dev:ios-device

或运行 Android 真机 App:

pnpm -F native dev:android-device

然后在 App 中:

  1. 登录账号
  2. 打开 设置 → 通知
  3. 点击 开启系统通知
  4. 允许系统通知权限
  5. 点击 发送测试通知

测试按钮只会向当前安装的 App 发送一条测试消息。

App 在前台时会显示 App 内提示;要测试系统通知栏,请先把 App 切到后台再发送。

请使用重新构建的 Development Build 或 Release Build 测试,不要使用 Expo Go。

6. 使用 Expo 网站测试

也可以打开 Expo Push Notifications Tool 发送测试通知。

Recipent

填写当前设备的 Expo Push Token,格式类似:

ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]

获取方式:

  1. 先在 App 中登录并允许通知
  2. 本地环境运行 pnpm db:studio:local,生产环境运行 pnpm db:studio
  3. 打开 notification_subscription
  4. 找到 providerexpo 的当前设备记录
  5. 复制 provider_subscription_id

Access Token

填写前面创建的 Expo Access Token,也就是 EXPO_ACCESS_TOKEN 的值。

Data (JSON string)

可以填写:

{"kind":"self_test","destination":{"type":"notification_settings"}}

点击通知后会打开 App 的通知设置页。

如果只想测试通知是否能显示,也可以留空。填写时必须使用合法 JSON,字段和文本都要使用双引号。

其他常用字段:

字段填写内容
Message title测试通知标题
Message body测试通知内容
Channel IDAndroid 填 default
Sound namedefault

使用其他推送服务商

EasyStarter 的通知发送层基于 NotificationProvider 接口设计,可以扩展 OneSignal、Braze、Customer.io、CleverTap 等其他推送服务商。下面以 OneSignal 为例。

第一步:扩展服务商类型

打开 packages/app-config/src/types.ts,将新服务商追加到 SUPPORTED_NOTIFICATION_PROVIDERS

packages/app-config/src/types.ts
export const SUPPORTED_NOTIFICATION_PROVIDERS = ["expo", "onesignal"] as const;

第二步:接入 App 端 SDK

按照服务商提供的 Expo 或 React Native 文档安装 SDK 和 Expo Plugin,并完成 iOS APNs、Android FCM 配置。

然后修改 apps/native/hooks/use-notification-subscription-sync.ts,将 Expo Push Token 替换为新服务商返回的设备推送标识,并将其注册到 Server。

不同服务商的设备推送标识不能混用。切换服务商后,用户需要打开新版本 App,让设备重新注册。

第三步:实现 Provider

apps/server/src/notifications/providers/ 下新建服务商文件,并实现 NotificationProvider 接口:

apps/server/src/notifications/providers/onesignal.ts

Provider 需要负责:

  • 使用服务商 API 批量发送通知
  • 将发送结果转换为成功或失败状态
  • 查询并返回通知送达结果
  • 设置服务商允许的单次发送和查询数量

可以参考现有的 apps/server/src/notifications/providers/expo.ts

第四步:注册服务商

打开 apps/server/src/notifications/provider.ts,导入新 Provider,并在 switch 中添加对应分支:

apps/server/src/notifications/provider.ts
import { createOneSignalNotificationProvider } from "./providers/onesignal";

// Add this branch to the existing switch.
case "onesignal":
  return createOneSignalNotificationProvider({
    appId: env.ONESIGNAL_APP_ID,
    apiKey: env.ONESIGNAL_API_KEY,
  });

同时将服务商需要的密钥写入 Server 环境变量。

第五步:切换配置

打开 packages/app-config/src/app-config.ts,将 notifications.provider 改为新服务商:

packages/app-config/src/app-config.ts
notifications: {
  enabled: true,
  provider: "onesignal",
},

然后在项目根目录执行:

pnpm -F native prebuild
pnpm -F native dev:ios-device

Android 真机使用:

pnpm -F native dev:android-device

接入前可以先参考 Expo 的 Push Notification Services Guide 和对应服务商的官方接入文档。

常见问题