Why might a React Native app get no usable push token in Expo Go, an iOS Simulator or an Android emulator?
answer
- Expo Go dropped remote push in SDK 53
- development build instead
- emulator image needs Google Play
- RN Firebase v26 skips APNs on ARM64 Simulator
- sandbox versus production APNs tokens
basics
~20 sExpo Go has no remote push since SDK 53, Android emulators need a Google Play image for FCM, and React Native Firebase v26 skips APNs registration on Apple-silicon Simulators. Test on a development build, ideally on a physical device.
solid answer
~40 sEach environment breaks token fetching differently. **Expo Go** lost remote push in SDK 53: on Android `getDevicePushTokenAsync` and `getExpoPushTokenAsync` throw, on iOS you get a warning, so push needs a **development build**. An **Android emulator** can only get an FCM token with a Google Play services system image. On **iOS Simulator**, Expo's docs support push on Xcode 14+ (macOS 13+, iOS 16+), but **React Native Firebase v26** deliberately does not call APNs registration on the ARM64 Simulator: `registerDeviceForRemoteMessages` rejects with `messaging/registration-timeout` after about 10 seconds and no real APNs token exists, so use a physical device. Also remember that development builds register with the **sandbox** APNs environment, so their tokens will not work with a production sender.
go deeper
Recall that remote push needs a development build, not Expo Go, and that emulators and simulators have limits.
Explain why Expo Go cannot receive your pushes, the Google Play emulator requirement, and the sandbox versus production APNs split.
Handle React Native Firebase v26's registration rejections, and set a test matrix of development builds on real devices plus a production-signed build before release.
Budget device and build coverage for push testing so release confidence does not rest on simulators or a single platform.
## Why the environment matters A push token is issued by the platform's provider to a **specific app binary with specific credentials**. Anything that changes the binary, the credentials or the platform services changes whether a token can be issued and whether it works. Four environments cause most "no token" or "token doesn't work" reports during development. | Environment | What happens | What to do | |---|---|---| | **Expo Go** (SDK 53+) | remote push removed; token calls throw on Android and warn on iOS | use a development build | | **Android emulator** | FCM needs Google Play services on the image | use an image with Google Play | | **iOS Simulator + expo-notifications** | supported on Xcode 14+ with macOS 13+ and iOS 16+ | fine for smoke tests; confirm on a device | | **ARM64 iOS Simulator + React Native Firebase v26** | APNs registration skipped by design; no real APNs token | test on a physical iPhone | ## Expo Go Expo Go is a prebuilt app with Expo's own bundle identifier. Up to SDK 52 it used Expo's own push credentials; from SDK 53 remote push was removed from Expo Go, because real push needs your app's own bundle ID, entitlement and credentials. In `expo-notifications`, the token functions and `addPushTokenListener` check whether they run in Expo Go: on Android they throw an error telling you to use a development build; on iOS they log a development warning, and remote push is still not supported there. Local notifications still work in Expo Go. The fix is a **development build** (`expo-dev-client`), which is your own binary with your bundle ID, your push entitlement and your Firebase config, built with EAS Build or locally. ## Android emulators On Android the token is an FCM token, delivered through Google Play services. An emulator image without Google Play has no way to obtain one. Use an image that includes Google Play, and make sure the app has its `google-services.json` (in Expo, `android.googleServicesFile`). ## iOS Simulator Two sources describe the Simulator differently, and both are right for their library: - **expo-notifications**: Expo's setup guide lists an iOS Simulator on Xcode 14 or later, running on macOS 13+ with iOS 16+, as a valid place to test push. - **React Native Firebase v26**: on the **ARM64 (Apple-silicon) iOS Simulator** the library no longer calls UIKit's remote-notification registration, because it could block the main thread. As a result: 1. `registerDeviceForRemoteMessages(getMessaging())` stays pending until a roughly 10-second timer rejects it with `messaging/registration-timeout`; 2. a second overlapping call rejects the first with `messaging/registration-superseded`; 3. `requestPermission` still resolves with an authorization status; 4. there is no real APNs token, so FCM cannot deliver to that Simulator. Code written for older versions that assumed registration always resolves must now handle these rejections. ## The APNs environment trap on real devices iOS has two APNs environments. A development-signed build registers with the **sandbox**; an App Store or TestFlight build registers with **production**. Expo's docs note the entitlement is set to `development` and Xcode switches it to `production` when archiving a release. Consequences: - a token from a development build does not work when your server sends to the production APNs endpoint, and vice versa; - `getExpoPushTokenAsync` detects the environment and tells Expo's service whether the build is a development one, which is why the same code works in both; - after moving a device from an Xcode build to a TestFlight build, Expo's FAQ suggests a device restart may be needed before registration settles. ## Reading the symptoms | Symptom | Likely environment cause | |---|---| | Error mentioning a development build | running in Expo Go | | Android token call fails on an emulator | image without Google Play services | | `messaging/registration-timeout` on a Simulator | React Native Firebase v26 on ARM64 Simulator, expected | | Token obtained, but sends fail only in production | sandbox token sent to production APNs, or the reverse | ## A testing plan that avoids all of this 1. Build a **development build** of the app with real push credentials. 2. Run it on a **physical iPhone** and a **Google Play emulator or physical Android phone**. 3. Log the token at startup and send a test push to it from your backend or Expo's push tool. 4. Before release, repeat on a **TestFlight or internal-track build**, which uses production APNs. Use the Simulator and Expo Go for UI and local-notification work, not as evidence that remote push works.
- Do local notifications work in Expo Go even though remote push does not?Yes. Scheduling and presenting local notifications with `expo-notifications` does not need a push token or the app's own push credentials, so it works in Expo Go. Only remote push, which depends on a token issued to your own binary, requires a development build.
- Your React Native Firebase app's registerDeviceForRemoteMessages rejects with messaging/registration-timeout on a physical iPhone; what could cause it?On a device, the timeout means iOS never reported a registration success or failure within about 10 seconds. The library's docs name a blocked main thread or missing notification permission as possibilities; also check that the build carries the push capability. It is expected on the ARM64 Simulator, but on a device it is a real bug to investigate.
saying these in an interview costs you the question
- Expo Go supports remote push if you use getExpoPushTokenAsync
- Any Android emulator image can obtain an FCM token
- React Native Firebase always returns an APNs token on the Simulator
- A development build's APNs token works with the production endpoint
- registerDeviceForRemoteMessages always resolves eventually