Push notifikacije u React Native aplikacijama u 2026. najjednostavnije se postavljaju kombinacijom paketa expo-notifications, Firebase Cloud Messaging HTTP v1 API-ja za Android i APNs autentikacijskog ključa za iOS, jer je legacy FCM API službeno isključen u lipnju 2024. godine. Ovaj vodič vodi vas kroz cijeli tok: od konfiguracije projekta i traženja dopuštenja, preko slanja poruka putem Expo Push servisa ili izravno preko FCM/APNs-a, sve do rukovanja pozadinskim porukama i debugiranja na fizičkim uređajima.
Paket expo-notifications u SDK-u 54 podržava nove Android kanale, iOS Live Activities i Bridgeless način rada.
Legacy FCM API (server key) ne radi više od 22. lipnja 2024.; obavezno koristite FCM HTTP v1 s OAuth2 servisnim računom.
Apple zahtijeva APNs .p8 autentikacijski ključ (Token-based) umjesto starih .p12 certifikata za nove postavke.
Expo Push servis je besplatan proxy koji šalje jedan zahtjev za sve uređaje i sam upravlja FCM-om i APNs-om.
Push notifikacije rade samo na fizičkim uređajima, jer iOS simulator i većina Android emulatora ih ne podržavaju.
Za pozadinske podatke koristite data-only poruke i TaskManager.defineTask, a ne običan notification payload.
Zašto Expo Notifications u 2026.
Paket expo-notifications u verziji 0.31+ (Expo SDK 54) postao je de facto standard za React Native push notifikacije zato što apstrahira tri različita transporta (FCM HTTP v1 za Android, APNs za iOS i lokalne UNUserNotificationCenter / NotificationCompat pozive) iza jedinstvenog JavaScript API-ja. Druga prednost je Expo Push servis, besplatni proxy koji prima jedan POST zahtjev s nizom Expo Push Tokena i sam ga prosljeđuje pravim platformama. Time se eliminira potreba za servisnim računima i autentikacijskim ključevima u vlastitom backendu tijekom prototipiranja.
Treća stvar koja je tijekom 2024. i 2025. bitno promijenila stvari su tri velike migracije s kojima se svaka produkcijska aplikacija mora suočiti:
Gašenje legacy FCM API-ja. Google je 22. lipnja 2024. ugasio send endpoint koji je koristio statički server ključ. Bilo koji backend koji još uvijek šalje zahtjev na fcm.googleapis.com/fcm/send dobit će 404.
Nova arhitektura React Nativea. Bridgeless mod, koji se uključuje prema zadanim postavkama u React Native 0.79, mijenja način na koji se notifikacijski handleri registriraju (više u članku o novoj arhitekturi React Nativea).
Android 14+ obavezno dopuštenje.POST_NOTIFICATIONS runtime dozvola više nije opcionalna na Androidu 13 i novijim, a Play Store odbija aplikacije koje ju ne traže ispravno.
Sve to zajedno znači da je pristup kroz Expo i SDK 54 najsigurniji način ostati kompatibilan s objema platformama bez pisanja native koda.
Instalacija i osnovna konfiguracija
Krenite od čistog Expo projekta ili dodajte paket u postojeću aplikaciju koja koristi Expo SDK 53 ili noviji. Komanda automatski instalira odgovarajuću verziju za vašu SDK granu:
Paket expo-device potreban je da bismo provjerili je li korisnik na fizičkom uređaju (push tokene nemoguće je dobiti na iOS simulatoru i većini Android emulatora), dok expo-constants služi za čitanje projectId potrebnog kod traženja Expo Push Tokena.
Nakon instalacije otvorite app.json (ili app.config.ts) i dodajte plugin u sekciju plugins. Ova konfiguracija postavlja prilagođenu ikonu, boju te traži POST_NOTIFICATIONS dozvolu:
Ikona mora biti monokromatski PNG od 96×96 piksela s prozirnom pozadinom, inače će se na Androidu prikazati kao bijeli kvadrat. Iskreno, na ovaj sam se kamen sapleo barem dva puta u prošlim projektima, pa imajte to na umu. Nakon promjene app.json obavezno pokrenite npx expo prebuild --clean ako koristite bare workflow ili EAS Build, da bi se promjene primijenile u AndroidManifest.xml i Info.plist.
Traženje dozvola i dohvaćanje tokena
Najčešća greška koju vidim na produkciji je preuranjeno pozivanje requestPermissionsAsync u App.tsx, čime aplikacija odmah pri prvom otvaranju pita za notifikacije prije nego što je korisnik shvatio što aplikacija uopće radi. iOS dopušta samo jedan dijalog za traženje notifikacijske dozvole; ako ga korisnik odbije, dozvolu može uključiti isključivo iz Postavki.
Bolja je praksa traženje dozvole vezati uz konkretnu akciju (npr. nakon onboardinga ili prijave). Sljedeći helper pokriva cijeli tok: provjeru uređaja, dozvola i registraciju Expo Push Tokena.
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';
import Constants from 'expo-constants';
import { Platform } from 'react-native';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowBanner: true,
shouldShowList: true,
shouldPlaySound: true,
shouldSetBadge: true,
}),
});
export async function registerForPushNotificationsAsync(): Promise<string | null> {
if (!Device.isDevice) {
console.warn('Push notifikacije zahtijevaju fizički uređaj.');
return null;
}
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync('default', {
name: 'Općenito',
importance: Notifications.AndroidImportance.DEFAULT,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#1f6feb',
});
}
const { status: existing } = await Notifications.getPermissionsAsync();
let finalStatus = existing;
if (existing !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') return null;
const projectId =
Constants.expoConfig?.extra?.eas?.projectId ??
Constants.easConfig?.projectId;
const tokenResponse = await Notifications.getExpoPushTokenAsync({ projectId });
return tokenResponse.data; // ExponentPushToken[xxxxxxxx]
}
Vraćeni string počinje s ExponentPushToken[ i šaljete ga svom backendu da ga poveže s korisničkim računom. Ako trebate native FCM ili APNs token (recimo, koristite OneSignal ili Braze umjesto Expo Push servisa), pozovite Notifications.getDevicePushTokenAsync() umjesto Expo verzije.
Postavljanje Androida s FCM HTTP v1 API-jem
Od 22. lipnja 2024. legacy FCM API koji je koristio statički Server Key potpuno je isključen, kao što je Google detaljno opisao u migracijskoj dokumentaciji. Sva slanja sada idu kroz FCM HTTP v1 API koji se autentificira OAuth 2.0 access tokenom dobivenim iz Google servisnog računa.
Postavljanje za Expo aplikacije ide ovako:
Otvorite Firebase konzolu i kreirajte projekt (ili iskoristite postojeći).
Dodajte Android aplikaciju s točno istim package imenom kao u app.json > android.package.
Preuzmite google-services.json i spremite ga u root projekta. Putanja se referencira iz app.json > android.googleServicesFile.
U Firebase konzoli idite na Project Settings → Service accounts → Generate new private key i preuzmite JSON datoteku.
U Expo dashboardu pod Credentials → Android → Push notifications (FCM V1) uploadajte taj JSON ključ.
Nakon ovih koraka Expo Push servis automatski izmjenjuje vaše Expo Push Tokene za native FCM tokene i koristi novi v1 endpoint. Ako šaljete izravno bez Expoa, autentificirate se ovako u Node.js backendu:
Postavljanje iOS-a s APNs autentikacijskim ključem
Apple već nekoliko godina preporučuje Token-based autentikaciju umjesto starih .p12 certifikata, jer jedan .p8 ključ vrijedi za sve vaše aplikacije i ne istječe automatski. Detalji se nalaze u službenoj Apple dokumentaciji o token-based vezi prema APNs-u.
Praktični tijek:
U Apple Developer Portalu otvorite Certificates, Identifiers & Profiles → Keys → +.
Označite Apple Push Notifications service (APNs), dajte ime, generirajte i preuzmite .p8 datoteku (može se preuzeti samo jednom).
Zabilježite Key ID (10 znakova) i Team ID (vidljiv u zaglavlju portala).
U Expo dashboardu pod Credentials → iOS → Push key uploadajte .p8 datoteku zajedno s Key ID i Team ID podacima.
Provjerite da je u Identifiers → vaš App ID → Capabilities uključen Push Notifications.
Ako koristite EAS Build, povezivanje je automatsko. Komanda eas credentials interaktivno pita za sve ove podatke i sprema ih u Expo profil. Za upravljanje cijelim deploy procesom pogledajte vodič o EAS Build i Submit procesu u kojem je APNs konfiguracija pokrivena unutar šireg konteksta App Store objave.
Slanje notifikacija preko Expo Push servisa
Najjednostavniji način slanja ide preko Expo Push API-ja koji prihvaća do 100 poruka u jednom batch zahtjevu i besplatno proksira do FCM-a i APNs-a. Endpoint je https://exp.host/--/api/v2/push/send i ne traži autentikaciju za zahtjeve s malim brojem poruka, iako se preporučuje koristiti Access Token iz Expo Dashboarda za produkcijske aplikacije.
Iz Node.js backenda najlakše je koristiti službeni expo-server-sdk paket koji automatski grupira poruke i poštuje rate limite:
Svaki ticket sadrži id kojim možete kasnije dohvatiti receipt i provjeriti je li poruka stvarno isporučena. Receipti su dostupni 24 sata nakon slanja i tu ćete uhvatiti greške poput DeviceNotRegistered (token više nije važeći, treba ga obrisati iz baze) ili MessageRateExceeded. U jednom projektu prije par mjeseci propustio sam pratiti receipte, pa smo tjednima slali poruke na već obrisane uređaje. Ne ponavljajte tu pogrešku.
Rukovanje notifikacijama u aplikaciji
Aplikacija može primati notifikacije u tri stanja: foreground (otvorena na ekranu), background (zatvorena ili u pozadini) i prilikom tapanja na samu notifikaciju kada se otvara. Za svako stanje koristi se drugi listener. Hook ispod sve to zaokružuje u jednu Reactovsku apstrakciju:
import { useEffect, useRef } from 'react';
import * as Notifications from 'expo-notifications';
import { useRouter } from 'expo-router';
export function useNotificationObservers() {
const router = useRouter();
const receivedSub = useRef<Notifications.Subscription | null>(null);
const responseSub = useRef<Notifications.Subscription | null>(null);
useEffect(() => {
receivedSub.current = Notifications.addNotificationReceivedListener(
(notification) => {
console.log('Primljena dok je app otvorena:', notification.request.content);
}
);
responseSub.current = Notifications.addNotificationResponseReceivedListener(
(response) => {
const screen = response.notification.request.content.data?.screen;
if (typeof screen === 'string') {
router.push(screen as never);
}
}
);
return () => {
receivedSub.current?.remove();
responseSub.current?.remove();
};
}, [router]);
}
Ako koristite Expo Router za navigaciju, podatke poput screen možete proslijediti u data payloadu push notifikacije i otvoriti točan ekran. Kompletan tok zaštićenih ruta i deep linkinga objašnjen je u članku o Expo Routeru v6.
Pozadinske i data-only poruke
Ako želite osvježiti podatke u pozadini bez prikazivanja notifikacije (npr. tihi sync), šaljete data-only poruku bez notification objekta i registrirate TaskManager task koji se izvršava u pozadini. Na iOS-u dodatno morate uključiti UIBackgroundModes s remote-notification u Info.plist (već je gore u app.json) i postaviti "_contentAvailable": true u payloadu.
import * as TaskManager from 'expo-task-manager';
import * as Notifications from 'expo-notifications';
const BACKGROUND_NOTIFICATION_TASK = 'BACKGROUND-NOTIFICATION-TASK';
TaskManager.defineTask(BACKGROUND_NOTIFICATION_TASK, ({ data, error }) => {
if (error) {
console.error('Background task error', error);
return;
}
// npr. spremi podatke u MMKV ili pokreni sinkronizaciju
console.log('Pozadinska push poruka:', data);
});
Notifications.registerTaskAsync(BACKGROUND_NOTIFICATION_TASK);
Bitno je razumjeti da operativni sustavi agresivno štede bateriju. iOS može odgoditi ili odbaciti data-only poruke ako uređaj prepoznaje da ih šaljete prečesto, a Android Doze mod zaustavlja sve zadatke nakon kratkog vremena u pozadini. Za pouzdane background sinkronizacije kombinirajte push s expo-background-fetch ili Android WorkManager mehanizmima.
Zašto moje push notifikacije ne rade?
Ovo je daleko najčešće pitanje na Expo forumima i Discord serveru. Devet od deset puta uzrok je jedan od ovih problema:
Testirate na simulatoru/emulatoru. iOS simulator ne podržava push tokene, a većina Android emulatora bez Google Play Services također ne. Koristite fizički uređaj.
Token nije osvježen nakon reinstalacije. Expo Push Token se mijenja kada korisnik obriše i ponovno instalira aplikaciju. Backend mora detektirati DeviceNotRegistered i izbrisati stari token.
FCM v1 nije konfiguriran. Možda još uvijek koristite legacy server key. Provjerite da je u Expo Dashboardu uploadan JSON servisnog računa.
Pogrešan APNs environment. Šaljete production poruke za TestFlight build koji koristi sandbox APNs.
Android 14+ bez POST_NOTIFICATIONS. Niste tražili runtime dozvolu pa korisnik ima blokirane notifikacije.
Foreground bez handlera. Bez setNotificationHandler notifikacije se neće prikazati dok je aplikacija otvorena, što ostavlja dojam da uopće ne stižu.
Za sistemski debug uključite expo-notifications debug logove i koristite Reactotron ili Hermes inspektor; detaljne tehnike opisane su u članku o React Native debugiranju s DevTools i Reactotronom. Pouzdano testiranje toka notifikacija dobro se uklapa u širi tok kvalitete, što je tema vodiča o React Native testiranju s Maestrom i Detoxom. Na strani backenda Expo Push receipti su jedini autoritativni izvor istine o tome je li poruka prihvaćena od strane FCM-a/APNs-a.
Možete li slati push notifikacije bez Expo servisa?
Da. Expo Push servis je samo opcionalan proxy, a expo-notifications paket podjednako dobro radi s native tokenima dobivenim preko getDevicePushTokenAsync(). Ovo je preporučeno za aplikacije koje već koriste OneSignal, Braze, CleverTap, Customer.io ili vlastiti FCM/APNs sender, te za projekte koji zbog GDPR-a ili enterprise compliance pravila ne smiju proksirati podatke kroz treću stranu.
Tablica ispod sažima ključne razlike između tri pristupa za 2026.:
Karakteristika
Expo Push servis
Direktno FCM v1 + APNs
OneSignal / Braze
Cijena
Besplatno
Besplatno (samo cloud troškovi)
Freemium, plaća po MAU
Setup vrijeme
~15 min
2 do 4 sata
~30 min
Vlastiti backend potreban
Tanki, samo HTTP POST
OAuth2 + APNs JWT logika
Ne, dashboard
Analytika
Ticket/receipt status
Vlastita implementacija
Bogate metrike, A/B testovi
Segmentacija publike
Vlastita logika
Vlastita logika
Ugrađena u dashboard
Rate limit
600 poruka/sek
FCM: 1M/min, APNs: brže
Po planu
GDPR/data residency
Podaci prolaze kroz Expo
Pod vašom kontrolom
Ovisi o davatelju
Praktičan savjet iz vlastitog iskustva: počnite s Expo Push servisom dok validirate proizvod, a migrirajte na direktan FCM/APNs ili komercijalni servis tek kada premašite 100 000 mjesečno aktivnih korisnika ili kada compliance to zahtijeva. Migracija je jednostavna jer su tokeni i payload format kompatibilni.
Često postavljana pitanja
Koja je razlika između lokalnih i remote push notifikacija u React Native?
Lokalne notifikacije zakazuje sama aplikacija pomoću Notifications.scheduleNotificationAsync i ne zahtijevaju internet ni backend, pa su savršene za podsjetnike ili alarme. Remote notifikacije šalje vanjski server putem FCM-a ili APNs-a i mogu doći kada je aplikacija zatvorena, ali zahtijevaju token i konfiguraciju servisnog računa.
Trebam li Firebase ako koristim samo iOS aplikaciju?
Ne. APNs se autenticira izravno Apple .p8 ključem i Firebase nije potreban za iOS-only aplikacije. Tek kada dodate Android verziju trebate Firebase projekt i FCM HTTP v1 servisni račun.
Mogu li testirati push notifikacije u Expo Go aplikaciji?
Da, Expo Go u SDK 53 i 54 podržava primanje Expo Push Tokena na fizičkim uređajima i odlično služi za prototipiranje. Ograničenje je da se identifikator aplikacije ne može mijenjati, pa za testiranje vlastite brand ikone, prilagođenih kanala i dubokog povezivanja morate napraviti development build.
Kako rukovati tokenima kada se korisnik odjavi iz aplikacije?
Pri odjavi pozovite endpoint na svom backendu koji briše vezu između korisnikova ID-a i tokena, te po želji pošaljite Notifications.unregisterForNotificationsAsync(). Pri ponovnoj prijavi novi token dohvaćate kroz isti registracijski tok kao i kod prvog otvaranja aplikacije.
Koliko često Expo Push Token istječe?
Token nema fiksan datum isteka, ali postaje nevažeći kada korisnik obriše aplikaciju, promijeni uređaj ili kada vi zarotirate projectId. Backend mora obraditi DeviceNotRegistered grešku iz Expo receipta i izbrisati pripadajući token iz baze, kako se ne bi gomilali mrtvi zapisi.
Priya is a staff mobile engineer with nine years working in React Native, currently consulting for fintech and healthtech teams shipping on both stores from a single codebase. She spent four years at Klarna on the merchant-facing app, where she led the migration off a legacy Java Android codebase to React Native 0.68 and later drove the New Architecture rollout (Fabric + TurboModules) for roughly 14 million MAU.
Before Klarna she was at Coinbase on the wallet team, writing native bridges to Secure Enclave and Android Keystore. She maintains two small open-source libraries for biometric auth and contributes occasional PRs to react-native-screens. She writes here mostly about performance profiling with Flipper and Hermes, EAS Build pipelines, and the practical headaches of running a brownfield RN app inside a 12-year-old iOS host.
Naučite slojeviti pristup testiranju React Native aplikacija u 2026. Jest za unit testove, RNTL za komponente, Maestro i Detox za E2E — s praktičnim primjerima koda i GitHub Actions CI/CD integracijom.
Vodič kroz React Native alate za debugiranje u 2026. — od DevToolsa koji zamjenjuje Flipper, preko Reactotrona za inspekciju stanja i MMKV-a, do Hermes profilera za CPU analizu i nativnih alata za iOS i Android.