This episode covers push notifications: FCM for Android and APNs for iOS, the permission flow, notification handlers for foreground and background, then background tasks with react-native-background-fetch and a battery-efficient strategy.

Notifications are one of the ways an app returns to the user's screen without them opening it. But building push notifications properly isn't just installing a library: there are two different ecosystems, a permission flow, and handlers for three app states.
Episode 11 covers push notifications thoroughly: Firebase Cloud Messaging for Android and APNs for iOS, the permission flow with notifee, notification handlers in foreground, background, and app quit, then background tasks with react-native-background-fetch and a battery-efficient strategy.
Each platform has its own push service: FCM (Firebase Cloud Messaging) for Android and APNs (Apple Push Notification service) for iOS. Push messages are sent from the server to these services, then forwarded to the device. To simplify with one API, use notifee, which wraps both:
npm install @notifee/react-nativeWhen the app first runs, the platform issues a device token — the device's identity in the push service. This token is sent to your server so the server knows where to send notifications. Tokens can change, so always update the server when the app detects a new token.
iOS requires explicit permission before showing notifications. Android 13+ also requests runtime permission. The flow: check the status, request permission when the user performs a relevant action, then explain why notifications are needed.
import notifee from "@notifee/react-native";
async function mintaIzin() {
const settings = await notifee.requestPermission();
return settings.authorizationStatus >= 1;
}Call notifee.requestPermission() when the user chooses a sensible action — for example tapping a "Enable reminders" button — not right when the app opens. The authorizationStatus result determines whether notifications are authorized, denied, or still provisional.
Notifications need to be handled differently depending on the app state:
import notifee, { EventType } from "@notifee/react-native";
notifee.onForegroundEvent(({ type, detail }) => {
if (type === EventType.PRESS) {
bukaLayarNotifikasi(detail.notification.data);
}
});detail.notification.data carries the payload sent by the server — use it to navigate to the right screen. This data is also available in the background event for when the app is in the background.
Android uses channels to group notifications. Create a channel during initialization so notifications work on modern Android versions:
import notifee from "@notifee/react-native";
async function buatChannel() {
await notifee.createChannel({
id: "default",
name: "Notifikasi Umum",
});
}Not all work can wait for the user to open the app. react-native-background-fetch lets the app run short tasks in the background on a system-defined schedule:
npm install react-native-background-fetchimport BackgroundFetch from "react-native-background-fetch";
async function initBackground() {
await BackgroundFetch.configure(
{
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
},
async (taskId) => {
await sinkronData();
BackgroundFetch.finish(taskId);
}
);
}The operating system decides when a task runs — minimumFetchInterval is only a lower bound, not a guarantee. Never forget to call BackgroundFetch.finish(taskId), or the OS will consider the task hung.
With enableHeadless: true, the task still runs even if the user terminated the app. Headless tasks use a separate entry point so JavaScript can be executed without a UI. Make sure headless tasks are short and don't touch UI state.
Background tasks and notifications are serious battery consumers. A few important principles:
Warning
Overusing background tasks gets the app blocked by the system or uninstalled by users. iOS gives a very limited time window for background fetch; design your sync as if it only happens a few times a day.
Episode 11 brought the app to life outside the screen: push notifications with FCM and APNs via notifee, the correct permission flow, handlers for foreground, background, and quit, plus battery-efficient background fetch.
Key takeaways:
BackgroundFetch.finish must be called at the end of a task.minimumFetchInterval is only a lower bound.In the next episode, episode 12, we'll discuss media, camera, and permissions: react-native-vision-camera, image picker, image resize and compression, permission management with react-native-permissions, and UX when permission is denied.