Notifiche Android: ricorrenza, badge e gamification
Le notifiche in un gestore di attività sono fondamentali. Se il promemoria non arriva al momento giusto, l'app ha fallito. E su Android, far arrivare un promemoria al momento giusto è una lotta costante contro il sistema operativo stesso.
Non è un problema di codice. È un problema di ecosistema. Samsung, Xiaomi, Huawei, Oppo: ogni produttore implementa la propria politica di risparmio energetico che può bloccare la tua app e le sue notifiche programmate senza preavviso. Aggiungi i badge delle icone, le push FCM e le notifiche di gamification, e ottieni un sistema che deve essere affidabile, cross-manufacturer ed emotivamente soddisfacente.
Punti chiave
- I promemoria ricorrenti programmano le prossime 30 occorrenze in una volta sola per sopravvivere al kill di Android, invece di programmare solo la prossima occorrenza.
- Ogni apertura dell'app verifica nuovamente e riprogramma le notifiche perse durante il riavvio o il kill da parte del sistema.
- I badge delle icone su Android richiedono implementazioni specifiche per launcher (Samsung, Nova, AOSP), senza un'API unificata.
- Le notifiche di gamification trasformano un meccanismo di sistema in un momento di motivazione grazie a messaggi personalizzati e icone personalizzate.
Perché programmare 30 occorrenze invece di una sola?
La risposta è in una parola: sopravvivenza. Su Android, il sistema operativo può decidere di bloccare la tua app in qualsiasi momento per liberare memoria. Quando l'app viene bloccata, la logica JavaScript che doveva programmare la prossima occorrenza muore con essa.
La strategia ingenua è quella di programmare solo il prossimo promemoria e riprogrammare il successivo quando il primo si attiva. Problema: se l'app viene bloccata tra l'attivazione del promemoria e la riprogrammazione, la catena si spezza. L'utente non riceverà mai più un promemoria.
La mia soluzione: programmare le prossime 30 occorrenze non appena viene creato il promemoria ricorrente. Se hai un promemoria giornaliero alle 9, l'app crea immediatamente 30 allarmi: uno per domani alle 9, uno per dopodomani alle 9, e così via. Anche se l'app viene bloccata per 3 settimane, i promemoria continueranno ad arrivare.
La documentazione Android su AlarmManager raccomanda di usare setExactAndAllowWhileIdle per gli allarmi critici. Questo è ciò che uso per ogni occorrenza. Il "AllowWhileIdle" è cruciale: senza di esso, la modalità Doze di Android (attivata quando il telefono è immobile e non collegato) può ritardare l'allarme indefinitamente.
Perché 30 e non 365? Perché troppi allarmi simultanei possono influire sulle prestazioni e sulla batteria. 30 giorni è il compromesso ideale: l'utente è coperto per un mese, e l'app aggiorna le occorrenze ad ogni apertura. Avevo già esplorato questo tipo di compromesso prestazioni/affidabilità nell'articolo sulla ricorrenza dei promemoria.
Come gestire le notifiche perse al riavvio?
Quando un telefono si riavvia, tutti gli allarmi programmati tramite AlarmManager vengono persi. Questo è il comportamento standard di Android. La soluzione ufficiale: ascoltare il broadcast BOOT_COMPLETED per riprogrammare gli allarmi all'avvio.
In teoria, è pulito. In pratica, è un campo minato.
Samsung blocca BOOT_COMPLETED per impostazione predefinita su alcuni modelli con la loro "Ottimizzazione della batteria". Xiaomi ha MIUI che impedisce l'avvio automatico delle app a meno che l'utente non lo autorizzi manualmente nelle impostazioni. Huawei con EMUI fa lo stesso. Oppo con ColorOS, idem. Secondo il sito Don't Kill My App, che elenca i comportamenti per produttore, alcuni dispositivi bloccano fino al 90% dei broadcast.
La mia soluzione pragmatica: non fare affidamento solo su BOOT_COMPLETED. Ad ogni apertura dell'app, il NotificationService esegue un audit completo:
- Recupero dei promemoria attivi dal database locale.
- Verifica: per ogni promemoria, l'allarme corrispondente esiste ancora in
AlarmManager? - Riprogrammazione degli allarmi mancanti.
- Pulizia degli allarmi obsoleti (attività eliminate, promemoria disattivati).
Questo processo richiede circa 200ms per 50 promemoria attivi. L'utente non lo nota. Ma garantisce che anche se il telefono si è riavviato, anche se il produttore ha bloccato il boot broadcast, le notifiche verranno riprogrammate alla prossima apertura dell'app.
Come Firebase Cloud Messaging gestisce le push di gruppo?
Le notifiche locali (promemoria, ricorrenza) sono gestite da AlarmManager sul dispositivo. Le notifiche push (attività di gruppo, badge sbloccati, menzioni) passano attraverso Firebase Cloud Messaging.
Il flusso è il seguente:
- Un utente crea un'attività in un gruppo e la assegna a un membro.
- Il backend rileva l'assegnazione e recupera il token FCM dell'assegnato dal database.
- Il backend invia un messaggio FCM con il titolo, il corpo e un payload di dati (tipo di azione, ID dell'attività, ID del gruppo).
- Il telefono dell'assegnato riceve la push, anche se l'app è chiusa.
- Se l'utente tocca la notifica, l'app si apre direttamente sull'attività in questione grazie al deep link nel payload.
La trappola principale con FCM: i token cambiano. Un token FCM può diventare invalido quando l'utente disinstalla e reinstalla l'app, quando cancella i dati dell'app, o quando Google decide di riciclarlo. La mia strategia: aggiornare il token ad ogni avvio dell'app e confrontarlo con quello memorizzato nel DB. Se diverso, aggiornare. E lato backend, ogni errore di invio FCM con il codice messaging/registration-token-not-registered attiva una pulizia automatica del token invalido.
È lo stesso principio di resilienza che applico nel sistema di sicurezza e rate limiting: anticipare i fallimenti, non solo gestirli quando si presentano.
Perché i badge delle icone sono così difficili su Android?
Il piccolo cerchio rosso con un numero sull'icona dell'app. Su iOS, è una riga di codice: UIApplication.shared.applicationIconBadgeNumber = 5. È un'API di sistema standardizzata da iOS 3.
Su Android, non esiste un'API standardizzata per i badge delle icone. Ogni launcher implementa il proprio metodo:
- Samsung (OneUI): utilizza i Samsung BadgeProvider tramite un ContentProvider specifico.
- Nova Launcher: legge i badge da un broadcast Intent personalizzato.
- AOSP/Pixel: utilizza il canale di notifica con
setNumber()sulla notifica stessa (nessun badge standalone). - Xiaomi (MIUI): ha la sua API tramite un ContentProvider diverso da Samsung.
- Huawei: utilizza i Huawei Mobile Services invece dei Google Play Services.
La libreria react-native-app-badge astrae parte di questa frammentazione, ma non copre tutti i casi. Ho accettato questa realtà: su alcuni dispositivi, i badge funzioneranno perfettamente. Su altri, non verranno visualizzati. L'app non deve mai dipendere esclusivamente dai badge per comunicare informazioni importanti, sono un bonus visivo, non un canale critico.
Come le notifiche di gamification trasformano l'esperienza?
Le notifiche più soddisfacenti non sono i promemoria. Sono le notifiche di gamification. Un badge sbloccato, un traguardo di streak raggiunto, un level up: sono momenti di celebrazione che l'utente non si aspettava.
Ho implementato tre tipi di notifiche di gamification:
Badge sbloccato
Notifica locale con un'icona personalizzata corrispondente al badge. Il testo è personalizzato: "Badge Organizzatore Pro sbloccato! Hai creato 100 attività." È più coinvolgente di "Nuovo badge sbloccato". La personalizzazione del messaggio aumenta il tasso di ritenzione della notifica secondo le ricerche di OneSignal sulla personalizzazione.
Traguardo di streak
"Streak di 30 giorni! Continua così." Lo streak è un contatore di giorni consecutivi di utilizzo dell'app. Il sistema riconosce i traguardi: 7 giorni, 30 giorni, 100 giorni, 365 giorni. Ogni traguardo attiva una notifica e punti bonus. Avevo dettagliato l'intero sistema di gamification nell'articolo sullo schema di gamification.
Level up
"Livello 5 raggiunto! Ora sei uno Stratega." I 12 livelli hanno ciascuno un nome e una soglia di punti. La notifica di level up è la più rara e gratificante. È lo stesso meccanismo di ricompensa variabile descritto da B.F. Skinner nelle sue ricerche sul rinforzo: le ricompense imprevedibili creano un coinvolgimento più forte delle ricompense prevedibili.
Il punto comune tra questi tre tipi: trasformano una notifica (meccanismo spesso percepito come intrusivo) in un momento positivo. L'utente non subisce la notifica, la aspetta. Questa è esattamente la filosofia del feed di gamification: rendere l'impegno visibile e gratificante.
Come ottimizzare l'affidabilità delle notifiche su tutti i dispositivi?
Se dovessi riassumere in una frase: non fidarti di nulla. Non fidarti di BOOT_COMPLETED. Non fidarti di AlarmManager in modalità Doze. Non fidarti dei token FCM. Non fidarti dei badge delle icone.
La strategia di difesa in profondità:
- Livello 1: allarmi locali tramite
setExactAndAllowWhileIdle(30 occorrenze pre-programmate). - Livello 2: audit e riprogrammazione ad ogni apertura dell'app.
- Livello 3: push FCM come backup per i promemoria critici (inviati dal backend se l'allarme locale non è stato confermato).
- Livello 4: guida dell'utente alle impostazioni della batteria del produttore (schermata dedicata nelle impostazioni dell'app).
Quest'ultimo punto è spesso trascurato. L'app include una schermata che rileva il produttore del telefono e guida l'utente passo dopo passo per disattivare l'ottimizzazione della batteria per TAMSIV. È UX tecnica: spiegare all'utente perché i suoi promemoria potrebbero non funzionare e come risolverlo. È la stessa trasparenza che nell'onboarding lazy registration: essere onesti sui limiti piuttosto che nasconderli.
Domande frequenti
I promemoria ricorrenti funzionano quando il telefono è spento?
No. Nessun allarme può attivarsi quando il telefono è spento. Tuttavia, non appena il telefono si riavvia, l'app riprogramma automaticamente le occorrenze mancate alla prossima apertura. I promemoria passati non vengono inviati retroattivamente.
Perché le notifiche sono a volte in ritardo su alcuni telefoni?
Ciò è dovuto alla modalità Doze di Android e alle ottimizzazioni della batteria dei produttori. TAMSIV utilizza setExactAndAllowWhileIdle per minimizzare i ritardi, ma alcuni produttori (in particolare Xiaomi e Huawei) impongono restrizioni aggiuntive. La sezione "Notifiche" delle impostazioni dell'app spiega come disattivarle.
Le notifiche di gamification possono essere disattivate?
Sì. Le impostazioni dell'app consentono di disattivare indipendentemente le notifiche di badge, streak e level up. I promemoria delle attività e le push di gruppo sono su canali separati e non sono influenzati.
Lo streak viene perso se salto un giorno?
Lo streak torna a zero se salti un giorno. Tuttavia, il sistema di "streak freeze" ti permette di proteggere il tuo streak: se hai accumulato abbastanza punti, puoi attivare un blocco che preserva il tuo streak per un giorno di inattività.
I badge delle icone mostrano il numero esatto di notifiche non lette?
Su Samsung e sui launcher compatibili, sì, il badge mostra il numero esatto. Sui launcher AOSP standard, il badge è un semplice punto (presenza/assenza) senza numero. È una limitazione di Android che Google non ha ancora unificato.