Notifiche Android in Java: guida completa con esempi

Notifiche Android in Java: guida completa con esempi

Scopri come creare notifiche Android in Java con NotificationCompat, NotificationChannel, PendingIntent e permessi Android 13+, con esempi pratici. Di seguito, questa guida ti accompagna passo passo nel mondo delle notifiche Android usando Java. Vedrai quindi come creare notifiche locali con NotificationCompat, gestire i NotificationChannel da Android 8 (Oreo) in poi, impostare icona, titolo, testo, priorità, aprire un’attività con PendingIntent, creare notifiche espandibili e infine capire la differenza tra notifiche locali e notifiche push.

Notifiche Android in Java: guida completa

Prerequisiti

Per seguire questa guida, dovresti avere i seguenti requisiti:

  • Conoscenza base di Java
  • Conoscenza base di Android Studio (creazione progetto, Activity, manifest)
  • SDK Android aggiornato (consigliato: minimo API 21+, target API 33 o successivo)

Tutti gli esempi presentati di seguito sono pensati per sviluppatori principianti e intermedi che desiderano acquisire una base solida sulle notifiche Android.

Concetti fondamentali delle notifiche

Una notifica Android è un messaggio mostrato fuori dalla tua app (tipicamente nell’area notifiche) per informare l’utente di qualcosa di importante: un nuovo messaggio, un promemoria, un download completato, e così via.

Componenti principali di una notifica

  • Icona piccola (small icon): appare nella barra di stato e a sinistra della notifica.
  • Titolo: testo in grassetto che riassume il contenuto.
  • Testo: descrizione più dettagliata.
  • Priorità / Importanza: indica quanto la notifica è “urgente” per l’utente.
  • Canale (NotificationChannel): categoria logica usata da Android 8+ per gestire le preferenze dell’utente.
  • Azione al tocco (PendingIntent): ciò che succede quando l’utente tocca la notifica (aprire un’Activity, eseguire un servizio, ecc.).

Configurazione di base del progetto

Dipendenze per NotificationCompat

Innanzitutto, assicurati di avere la libreria AndroidX Core (che include NotificationCompat) nel file build.gradle (module):

dependencies {
    implementation "androidx.core:core:1.12.0" // dipendenza core compatibile con Java
}

Se utilizzi solo Java, la parte -ktx non è obbligatoria, anche se è comune nei progetti moderni. Di fatto, NotificationCompat si trova in androidx.core.app.NotificationCompat.

NotificationChannel per Android 8.0 (API 26) e successivi

A partire da Android 8.0, ogni notifica deve appartenere a un canale. Questo consente all’utente di gestire, su base canale, il suono, la vibrazione e altre impostazioni. In assenza di un canale, su Android 8+ la notifica non verrà visualizzata.

Creare un NotificationChannel

Di norma, i canali si creano una sola volta, ad esempio nell’Application o nella prima Activity avviata.

public class MyApp extends Application {

    public static final String CHANNEL_ID_MESSAGES = "channel_messages";

    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannel();
    }

    private void createNotificationChannel() {
        // I canali sono richiesti solo da Android 8.0 (API 26) in poi
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "Messaggi"; // Nome visibile all'utente
            String description = "Notifiche per i nuovi messaggi";
            int importance = NotificationManager.IMPORTANCE_DEFAULT;

            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID_MESSAGES,
                    name,
                    importance
            );
            channel.setDescription(description);

            NotificationManager notificationManager =
                    getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }
}

Non dimenticare di dichiarare la tua classe Application nel AndroidManifest.xml:

<application
    android:name=".MyApp"
    ... >

    <!-- resto del manifest -->

</application>

Creare una notifica base con NotificationCompat

NotificationCompat fornisce un’API compatibile con più versioni Android per creare notifiche in modo semplice e affidabile. Di seguito, vedrai un esempio completo in Java che mostra come implementare:

  • icona
  • titolo
  • testo
  • priorità
  • PendingIntent per aprire un’Activity

Esempio: notifica semplice che apre un’Activity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Esempio: invia una notifica quando viene premuto un pulsante
        Button btnNotify = findViewById(R.id.btn_notify);
        btnNotify.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showSimpleNotification();
            }
        });
    }

    private void showSimpleNotification() {
        // 1. Intent che verrà aperto quando l'utente tocca la notifica
        Intent intent = new Intent(this, DetailActivity.class);
        // Cancella lo stack precedente e apre l'Activity come nuova
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

        // 2. Wrappiamo l'Intent in un PendingIntent
        PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                0,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );

        // 3. Costruiamo la notifica con NotificationCompat.Builder
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, MyApp.CHANNEL_ID_MESSAGES)
                .setSmallIcon(R.drawable.ic_notification) // deve essere un'icona vettoriale/bitmap semplice
                .setContentTitle("Nuovo messaggio")
                .setContentText("Hai ricevuto un nuovo messaggio.")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT) // per API < 26
                .setContentIntent(pendingIntent) // azione al tocco
                .setAutoCancel(true); // rimuove la notifica quando viene toccata

        // 4. Mostriamo la notifica tramite NotificationManagerCompat
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

        int notificationId = 1; // ID univoco per aggiornare/cancellare la notifica in futuro
        notificationManager.notify(notificationId, builder.build());
    }
}

In questo esempio, quando l’utente tocca la notifica, viene aperta DetailActivity. Inoltre, l’uso di FLAG_IMMUTABLE è fortemente consigliato nelle versioni moderne di Android per ragioni di sicurezza.

Priorità (pre-Android 8) e importanza del canale (Android 8+)

Prima di Android 8, si utilizzava setPriority() per indicare quanto fosse importante una notifica. Al contrario, con Android 8+, l’importanza è gestita a livello di canale (NotificationChannel).

  • PRIORITÀ (NotificationCompat): PRIORITY_MIN, LOW, DEFAULT, HIGH, MAX.
  • IMPORTANZA (NotificationChannel): IMPORTANCE_MIN, LOW, DEFAULT, HIGH, IMPORTANCE_MAX.

Per garantire compatibilità tra le diverse versioni:

  • Imposta sempre una priorità con setPriority() (per dispositivi < Android 8).
  • Scegli un’importanza appropriata quando crei il canale (per dispositivi Android 8+).

PendingIntent: aprire un’Activity dalla notifica

Un PendingIntent è essenzialmente un “permesso” concesso a un componente di sistema (come il NotificationManager) per eseguire un Intent per conto della tua app in futuro. Per aprire un’Activity, procedi come segue:

Intent intent = new Intent(context, DetailActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

PendingIntent pendingIntent = PendingIntent.getActivity(
        context,
        0,
        intent,
        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);

NotificationCompat.Builder builder = new NotificationCompat.Builder(context, MyApp.CHANNEL_ID_MESSAGES)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle("Titolo")
        .setContentText("Testo della notifica")
        .setContentIntent(pendingIntent)
        .setAutoCancel(true);

Puoi utilizzare getBroadcast() o getService() al posto di getActivity() se desideri che la notifica attivi un BroadcastReceiver Android o un Service; consulta la sezione dedicata agli approfondimenti per ulteriori dettagli.

Notifiche espandibili: BigTextStyle, BigPictureStyle e InboxStyle

Le notifiche espandibili permettono di mostrare più contenuto quando l’utente trascina verso il basso la notifica. In questo senso, Android mette a disposizione diverse style predefinite tramite NotificationCompat.

BigTextStyle: testo lungo

Utilizza BigTextStyle in Android quando devi mostrare una quantità considerevole di testo, come un messaggio lungo o una descrizione dettagliata.

NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle()
        .bigText("Questo è un testo molto più lungo che verrà mostrato quando la notifica viene espansa. Puoi inserire dettagli, descrizioni, istruzioni, ecc.")
        .setBigContentTitle("Dettagli del messaggio")
        .setSummaryText("Messaggi");

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, MyApp.CHANNEL_ID_MESSAGES)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle("Nuovo messaggio")
        .setContentText("Tocca per leggere i dettagli")
        .setStyle(bigTextStyle)
        .setPriority(NotificationCompat.PRIORITY_HIGH);

BigPictureStyle: immagine grande

BigPictureStyle per Android consente, al contrario, di visualizzare una grande immagine quando la notifica viene espansa, ad esempio una foto o un’anteprima di contenuto.

Bitmap bigPicture = BitmapFactory.decodeResource(getResources(), R.drawable.sample_image);

NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle()
        .bigPicture(bigPicture)
        .bigLargeIcon(null); // opzionale: nascondi la large icon quando espanso

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, MyApp.CHANNEL_ID_MESSAGES)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle("Nuova foto disponibile")
        .setContentText("Tocca per visualizzare")
        .setStyle(bigPictureStyle)
        .setLargeIcon(bigPicture)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

InboxStyle: lista di elementi

InboxStyle in Android è ideale per visualizzare una lista di brevi elementi, per esempio più email o messaggi in una conversazione.

NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle()
        .setBigContentTitle("3 nuovi messaggi")
        .addLine("Mario: Ciao!")
        .addLine("Lucia: Hai visto l'aggiornamento?")
        .addLine("Admin: Manutenzione programmata domani")
        .setSummaryText("Chat di gruppo");

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, MyApp.CHANNEL_ID_MESSAGES)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle("Nuovi messaggi")
        .setContentText("Hai 3 nuovi messaggi")
        .setStyle(inboxStyle)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

Inoltre, queste style possono essere combinate con PendingIntent, azioni aggiuntive, suoni personalizzati, e molte altre funzionalità avanzate.

Autorizzazioni per le notifiche (Android 13+)

A partire da Android 13 (API 33), le app devono richiedere all’utente un permesso esplicito per inviare notifiche. Senza questa autorizzazione, le notifiche possono essere silenziate o non visualizzate.

Dichiarare l’autorizzazione nel Manifest

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Richiedere il permesso a runtime

Solo per i dispositivi con API 33+ è necessario richiedere il permesso a runtime (come per la fotocamera o la posizione). In Java, potresti implementare questa logica in un’Activity. Inoltre, la dichiarazione di POST_NOTIFICATIONS nel manifest è essenziale per Android 13+.

private static final int REQUEST_NOTIFICATION_PERMISSION = 1001;

private void requestNotificationPermissionIfNeeded() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
                != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.POST_NOTIFICATIONS},
                    REQUEST_NOTIFICATION_PERMISSION
            );
        }
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == REQUEST_NOTIFICATION_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permesso concesso: ora puoi inviare notifiche
        } else {
            // Permesso negato: valuta di spiegare all'utente l'importanza delle notifiche
        }
    }
}

Una buona pratica consiste nel richiedere il permesso in un momento significativo (ad esempio quando l’utente attiva un’opzione “Ricevi notifiche”), piuttosto che al primo avvio dell’app senza alcun contesto.

Notifiche locali vs notifiche push

È importante distinguere tra notifiche locali e notifiche push, poiché, sebbene entrambe appaiano nello stesso modo all’utente, hanno origini e flussi molto diversi.

Notifiche locali

Le notifiche locali sono create direttamente sul dispositivo dal codice dell’app. Alcuni esempi comuni includono:

  • Promemoria di un’attività impostata dall’utente
  • Conferma che un download è terminato
  • Allarmi generati da un AlarmManager o un WorkManager in background

In questi casi, utilizzi direttamente NotificationCompat.Builder e NotificationManagerCompat, come mostrato negli esempi precedenti; di conseguenza, non hai bisogno di alcun servizio remoto.

Notifiche push da server con Java su Android

Le notifiche push provengono da un server remoto (ad esempio il backend della tua app) e raggiungono il dispositivo tramite un servizio come Firebase Cloud Messaging (FCM). Il flusso tipico è il seguente:

  • Il server invia un messaggio push a FCM
  • FCM recapita il messaggio al dispositivo
  • La tua app riceve il messaggio (di solito in un FirebaseMessagingService)
  • Nel codice di ricezione costruisci una notifica locale con NotificationCompat

In conclusione, anche per le notifiche push, al termine del processo utilizzi lo stesso codice di creazione notifiche descritto in questa guida. La differenza sostanziale risiede nell’origine del trigger (evento locale versus messaggio da server).

Approfondimenti sugli stili e tecniche avanzate

BigTextStyle, BigPictureStyle e InboxStyle a confronto

In questa guida hai acquisito una panoramica rapida di queste tre style. Di seguito, alcune idee per approfondire:

  • Creare una classe helper che accetta parametri (titolo, testo, immagine) e costruisce automaticamente la style corretta.
  • Gestire versioni diverse della stessa notifica (ad esempio solo testo per dispositivi più vecchi, immagine per dispositivi recenti).
  • Aggiungere azioni (bottoni) alle notifiche espandibili, come “Rispondi”, “Segna come letto”.

BroadcastReceiver e gestione delle azioni

I BroadcastReceiver in Android sono comunemente utilizzati per:

  • Ricevere eventi di sistema (es. riavvio del dispositivo) e ricreare promemoria/notifiche pianificate.
  • Ricevere un PendingIntent da una notifica (es. bottone “Annulla” che cancella un download e la relativa notifica).

Per collegare una notifica a un BroadcastReceiver, utilizzerai PendingIntent.getBroadcast() al posto di getActivity():

Intent actionIntent = new Intent(this, NotificationActionReceiver.class);
actionIntent.setAction("ACTION_MARK_AS_READ");

PendingIntent actionPendingIntent = PendingIntent.getBroadcast(
        this,
        0,
        actionIntent,
        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, MyApp.CHANNEL_ID_MESSAGES)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle("Nuovo messaggio")
        .setContentText("Tocca per leggere")
        .addAction(R.drawable.ic_read, "Segna come letto", actionPendingIntent);

Firebase Cloud Messaging (FCM) per notifiche push

Con Firebase Cloud Messaging puoi svolgere le seguenti operazioni:

  • Registrare il dispositivo e ottenere un token univoco.
  • Inviare notifiche o messaggi dati a uno o più dispositivi.
  • Gestire segmenti di utenti, argomenti (topics), programmazioni, ecc.

Nel tuo FirebaseMessagingService, dovrai sovrascrivere onMessageReceived() e da lì invocare la stessa logica di creazione delle notifiche mostrata negli esempi (con NotificationCompat.Builder e NotificationManagerCompat).

Buone pratiche per notifiche efficaci

  • Sii chiaro e conciso: titolo e testo devono spiegare rapidamente cosa è successo.
  • Evita lo spam: troppe notifiche portano l’utente a disattivarle.
  • Usa canali separati: ad esempio “Messaggi”, “Promozioni”, “Aggiornamenti di sistema” per permettere all’utente di personalizzare.
  • Rispetta l’utente: non usare priorità/importanza “alta” senza un buon motivo.
  • Gestisci i casi di riapertura: se l’utente ha già visto il contenuto, magari aggiorna o cancella la notifica.

Riepilogo

In questa guida introduttiva abbiamo esaminato il funzionamento delle notifiche Android con Java, partendo dai concetti fondamentali fino alle notifiche espandibili e alle differenze tra notifiche locali e push. Più specificatamente, hai imparato a:

  • Creare canali di notifica (NotificationChannel) per Android 8+.
  • Costruire notifiche con NotificationCompat.Builder impostando icona, titolo, testo e priorità.
  • Usare PendingIntent per aprire un’Activity o un BroadcastReceiver.
  • Creare notifiche espandibili con BigTextStyle, BigPictureStyle e InboxStyle.
  • Gestire il permesso delle notifiche su Android 13+.
  • Capire la differenza tra notifiche locali e notifiche push tramite FCM.

Da qui in avanti, puoi approfondire creando un NotificationHelper riutilizzabile, integrando Firebase Cloud Messaging per le notifiche push e, soprattutto, progettando una strategia di notifiche che rispetti l’utente e valorizzi la tua applicazione.

Commenti

Lascia un commento