Probabilmente sei arrivato al punto in cui l'app funziona, gli utenti sono stati registrati e il prodotto vuole flussi di ri-engaggio che sentono nativi. Ricordi della cesta. Suggerimenti di recensione. Nuove notifiche di messaggio. Annunci di rilascio. La prima istintiva è spesso
,
, , ,
,
- ,
- Configurazione e impostazione del progetto iniziale
- Richiesta di autorizzazione e cattura dei token di push
- Invia notifiche dal tuo server
- Gestione delle notifiche in arrivo nel tuo App
- Pratiche e trappole comuni nella produzione
La Fondazione per coinvolgere gli utenti con le notifiche Push di Expo
Un setup delle notifiche Push di Expo è attraente per una ragione soprattutto. Rimuove molta complessità della messaggistica nativa che le squadre non vogliono gestire già dal primo giorno. Invece di costruire il collegamento diretto con APNs e FCM in primo luogo, potete lavorare con la gateway di Expo e concentrarvi sul comportamento del prodotto, la routing, l'esperienza UX delle autorizzazioni e la logica dei messaggi backend.
Quell'astrazione non rende le notifiche 'meno reali'. Cambia solo dove va il tuo sforzo di ingegneria.
Il servizio è anche veloce abbastanza che il rendimento non è il primo problema da cui preoccuparsi. Dal 14 marzo 2023 al 12 giugno 2023, le notifiche push di Expo API hanno mostrato un 42 millisecondo di tempo di risposta mediano, 273 millisecondo di latenza p99, e un tasso di errore medio quotidiano del 0,17% su decine di milioni di messaggi quotidianisecondo Knock’s Expo push API analisi di benchmark di Knock. Ciò dovrebbe rassicurare qualsiasi team che si chieda se Expo sia adatto solo per prototipi.
Cosa Expo astrae effettivamente
Quando i team dicono “Expo push,” spesso si riferiscono a diverse preoccupazioni separate raccolte insieme:
- Fornitore di routing: 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.
- Richiesta di contratto: Inviare un payload al push di Expo API al posto di integrare direttamente le 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:
| Preoccupazione | Mentalità di demo | Mentalità di produzione |
|---|---|---|
| Autorizzazioni | Chiedi subito | Chiedi in contesto, dopo che il valore dell'utente è chiaro |
| Token | Salva una volta | Aggiorna, elimina duplicati, scada e riconcilia |
| Payload | Metti tutto in 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 di manuali | Ricevute, pulizia, log e gestione degli incidenti |
La differenza tra “invio di notifiche” e “notifiche che supportano un workflow di prodotto reale.”
Configurazione e impostazione 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 flusso di lavoro locale con una configurazione del client di sviluppo Expo personalizzata, perché il comportamento delle notifiche spesso deve essere verificato in una build che riflette la produzione più da vicino di una rapida esecuzione di sandbox.
Installa i pacchetti di notifica
Almeno, avrai bisogno di:
expo-notificationsper le richieste di autorizzazione, la raccolta del token, i listener 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 quelle 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 tuo contratto di 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"
}
}
}
}
Un paio di dettagli contano qui:
- I identificatori di bundle e i nomi dei pacchetti devono corrispondere all'app che effettivamente invii.
- Il plugin delle notifiche assicura che il progetto nativo riceva la configurazione richiesta durante la compilazione.
- L'ID del progetto EAS È importante che la raccolta del token tenga presente l'app associata al progetto Expo corretto.
Imposta un gestore di notifica in anticipo
Molti tutorial di base aspettano troppo a definire il comportamento delle notifiche. Non farlo. Collocale vicino all'avvio dell'app per comportamento di primo piano prevedibile.
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: true,
}),
});
I team 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 il comportamento in primo piano in modo intenzionale, il tuo team si ritroverà a debuggare le notifiche 'mancanti' che sono state effettivamente ricevute ma mai presentate nel modo in cui il prodotto si aspettava.
Android richiede la configurazione del canale
I canali di notifica Android non sono facoltativi nella pratica. Se li ignorate, le vostre avvisaglie possono sembrare inconsistenti o fallire nel soddisfare le aspettative degli utenti.
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,
});
}
Configura questo durante l'inizializzazione dell'app. Poi mantieni stabili gli ID dei canali. Cambiarli casualmente rende il comportamento delle notifiche più difficile da ragionare in seguito.
Richiesta di autorizzazione e cattura dei token di push
Questo è il passaggio che molti team copiano da un snippet, poi finiscono per pentirsi.
Le richieste di autorizzazione richiedono un timing, una consapevolezza della piattaforma e un trattamento asincrono disciplinato. La cattura dei token deve avvenire solo su un dispositivo fisico, solo dopo la risoluzione delle autorizzazioni e solo se si è pronti a memorizzare il risultato sul backend immediatamente.

The 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. Verifica il tipo di dispositivo per primo, 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. Le squadre esperte richiedono le autorizzazioni condizionalmente solo quando Device.isDevice è vero, e un comune tranello è saltare quel guardiano, che porta gli sviluppatori a inviare notifiche a token di simulatore non validi e a incolpare Expo quando il problema è realmente la configurazione dell'app, come descritto in Note di implementazione delle notifiche Expo di Eagerworks.
È per questo che il controllo si trova in cima alla funzione. Non nasconderlo dietro un aiutante. Faglielo evidente.
I risultati del simulatore sono utili per la verifica della UI. Non sono affidabili per la validazione della registrazione del token di push.
Chiedi le autorizzazioni nel momento giusto
Don’t chiedere sulla schermata di benvenuto. 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 segnalato.
Una buona implementazione segue di solito questo flusso:
- L’utente raggiunge un confine significativo della funzionalità dell’app.
- 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 molte 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 un momento specifico.
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 seguito nel workflow, questo walkthrough è un utile riferimento visivo:
Per le squadre che stanno costruendo app con rilasci frequenti, è anche utile pensare alla registrazione del token come parte dello stato operativo dell’app, non solo come parte dell’onboarding. Questo modo di pensare si adatta bene con le workflow di consegna dell’app Expo, dove il comportamento dell’app può cambiare frequentemente e lo stato del backend deve rimanere sincronizzato.
Invia Notifiche dal tuo Server
Una volta che il tuo backend ha un token di avvio Expo valido, inviare una notifica è abbastanza semplice. La parte difficile non è la richiesta stessa. È decidere cosa appartiene al payload e quanto fiducia si mette nel stato del client.
Ecco un esempio minimale Node-style utilizzando 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;
}
Cosa dovrebbe fare ogni campo del payload
Non trattare il payload come un mucchio di rifiuti. Mantieni ogni campo intenzionale.
| Campo | Scopo | Consigli pratici |
|---|---|---|
to |
Token di avvio Expo di destinazione | Verifica che appartenga al record dispositivo corrente |
title |
Intestazione della notifica | Tienilo breve e leggibile per l'uomo |
body |
Testo visibile principale | Fare chiara l'azione |
sound |
Comportamento del suono del sistema | Usare con parsimonia per avvisi di alto valore |
data |
Metadati specifici dell'app | Preferire 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 di record, quindi lasciare che l'app fetchi i dati più recenti quando l'utente clicca. È più sicuro di inserire direttamente nel payload grandi o sensibili blocchi di dati.
Tenere i payload piccoli e noiosi
Secondo la guida di Courier per le notifiche di Expo, i Token di Push di Expo dovrebbero essere trattati come ephemeris, i payload che superano i limiti di dimensione di circa 4 KB può essere abbandonato, e un modello affidabile è quello di inviare piccoli payload di metadati come { "type": "new_review", "id": 123 } piuttosto che grandi JSON o media inline. Quel consiglio corrisponde a ciò che funziona nei sistemi reali. I payload piccoli falliscono meno spesso e invecchiano meglio quando cambia la logica dell'applicazione.
Inviare abbastanza dati per indirizzare l'utente. Estrarre il resto dopo che l'app è stata aperta.
Abitudini utili del lato server
Una funzione di invio base è sufficiente per la prova. Una funzione di produzione solitamente aggiunge alcune responsabilità:
- Persistere gli sforzi di invio: Salvare l'intento di notifica con ID utente, token, tipo di payload e timestamp.
- Separare la generazione del contenuto dal trasporto: Costruire la copia del messaggio in un layer e la richiesta Expo API in un altro.
- Trattare la feedback di invalidazione: Se Expo riporta in seguito
DeviceNotRegisteredSegnala che quel token è scaduto e smetti di riprovare senza senso. - Utilizza un design adatto per le webhook: Se il tuo sistema emette già eventi, invia i trigger delle notifiche attraverso lo stesso modello di elaborazione delle webhook sul backend che usi altrove. Prima di debuggare i client listener, invia una push manuale per testare. Se un token riceve una notifica semplice con un payload piccolo, il tuo percorso di trasporto è probabilmente sano. Se non, non iniziare a cambiare la navigazione __CAPGO_KEEP_0__. Inizia a validare il token, la forma del payload e lo stato delle autorizzazioni. 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.
Questo significa gestire due momenti separati:
la notifica arriva mentre l'app è aperta
l'utente interagisce con la notifica dalla barra delle notifiche o dalla schermata di blocco
- Diagramma di flusso che illustra il ciclo di vita delle notifiche push per le applicazioni mobili in stati di anteprima e di background.
- Handling Incoming Notifications in Your App

La ricezione di background e la risposta dell'utente sono eventi diversi
Una configurazione affidabile include di solito 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 si esegue quando l'app è attiva. addNotificationResponseReceivedListener si esegue quando l'utente tocca una notifica inviata. Non combinarli mentalmente. Servono percorsi UX diversi.
Leggi il payload dei dati e naviga intenzionalmente
Ecco un pattern pratico per il trattamento del tap:
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 obiettivo evidente. Se il tuo percorso di fallback è vago, gli utenti lo notano immediatamente.
Il comportamento in primo piano dovrebbe corrispondere al contesto dell'utente
Quando l'app è già aperta, mostrare un avviso di sistema a caso può sembrare goffo. A volte il movimento giusto è un banner in-app, un aggiornamento della badge o un aggiornamento silenzioso. Una schermata di supporto per la casella di posta in arrivo potrebbe non richiedere 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 della chat aperto: Aggiungi il messaggio e evita un banner inutile
- Dashboard aperto: Mostra un avviso leggero in-app
- Evento critico dell'account: Sottolinea un trattamento UI più forte
Un approccio semplice sembra essere 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 ottimali di produzione e comuni insuccessi
La maggior parte delle configurazioni di notifiche push rotte Expo non falliscono perché Expo è troppo limitato. Falliscono perché i team 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.

I token sono effimeri, non registri 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 DeviceNotRegistered eventualmente, il tuo backend dovrebbe smettere di trattarlo come attivo.
Un modello di backend pratico memorizza:
- ID utente
- piattaforma
- metadati di installazione a livello di applicazione
- token corrente
- timestamp dell'ultima visualizzazione
- stato come attivo, scaduto o revocato
Non memorizzare un campo di token unico sulla tabella degli utenti e chiamalo fatto. Gli utenti hanno più dispositivi e i dispositivi cambiano stato.
La strategia di aggiornamento conta più di quanto ammettano la maggior parte dei tutorial
La guida ufficiale dell'ecosistema lascia un vero gap operativo qui. Il contenuto di notifica Expo esistente spesso non spiega come mantenere la validità dei token across Cicli di revisione delle recensioni dell'App Store e aggiornamenti OTA, il che è particolarmente importante per le squadre che inviano modifiche live perché la affidabilità della push dipende dallo stato attuale del token e dalla sincronizzazione del backend, come notato in La documentazione delle notifiche di Expo.
Ciò influenza come progettare i trigger di aggiornamento. Buoni momenti per riconciliare lo stato del token includono:
- Avvio dell'app dopo un aggiornamento
- Accesso dell'utente
- Modifica delle impostazioni delle autorizzazioni
- Lavoro di rotazione delle credenziali sul processo di rilascio
- Flussi di recupero dopo i ticket di supporto correlati alla push
La sicurezza e la conformità non devono essere lasciate alla fine dello sprint
Molti tutorial di Expo si concentrano sulla meccanica e trascurano il rischio operativo. È tutto a posto per gli app di hobby. Non è a posto per i prodotti di healthcare-adiacente, fintech o commercio regolamentato
La discussione di Courier sulle lacune delle notifiche di Expo focalizzata sull'enterprise mette in evidenza la mancanza di una guida pratica per la registrazione del consenso, le tracce di audit e la minimizzazione dell'esposizione dei payload sensibili. Il takeaway di ingegneria diretta è semplice:
- Non inserire dati aziendali sensibili nel testo delle notifiche o nei metadati dei payload.
- Logga le modifiche del consenso sul server.
- Registra quale intento di notifica è stato inviato a quale token.
- Utilizza gli ID nei payload e recupera il contenuto protetto dopo l'apertura dell'app.
Per gli squadre che allineano le operazioni di rilascio con le pratiche di sicurezza più ampie e __CAPGO_KEEP_0__ dell'app store app store compliance and API security practicesIl notifiche push sono messaggi faccia a faccia con l'utente, ma sono anche un problema di sistemi distribuiti. Trattali con la stessa cura che si applica allo stato di autenticazione e agli eventi di pagamento.
Cosa funziona di solito e cosa di solito si rompe
Funziona di solito
| Si rompe di solito | breaks |
|---|---|
| Richiedere la autorizzazione dopo una spiegazione del valore chiaro | Sollecitare nella prima riga del frame |
| Testare su dispositivi reali | Trasmettere la registrazione del simulatore |
| Memorizzare i token con contesto dispositivo | Un token per ogni record utente |
| Inviare piccoli payload di metadati | Inserire grandi o sensibili blob |
| Gestire eventi di foreground e tap separatamente | Assumere che tutte le notifiche seguano un percorso |
| Scadere i token invecchiati con aggressività | Riprovare i token morti per sempre |
Una configurazione Expo push solida non è complicata. È disciplinata.
Se il tuo team invia modifiche alla logica 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 attendere la revisione della store, il che è particolarmente utile quando i flussi di notifica, la logica di routing o i ripari sul lato del client devono raggiungere gli utenti velocemente.