Probabilmente sei arrivato al punto in cui l'app funziona, gli utenti sono stati registrati e il prodotto vuole flussi di ri-engaggio che sentano nativi. Sostituzioni della cesta. Suggerimenti di revisione. Nuove notifiche di messaggio. Annunci di rilascio. La prima istintiva è spesso quella di "impostare semplicemente la push", poi una settimana dopo si è impegnati a debuggere perché un dispositivo riceve notifiche, il simulatore sembra registrarsi bene e nessuno può spiegare perché i tocchi non aprono la schermata giusta.
È lì che le notifiche push di Expo sono o piacevolmente semplici o sorprendentemente fragili.
Expo fornisce a React Native un layer pratico sopra APNs e FCM, che è esattamente il motivo per cui così tanti team lo utilizzano. Ma il gap tra una dimostrazione e un'implementazione pronta per la produzione è reale. Il ciclo di vita dei token, l'orario delle autorizzazioni, la configurazione dei listener, la progettazione dei payload e la pulizia del backend contano. Se anche stai spedito cambiamenti logici dell'app con frequenza, la necessità di disciplina operativa diventa ancora più acuta, soprattutto se il tuo lavoro di mantenimento della retention dipende da messaggi affidabili e velocità di rilascio. È lo stesso problema più ampio dietro miglioramento della retenzione degli utenti per l'app mobile: la consegna è utile solo se l'esperienza utente che la circonda è prevedibile.
Tavola dei contenuti
- La base per coinvolgere gli utenti con le notifiche di Expo
- Configurazione e impostazione del progetto iniziale
- Richiesta di autorizzazione e cattura dei token di notifica
- Invia Notifiche dal tuo Server
- Gestisci le Notifiche Inbound nel tuo App
- Pratiche e trappole comuni per la produzione
La Fondazione per coinvolgere gli utenti con le notifiche Push di Expo
Un Notifica push di Expo La configurazione è attraente per una ragione soprattutto. Elimina molta complessità di messaggistica nativa che le squadre non vogliono gestire già il primo giorno. Invece di costruire il tubo di APNs e FCM direttamente, puoi lavorare con la porta di ingresso di Expo e concentrarti sul comportamento del prodotto, la routing, l'esperienza UX delle autorizzazioni e la logica dei messaggi backend.
Quell'astrazione non rende le notifiche
The service is also fast enough that performance usually isn’t the first thing to worry about. From March 14, 2023 through June 12, 2023, Expo’s push notification API showed a Solo cambia dove si concentra il tuo sforzo di ingegneria., Il servizio è anche abbastanza veloce che il rendimento non è il primo problema da cui preoccuparsi. Dal 14 marzo 2023 al 12 giugno 2023, le notifiche push di Expo __CAPGO_KEEP_0__ hanno mostrato un tempo di risposta mediano di 42 millisecondi e una latenza p99 di 273 millisecondi, e un tasso medio di errori giornalieri del 0,17% su decine di milioni di messaggi giornalieri, secondo l'analisi di benchmark di Knock’s Expo push API. Ciò dovrebbe rassicurare qualsiasi team che si chiede se Expo sia adatto solo per prototipi.
Cosa Expo astrae effettivamente
Quando i team dicono “Expo push,” spesso intendono diversi problemi separati raccolti insieme:
- Routing del provider: Expo invia messaggi a APNs per iOS e FCM per Android.
- Formato del token: Il tuo server memorizza e invia un Token di Push Expo al posto di gestire il trattamento dei token specifici per piattaforma in primo luogo.
- Contratto di richiesta: Invi un payload tramite POST su Expo’s push API al posto di integrare direttamente gli API dei provider nativi.
È utile, ma crea anche una comune fraintesa. Le squadre a volte suppongono che Expo gestisca ogni problema di consegna. In pratica, molti fallimenti provengono dall'app code, dai token scaduti, dai payload distorti o da un flusso di autorizzazione povero.
Regola pratica: Tratta Expo come un layer di trasporto affidabile, non come un sostituto di un design client e backend solido.
Cosa significa effettivamente la prontezza di produzione
Un demo funzionante prova solo che un dispositivo ha accettato un payload una volta sola. La prontezza di produzione significa qualcos'altro:
| Preoccupazioni | Mindset di demo | Mindset di produzione |
|---|---|---|
| Autorizzazioni | Chiedi subito | Chiedi in contesto, dopo che il valore dell'utente è chiaro |
| Token | Salva una volta | Aggiorna, deduplica, scada e riconcilia |
| Payload | Metti tutto dentro data |
Mantieni i payload piccoli e orientati all'azione |
| Comportamento dell'app | Mostra un avviso | Naviga correttamente e gestisci lo stato in primo piano |
| Operazioni | Test manuali | Ricevute, pulizia, log e gestione degli incidenti |
Questa è la differenza tra "invia notifiche" e "notifiche supportano un workflow di prodotto reale."
Impostazione e configurazione del progetto iniziale
Un sacco di dolore per le push Expo inizia prima della prima richiesta di autorizzazione. Se la configurazione del progetto è disordinata, il client code può sembrare corretto mentre l'app si comporta in modo inconsistente tra le build.

Inizia con le librerie giuste installate e un ambiente di sviluppo che corrisponde al percorso di build. Se stai lavorando oltre Expo Go, è utile allineare il tuo workflow locale con una configurazione del client di sviluppo Expo personalizzata, perché il comportamento delle notifiche spesso richiede di essere validato in un build che rifletta più da vicino la produzione rispetto a una rapida esecuzione di sandbox.
Installa i pacchetti di notifica
In ogni caso, avrai bisogno almeno di:
expo-notificationsper le richieste di autorizzazione, la raccolta di token, gli ascoltatori e la presentazione delle notifiche.expo-deviceperché dovresti proteggere la raccolta di token conDevice.isDevice.
I comandi di installazione tipici dipendono dal tuo gestore di pacchetti, ma la chiave è l'allineamento della versione con il tuo Expo SDK. Non mescolare versioni di pacchetti arbitrarie. Lascia che Expo risolva le compatibili.
Aggiungi la configurazione a livello di progetto
Mantieni la tua configurazione esplicita. Un minimo app.json o app.config.js dovrebbe riflettere il fatto che le notifiche fanno parte del contratto dell'app, non un dopo pensiero.
{
"expo": {
"name": "MyApp",
"slug": "my-app",
"plugins": ["expo-notifications"],
"ios": {
"bundleIdentifier": "com.example.myapp"
},
"android": {
"package": "com.example.myapp"
},
"extra": {
"eas": {
"projectId": "your-project-id"
}
}
}
}
Alcune informazioni sono importanti qui:
- Identificatori di bundle e nomi di pacchetto Per garantire che l'applicazione corrisponda a quella effettivamente distribuita.
- Il plugin delle notifiche assicura che il progetto nativo riceva la configurazione necessaria durante la compilazione.
- L'ID del progetto EAS è importante quando il recupero del token attende che l'app sia associata al progetto Expo corretto.
Imposta un gestore delle notifiche fin da subito
Molti tutorial di base aspettano troppo a definire il comportamento delle notifiche. Non farlo. Colloca il gestore vicino all'avvio dell'applicazione per garantire un comportamento prevedibile in primo piano.
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: true,
}),
});
Le squadre decidono se le notifiche in primo piano dovrebbero visualizzare un avviso, riprodurre un suono o influenzare le badge. Il comportamento esatto dipende dal tuo prodotto. Un'app di chat e un'app di pagamento non faranno le stesse scelte.
Se non definisci intenzionalmente il comportamento in primo piano, la tua squadra finirà per debuggare le notifiche
mancanti
che sono state effettivamente ricevute ma mai presentate nel modo in cui il prodotto si aspettava.
import { Platform } from 'react-native';
import * as Notifications from 'expo-notifications';
export async function configureAndroidNotifications() {
if (Platform.OS !== 'android') return;
await Notifications.setNotificationChannelAsync('default', {
name: 'Default',
importance: Notifications.AndroidImportance.MAX,
});
}
Le notifiche di Android richiedono una configurazione del canale. Le notifiche di canale di Android non sono facoltative in pratica. Se le trascuri, le tue avvisaglie possono sembrare inconsistenti o fallire nel corrispondere alle aspettative degli utenti. Imposta questo durante l'inizializzazione dell'app. Poi mantieni stabili gli ID dei canali. Cambiarli con leggerezza rende più difficile ragionare sul comportamento delle notifiche in seguito.
Richiesta di autorizzazione e cattura di token Push
Questo è il passaggio che molti team copiano da un snippet, poi finiscono per pentirsene.
Il richiesta di autorizzazione richiede un timing, una consapevolezza della piattaforma e un trattamento asincrono disciplinato. La cattura dei token deve avvenire solo su un dispositivo fisico, solo dopo che le autorizzazioni sono state risolte, e solo se sei pronto a memorizzare il risultato sul tuo backend immediatamente.

La funzione del client che dovrebbe essere il tuo punto di partenza
Usa una funzione come questa come punto di partenza:
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';
import { Platform } from 'react-native';
type RegisterResult =
| { ok: true; token: string }
| { ok: false; reason: string };
export async function registerForExpoPushNotificationsAsync(): Promise<RegisterResult> {
if (!Device.isDevice) {
return { ok: false, reason: 'Push notifications require a physical device.' };
}
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync('default', {
name: 'Default',
importance: Notifications.AndroidImportance.MAX,
});
}
const permissions = await Notifications.getPermissionsAsync();
let finalStatus = permissions.status;
if (finalStatus !== 'granted') {
const request = await Notifications.requestPermissionsAsync();
finalStatus = request.status;
}
if (finalStatus !== 'granted') {
return { ok: false, reason: 'Notification permission was not granted.' };
}
const projectId =
Constants.expoConfig?.extra?.eas?.projectId ??
Constants.easConfig?.projectId;
if (!projectId) {
return { ok: false, reason: 'Missing EAS project ID configuration.' };
}
const tokenResponse = await Notifications.getExpoPushTokenAsync({ projectId });
return { ok: true, token: tokenResponse.data };
}
L'ordine conta. Controlli il tipo di dispositivo prima, impostare il comportamento del canale Android, risolvi le autorizzazioni, verifica la configurazione del progetto, poi richiedi il token Expo.
Perché Device.isDevice non è facoltativo
Questo è uno dei pochi errori che crea molto rumore mentre sembra innocuo. Gli esperti team richiedono l'autorizzazione condizionalmente solo quando Device.isDevice è vero, e un comune tranello è saltare quel guardiano, che porta gli sviluppatori a inviare notifiche a token di simulator non validi e a incolpare Expo quando il problema è realmente la configurazione dell'app, come descritto in Eagerworks’ implementazione delle notifiche Expo: note.
Quello è il motivo per cui il controllo si trova in cima alla funzione. Non nasconderlo dietro un aiuto. Faglielo capire.
Il risultato del simulatore è utile per il testing della UI. Non è affidabile per la validazione della registrazione del token di push.
Chiedi il permesso nel momento giusto
Non chiedere sulla schermata di avvio. Non chiedere prima che l'utente capisca il valore. Il momento migliore è di solito dopo un'azione dell'utente che rende i benefici delle notifiche concrete, come abilitare gli aggiornamenti di consegna, unirsi a una conversazione o salvare un oggetto seguito.
Un buona implementazione segue di solito questo flusso:
- L'utente raggiunge un confine significativo della funzione.
- L'app spiega il valore delle notifiche nel proprio UI.
- L'app richiede il permesso del sistema.
- L'app memorizza il token sul backend immediatamente se il permesso è stato concesso.
Quel passaggio finale è dove molti app falliscono. Eseguono il recupero del token, lo registrano localmente e rimandano la registrazione sul backend. In seguito, il supporto non può dire quale dispositivo aveva quale token in quale momento.
Ecco un semplice esempio di memorizzazione del token dopo la registrazione:
export async function enablePushForCurrentUser(userId: string) {
const result = await registerForExpoPushNotificationsAsync();
if (!result.ok) {
return result;
}
await fetch('https://api.example.com/push-tokens', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer user-session-token',
},
body: JSON.stringify({
userId,
token: result.token,
platform: Platform.OS,
}),
});
return result;
}
In un momento successivo del workflow, questo walkthrough è una utile riferimento visivo:
Per le squadre che stanno sviluppando app con rilasci pesanti, è anche utile pensare alla registrazione dei token come parte dello stato operativo dell'app, non solo come parte dell'accesso iniziale. Questo modo di pensare si adatta bene a flussi di lavoro più ampi di consegna di app Expo dove il comportamento dell'applicazione può cambiare frequentemente e lo stato del backend deve rimanere sincronizzato.Invio di Notifiche dal Server
Una volta che il backend ha un token di push Expo valido, l'invio di una notifica è abbastanza semplice. La parte difficile non è la richiesta stessa. È decidere cosa appartiene al payload e quanto fiducia si mette nello stato del client.
Ecco un esempio minimale Node-style utilizzando
Cosa dovrebbe fare ogni campo del payload fetch:
type ExpoPushMessage = {
to: string;
title: string;
body: string;
sound?: 'default' | null;
data?: Record<string, unknown>;
};
export async function sendExpoPushNotification(token: string) {
const message: ExpoPushMessage = {
to: token,
title: 'New review received',
body: 'Tap to open the order details.',
sound: 'default',
data: {
type: 'new_review',
orderId: 'ord_123',
screen: 'OrderDetails',
},
};
const response = await fetch('https://exp.host/--/api/v2/push/send', {
method: 'POST',
headers: {
Accept: 'application/json',
'Accept-encoding': 'gzip, deflate',
'Content-Type': 'application/json',
},
body: JSON.stringify(message),
});
const result = await response.json();
return result;
}
Non trattare il payload come un contenitore di scarti. Mantieni ogni campo intenzionale.
Campo
| Scopo | Consigli pratici | protectedTokens |
|---|---|---|
to |
Target Token di Expo | Verifica che appartenga al record dispositivo corrente |
title |
Intestazione di notifica | Tienilo breve e leggibile dagli utenti |
body |
Testo visibile principale | Fai chiara l'azione |
sound |
Comportamento del suono del sistema | Usalo con parsimonia per avvisi di alto valore |
data |
Metadati specifici dell'app | Preferisci gli ID e le indicazioni di percorso rispetto al contenuto ricco |
Il data l'oggetto è dove i flussi di lavoro dei prodotti diventano utili. Puoi passare un tipo e un ID record, poi lascia che l'app fetchi i dati più recenti quando l'utente clicca. È più sicuro di inserire direttamente nel payload grandi o sensibili blob.
Mantieni i payload piccoli e noiosi
Secondo La guida di Courier per le notifiche di ExpoLe token di notifica di Expo dovrebbero essere trattati come ephemeri, i payload che superano i limiti di dimensione di circa 4 KB possono essere eliminati, e un pattern affidabile è inviare payload di metadati piccoli come { "type": "new_review", "id": 123 } piuttosto che grandi JSON o media inline. Quell'indicazione corrisponde a ciò che funziona nei sistemi reali. I payload piccoli falliscono meno spesso e invecchiano meglio quando cambia la logica dell'applicazione.
Invia abbastanza dati per indirizzare l'utente. Esegui il resto dopo che l'app si apre.
Abitudini utili del server
Una funzione di invio base è sufficiente per le prove. Una funzione di produzione solitamente aggiunge alcune responsabilità aggiuntive:
- Mantieni i tentativi di invio: Salva l'intento di notifica con ID utente, token, tipo di payload e timestamp.
- Separate la generazione del contenuto dal trasporto: Costruisci la copia del messaggio in un layer e la richiesta Expo API in un altro.
- Tratta i feedback di invalidazione: Se Expo riporta in seguito
DeviceNotRegistered, segnala che il token è scaduto e smetti di riprovare a caso. - Utilizza un design amico dei webhook: Se il tuo sistema emette già eventi, invia le notifiche di trigger attraverso lo stesso modello di elaborazione dei webhook di backend che utilizzi altrove. Prima di debuggare gli ascoltatori del client, invia una notifica di test manuale. Se un token riceve una notifica normale con un payload piccolo, il tuo percorso di trasporto è probabilmente sano. Se non, non iniziare cambiando la navigazione __CAPGO_KEEP_0__. Inizia validando il token, la forma del payload e lo stato di autorizzazione. Manutenzione delle Notifiche In Arrivo Nella Tua App
Before debugging client listeners, send a manual test push first. If a token receives a plain notification with a tiny payload, your transport path is probably healthy. If not, don’t start by changing navigation code. Start by validating the token, payload shape, and permission state.
Handling Incoming Notifications in Your App
Delivery is only half of the feature. The app has to do something coherent when the notification arrives and when the user taps it.
Che significa gestire due momenti separati:
- l'arrivo della notifica mentre l'app è aperta
- l'utente interagisce con la notifica dalla barra dei sistemi o dalla schermata di blocco

La ricezione in anteprima e la risposta dell'utente sono eventi diversi
Un setup affidabile include entrambi gli ascoltatori:
import { useEffect } from 'react';
import * as Notifications from 'expo-notifications';
export function useNotificationObservers(
onForegroundMessage: (notification: Notifications.Notification) => void,
onNotificationTap: (response: Notifications.NotificationResponse) => void
) {
useEffect(() => {
const receivedSub = Notifications.addNotificationReceivedListener(
(notification) => {
onForegroundMessage(notification);
}
);
const responseSub = Notifications.addNotificationResponseReceivedListener(
(response) => {
onNotificationTap(response);
}
);
return () => {
receivedSub.remove();
responseSub.remove();
};
}, [onForegroundMessage, onNotificationTap]);
}
addNotificationReceivedListener Esegue quando l'app è attiva. addNotificationResponseReceivedListener Esegue quando l'utente tocca una notifica consegnata. Non combinarli mentalmente. Servono percorsi UX diversi.
Leggi il payload dei dati e naviga intenzionalmente
Ecco un pattern pratico per il trattamento del tocco:
type NotificationData = {
type?: string;
orderId?: string;
screen?: string;
};
export function handleNotificationTap(
response: Notifications.NotificationResponse,
navigation: any
) {
const data =
response.notification.request.content.data as NotificationData;
if (data.screen === 'OrderDetails' && data.orderId) {
navigation.navigate('OrderDetails', { orderId: data.orderId });
return;
}
if (data.type === 'new_review') {
navigation.navigate('Inbox');
return;
}
navigation.navigate('Home');
}
Questo pattern rimane resiliente perché il payload contiene indizi di routing, non documenti interi. Se l'ordine è cambiato dal momento in cui la notifica è stata inviata, l'app può recuperare lo stato del server corrente dopo la navigazione.
Una notifica toccata dovrebbe portare a un destino ovvio. Se il tuo percorso di fallback è vago, gli utenti lo notano immediatamente.
Il comportamento in primo piano dovrebbe corrispondere al contesto utente
Mostrare un avviso di sistema a schermo chiuso quando l'app è già aperta può sembrare goffo. A volte il passo giusto è un banner in-app, aggiornamento della badge o rinfresco silenzioso. Una schermata di posta di supporto potrebbe non aver bisogno di un avviso visibile quando l'utente sta già leggendo quella conversazione.
È per questo che il tuo ascoltatore in primo piano dovrebbe ramificarsi in base alla rotta e al tipo di notifica. Ad esempio:
- Schermo di chat aperto: aggiungi il messaggio e evita un banner ridondante
- Schermo di dashboard aperto: mostra un toast in-app leggero
- Evento critico dell'account: presenta un trattamento UI più forte
Un approccio semplice assomiglia a questo:
export function handleForegroundNotification(
notification: Notifications.Notification,
currentRouteName: string
) {
const data = notification.request.content.data as { type?: string };
if (currentRouteName === 'ChatThread' && data.type === 'new_message') {
// refresh local thread state
return;
}
// otherwise show your own in-app UI or update badges
}
Se il tuo app non distingue questi contesti, gli utenti sentiranno la fatica delle notifiche più velocemente, anche se la consegna è tecnicamente corretta.
Pratiche di produzione migliori e comuni insidie
La maggior parte delle configurazioni di notifiche push Expo non funzionanti non falliscono perché Expo è troppo limitato. Falliscono perché gli squadre assumono che il token sia permanente, i payload possono trasportare qualsiasi cosa e gli aggiornamenti dell'app non influenzeranno la logica delle notifiche.
Quell'assunzione non sopravvive alla produzione.

Il token è effimero, non un registro di identità
Un token di notifica Expo è meglio trattato come un affitto, non come un dispositivo di identificazione a vita. I token possono rotare dopo reinstallazione, cambiamenti di sistema operativo o altri eventi di ciclo di vita. Se un token torna infine DeviceNotRegisteredil tuo backend dovrebbe smettere di trattarlo come attivo.
Un modello backend pratico memorizza:
- ID utente
- piattaforma
- metadati di installazione
- token corrente
- timestamp dell'ultima visualizzazione
- Stato come attivo, scaduto o revocato
Non memorizzare un campo di token nella tabella degli utenti e chiamarlo fatto. Gli utenti hanno più dispositivi e i dispositivi cambiano stato.
La strategia di aggiornamento conta più di quanto ammettono la maggior parte dei tutorial
La guida ufficiale dell'ecosistema lascia un vero e reale gap operativo qui. Il contenuto delle notifiche di Expo push spesso non spiega come mantenere la validità dei token attraverso i cicli di revisione dell'App Store e gli aggiornamenti OTA Ciò è particolarmente importante per i team che inviano cambiamenti live perché la affidabilità delle push dipende dallo stato dei token correnti e dalla sincronizzazione con il backend, come notato nella documentazione delle notifiche di ExpoCiò influenza come progettare i trigger di aggiornamento. Buoni momenti per riconciliare lo stato dei token includono: Avvio dell'app dopo un aggiornamento.
Accesso dell'utente
- Cambio delle impostazioni di autorizzazione
- Lavoro di rotazione delle credenziali nel processo di rilascio
- Lavoro di rotazione delle credenziali nel processo di rilascio
- Lavoro di rotazione delle credenziali nel processo di rilascio
- Flussi di ripristino dopo biglietti di supporto correlati a push
La sicurezza e la conformità non devono essere al termine della sprint
Molti tutorial di Expo si concentrano sulla meccanica e trascurano il rischio operativo. È tutto bene per le app di hobby. Non è tutto bene per i prodotti sanitari, fintech o commercio regolamentato.
Il discorso di Courier incentrato sull'impresa sui vuoti di notifica di Expo mette in evidenza una mancanza di guide pratiche sull'iscrizione al consenso, sulle tracce di audit e sulla riduzione dell'esposizione dei dati sensibili nel payload. Il takeaway di ingegneria diretta è semplice:
- Non mettere i dati sensibili dell'azienda nel testo o nel metadati di payload delle notifiche.
- Registrare i cambiamenti di consenso sul server.
- Registrare quale intento di notifica è stato inviato a quale token.
- Usare gli ID nei payload e recuperare il contenuto protetto dopo l'apertura dell'app.
Per le squadre che allineano le operazioni di rilascio con le pratiche di sicurezza più ampie e __CAPGO_KEEP_0__ di conformità dell'app store app store compliance and API security practices__CAPGO_KEEP_0__
Le notifiche push sono messaggi destinati agli utenti, ma sono anche un problema di sistemi distribuiti. Trattiamole con la stessa cura che applichiamo allo stato di autenticazione e agli eventi di pagamento.
Cosa funziona di solito e cosa di solito si rompe
| Funziona di solito | Chiedere il permesso dopo una chiara spiegazione del valore |
|---|---|
| Sporca sul primo frame | Testare su dispositivi reali |
| Fidarsi della registrazione del simulatore | Memorizzare i token con il contesto del dispositivo |
| Un token per ogni record utente | Invio di piccoli payload di metadati |
| Inserimento di grandi o sensibili blob | Inserimento di grandi o sensibili blob |
| Gestione di eventi in primo piano e di tap separatamente | Supponendo che tutte le notifiche seguano un percorso |
| Scadere i token obsoleti con aggressività | Riprovare i token morti per sempre |
Una buona configurazione di push per Expo non è complicata. È disciplinata.
Se il tuo team invia cambiamenti logici dell'app con frequenza e ha bisogno di un controllo più stretto sul comportamento di rilascio, sui rollback e sulla visibilità della consegna, Capgo è degno di una considerazione. Aiuta i team mobili a inviare aggiornamenti velocemente senza dover aspettare la revisione della store, il che è particolarmente utile quando sono necessari flussi di notifiche, logica di routing o correzioni client-side che devono raggiungere gli utenti velocemente.