In a bare React Native app using React Native Firebase v26 messaging, why might Android 13 users never see a notification prompt, and how do you fix it?
answer
- the method is iOS-only
- resolves AUTHORIZED on Android
- deprecated since v25
- manifest declares no POST_NOTIFICATIONS
- PermissionsAndroid, gated on API 33
basics
~10 sReact Native Firebase's messaging requestPermission() is iOS-only: on Android it resolves AUTHORIZED without asking, and it is deprecated. Declare POST_NOTIFICATIONS in the app manifest and request it with PermissionsAndroid, or use expo-notifications.
solid answer
~30 sIn `@react-native-firebase/messaging` v26, `requestPermission()` returns `AuthorizationStatus.AUTHORIZED` immediately when running on Android, without touching the OS, so code that relies on it believes everything is fine while Android 13+ devices never grant `POST_NOTIFICATIONS`. The module's own manifest does not declare that permission either. The permission APIs (`requestPermission`, `hasPermission`, `AuthorizationStatus`) have been deprecated since v25 in favour of react-native-permissions or expo-notifications. The fix in a bare app: add `<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>` to the app's `AndroidManifest.xml`, then call `PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS)` when `Platform.Version >= 33`, at an in-context moment, and handle `'never_ask_again'`. Alternatively adopt expo-notifications, whose manifest already declares the permission and whose `requestPermissionsAsync` covers both platforms.
code
xml · 4 lines<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- application element unchanged -->
</manifest>go deeper
Remember that Android 13 needs the POST_NOTIFICATIONS permission declared in the manifest and requested at runtime, and that React Native Firebase's requestPermission does not do it.
Explain why the deprecated React Native Firebase method returns AUTHORIZED on Android, and write the PermissionsAndroid request gated on Platform.Version >= 33 with its three results.
Diagnose the silent failure from its signature (tokens fine, sends succeed, nothing shown, no dialog ever seen) and fix both the manifest and the request, then add an Android 13 fresh-install check to release testing.
Decide who owns notification consent across libraries, and plan the move off React Native Firebase's deprecated permission APIs before a future major release removes them.
## The symptom A bare React Native app uses React Native Firebase for push. The team tested on iOS and on an older Android phone and everything worked. After release, Android 13+ users report that reminders never arrive, and nobody ever saw a permission dialog. Tokens register, the server reports successful sends, and there is no error in the JavaScript logs. ## Why it happens Three facts combine: 1. **`requestPermission()` is iOS-only.** In `@react-native-firebase/messaging` v26 the method begins with an Android check and returns `AuthorizationStatus.AUTHORIZED` straight away. Its documentation calls it a no-op on Android. Code such as `const status = await requestPermission(getMessaging()); if (status) registerToken();` therefore passes on every Android device. 2. **The permission is never declared.** The messaging module's Android manifest declares `INTERNET`, `WAKE_LOCK` and `ACCESS_NETWORK_STATE`, not `POST_NOTIFICATIONS`. Android refuses a runtime permission that no manifest in the build declares, without showing a dialog. 3. **Android 13 needs it.** From API 33 the system will not display the app's regular notifications until `POST_NOTIFICATIONS` is granted, and React Native 0.87 targets API 36. On Android 12 and below none of this mattered, because notifications were enabled at install, which is why testing on an old device hides the bug. Put together, the failure has a recognisable signature: - the permission code logs a success status on Android; - no user on Android 13+ remembers seeing a dialog; - `PermissionsAndroid.check(...)` for `POST_NOTIFICATIONS` resolves `false` on those devices; - the same build behaves correctly on iOS and on older Android versions. When all four hold, the cause is the permission flow, not the push pipeline, and time spent inspecting server logs or FCM payloads is wasted. ## The deprecation React Native Firebase v25 deprecated the messaging permission APIs: | API | Status in v26 | Suggested replacement | |---|---|---| | `requestPermission()` | Deprecated, no-op on Android | react-native-permissions or expo-notifications | | `hasPermission()` | Deprecated | the same | | `AuthorizationStatus` | Deprecated | the same | Its Android usage guide says that for API level 33+ the permission must be requested manually with core `PermissionsAndroid` or one of those libraries. ## Fix 1: core PermissionsAndroid 1. Declare the permission in `android/app/src/main/AndroidManifest.xml`. 2. Request it only on Android 13+, where it exists: `Platform.OS === 'android' && Platform.Version >= 33`. On Android `Platform.Version` is the API level as a number. 3. Ask in context, for example when the user turns on a habit reminder, not at startup. 4. Handle the three results of `PermissionsAndroid.request`: `'granted'`, `'denied'` (the system may ask again later) and `'never_ask_again'` (only Settings can help now). 5. Keep the iOS request on a supported path; the deprecated method still works there for now but is scheduled for removal. Below Android 13 there is nothing to request, so the gate avoids a meaningless non-granted result on devices where notifications are already on. ## Fix 2: expo-notifications for permission only A bare app can also install expo-notifications (with the Expo modules it needs) and use `requestPermissionsAsync()` for the permission while keeping React Native Firebase for FCM messaging. expo-notifications declares `POST_NOTIFICATIONS` in its own library manifest and handles the API-level check itself, and its `ios` options cover the iOS side in the same call. ## Handling iOS after the deprecation The deprecated method still requests iOS authorization in v26, so the iOS half keeps working for now. Planning the move off it avoids a second silent failure when a future major release removes it: - keep one `requestNotificationPermission()` function in the app that hides which library is used on each platform; - route iOS through expo-notifications' `requestPermissionsAsync({ ios: {...} })` or react-native-permissions when you migrate; - keep message handling, tokens and topics in React Native Firebase, which the deprecation does not touch. ## How to catch it earlier - Test permission flows on an Android 13+ device or emulator with a fresh install. - Treat an Android `AUTHORIZED` result that appeared without any dialog as a warning sign. - Verify with `PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS)`, which reads the real OS state. ## Common mistakes - Trusting the deprecated method's Android result as proof of permission. - Adding the runtime request without the manifest line, so the request is refused silently. - Requesting on every Android version instead of gating on API 33.
- Why does testing on an Android 12 phone not reveal this bug?On Android 12 and below notifications are enabled at install and there is no `POST_NOTIFICATIONS` permission to request, so the missing request and missing manifest line change nothing. The bug only exists on Android 13+, where the system withholds notification display until the permission is granted.
- Can the app keep React Native Firebase for FCM and still use expo-notifications for the permission?Yes. React Native Firebase's own documentation points to expo-notifications as a replacement for its permission APIs. The app can call `requestPermissionsAsync()` from expo-notifications for consent, whose library manifest declares `POST_NOTIFICATIONS`, while keeping React Native Firebase messaging for tokens and message handling.
saying these in an interview costs you the question
- React Native Firebase's requestPermission() shows the Android 13 dialog
- An AUTHORIZED result on Android proves the user granted notifications
- The messaging module declares POST_NOTIFICATIONS, so the app manifest needs nothing
- The runtime request alone is enough without a manifest declaration
- Request POST_NOTIFICATIONS on every Android version to be safe