Crea una notifica

Le notifiche forniscono informazioni brevi e tempestive sugli eventi nella tua app quando non è in uso. Questo documento mostra come creare una notifica con varie funzionalità. Per un'introduzione alla visualizzazione delle notifiche su Android, consulta la Panoramica delle notifiche. Per il codice di esempio che utilizza le notifiche, consulta l'esempio Persone su GitHub.

Il codice in questa pagina utilizza le API NotificationCompat della libreria AndroidX. Queste API ti consentono di aggiungere funzionalità disponibili solo su versioni più recenti di Android, garantendo al contempo la compatibilità con Android 9 (livello API 28). Tuttavia, alcune funzionalità, come l'azione di risposta in linea, non hanno alcun effetto nelle versioni precedenti.

Aggiungi la libreria di base AndroidX

Sebbene la maggior parte dei progetti creati con Android Studio includa le dipendenze necessarie per utilizzare NotificationCompat, verifica che il file NotificationCompat a livello di modulo includa la seguente dipendenza:build.gradle

Alla moda

dependencies {
    implementation "androidx.core:core:2.2.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-ktx:2.2.0")
}

Crea una notifica di base

Una notifica nella sua forma più semplice e compatta, nota anche come forma collapse, mostra un'icona, un titolo e una piccola quantità di contenuti di testo. Questa sezione mostra come creare una notifica che l'utente può toccare per avviare un'attività nella tua app.

Figura 1. Una notifica con un'icona, un titolo e del testo.

Per ulteriori dettagli su ogni parte di una notifica, leggi l'articolo sulla anatomia delle notifiche.

Dichiara l'autorizzazione di runtime

Android 13 (livello API 33) e versioni successive supporta un'autorizzazione di runtime per la pubblicazione di notifiche non esenti (inclusi i servizi in primo piano (FGS)) da un'app.

L'autorizzazione che devi dichiarare nel file manifest della tua app viene visualizzata nel seguente snippet di codice:

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

Per ulteriori dettagli sulle autorizzazioni di runtime, vedi Autorizzazione di runtime per le notifiche.

Impostare i contenuti della notifica

Per iniziare, imposta i contenuti e il canale della notifica utilizzando un oggetto NotificationCompat.Builder. L'esempio seguente mostra come creare una notifica con:

  • Un'icona piccola, impostata da setSmallIcon(). Si tratta degli unici contenuti visibili all'utente richiesti.

  • Un titolo impostato da setContentTitle().

  • Il corpo del testo, impostato da setContentText().

  • La priorità della notifica, impostata da setPriority(). La priorità determina quanto è invadente la notifica su Android 7.1 e versioni precedenti. Per Android 8.0 e versioni successive, imposta invece l'importanza del canale come mostrato nella prossima sezione.

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

Il costruttore NotificationCompat.Builder richiede di fornire un ID canale. Questo è necessario per la compatibilità con Android 8.0 (livello API 26) e versioni successive, ma viene ignorato dalle versioni precedenti.

Per impostazione predefinita, i contenuti di testo della notifica vengono troncati per adattarsi a una riga. Puoi mostrare informazioni aggiuntive creando una notifica espandibile.

Figura 2. Una notifica espandibile nella sua forma compressa ed espansa.

Se vuoi che la notifica sia più lunga, puoi attivare una notifica espandibile aggiungendo un modello di stile con setStyle(). Ad esempio, il seguente codice crea un'area di testo più grande:

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(new NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

Per ulteriori informazioni su altri stili di notifica di grandi dimensioni, incluso come aggiungere un'immagine e i controlli di riproduzione dei contenuti multimediali, consulta la sezione Creare una notifica espandibile.

Creare un canale e stabilire l'importanza

Prima di poter inviare la notifica su Android 8.0 e versioni successive, registra il canale di notifica della tua app con il sistema trasmettendo un'istanza di NotificationChannel a createNotificationChannel(). Il seguente codice è bloccato da una condizione nella versione SDK_INT:

Kotlin

private fun createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = getString(R.string.channel_name)
        val descriptionText = getString(R.string.channel_description)
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
            description = descriptionText
        }
        // Register the channel with the system.
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

Java

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this.
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

Poiché devi creare il canale di notifica prima di pubblicare qualsiasi notifica su Android 8.0 e versioni successive, esegui questo codice non appena l'app viene avviata. Puoi richiamare questo numero più volte, in quanto la creazione di un canale di notifica esistente non esegue alcuna operazione.

Il costruttore NotificationChannel richiede un importance, utilizzando una delle costanti della classe NotificationManager. Questo parametro determina come interrompere l'utente per qualsiasi notifica appartenente a questo canale. Imposta la priorità con setPriority() per supportare Android 7.1 e versioni precedenti, come mostrato nell'esempio precedente.

Sebbene sia necessario impostare l'importanza o la priorità delle notifiche come mostrato nell'esempio riportato di seguito, il sistema non garantisce il comportamento degli avvisi che ottieni. In alcuni casi, il sistema potrebbe modificare il livello di importanza in base ad altri fattori e l'utente può sempre ridefinire il livello di importanza per un determinato canale.

Per saperne di più sul significato dei diversi livelli, consulta la sezione relativa ai livelli di importanza delle notifiche.

Impostare l'azione di tocco della notifica

Ogni notifica deve rispondere a un tocco, in genere per aprire un'attività nell'app corrispondente alla notifica. A questo scopo, specifica un intent di contenuto definito con un oggetto PendingIntent e passalo a setContentIntent().

Lo snippet seguente mostra come creare un intent di base per aprire un'attività quando l'utente tocca la notifica:

Kotlin

// Create an explicit intent for an Activity in your app.
val intent = Intent(this, AlertDetails::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)

val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)

Java

// Create an explicit intent for an Activity in your app.
Intent intent = new Intent(this, AlertDetails.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true);

Questo codice chiama setAutoCancel(), che rimuove automaticamente la notifica quando l'utente la tocca.

Il metodo setFlags() mostrato nell'esempio precedente preserva l'esperienza di navigazione prevista dell'utente dopo l'apertura dell'app tramite la notifica. Ti consigliamo di utilizzarlo in base al tipo di attività che stai avviando, che può essere una delle seguenti:

  • Un'attività esistente esclusivamente per le risposte alla notifica. Non c'è motivo per cui l'utente acceda a questa attività durante il normale utilizzo dell'app, quindi l'attività avvia una nuova attività anziché essere aggiunta all'attività e alla pila di ritorno esistenti dell'app. Si tratta del tipo di intent creato nell'esempio precedente.

  • Un'attività esistente nel normale flusso dell'app. In questo caso, l'avvio dell'attività crea una pila di ritorno in modo che le aspettative dell'utente per i pulsanti Indietro e Backup siano conservate.

Per saperne di più sui diversi modi per configurare l'intent della notifica, consulta Avvia un'attività da una notifica.

Mostra la notifica

Per visualizzare la notifica, chiama NotificationManagerCompat.notify(), trasmettendo un ID univoco per la notifica e il risultato di NotificationCompat.Builder.build(). Ciò è mostrato nell'esempio seguente:

Kotlin

with(NotificationManagerCompat.from(this)) {
    if (ActivityCompat.checkSelfPermission(
            this@MainActivity,
            Manifest.permission.POST_NOTIFICATIONS
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        // TODO: Consider calling
        // ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        // public fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
        //                                        grantResults: IntArray)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.

        return@with
    }
    // notificationId is a unique int for each notification that you must define.
    notify(NOTIFICATION_ID, builder.build())
}

Java

with(NotificationManagerCompat.from(this)) {
   if (ActivityCompat.checkSelfPermission(
           this@MainActivity,
           Manifest.permission.POST_NOTIFICATIONS
       ) != PackageManager.PERMISSION_GRANTED
   ) {
       // TODO: Consider calling
       // ActivityCompat#requestPermissions
       // here to request the missing permissions, and then overriding
       // public void onRequestPermissionsResult(int requestCode, String[] permissions,
       //                                        int[] grantResults)
       // to handle the case where the user grants the permission. See the documentation
       // for ActivityCompat#requestPermissions for more details.

       return
   }
   // notificationId is a unique int for each notification that you must define.
   notify(NOTIFICATION_ID, builder.build())
}

Salva l'ID notifica che trasmetti a NotificationManagerCompat.notify(), perché ti serve per aggiornare o rimuovere la notifica.

Inoltre, per testare le notifiche di base sui dispositivi con Android 13 e versioni successive, attiva le notifiche manualmente o crea una finestra di dialogo per richiederle.

Aggiungere pulsanti di azione

Una notifica può offrire fino a tre pulsanti di azione che consentono all'utente di rispondere rapidamente, ad esempio per posticipare un promemoria o per rispondere a un messaggio. Tuttavia, questi pulsanti di azione non devono duplicare l'azione eseguita quando l'utente tocca la notifica.

Figura 3. Una notifica con un pulsante di azione.

Per aggiungere un pulsante di azione, passa un PendingIntent al metodo addAction(). È come configurare l'azione di tocco predefinita per la notifica, ma invece di avviare un'attività, puoi svolgere altre operazioni, ad esempio avviare una BroadcastReceiver che esegue un job in background in modo che l'azione non interrompa l'app già aperta.

Ad esempio, il seguente codice mostra come inviare una trasmissione a un ricevitore specifico:

Kotlin

val ACTION_SNOOZE = "snooze"

val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {
    action = ACTION_SNOOZE
    putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val snoozePendingIntent: PendingIntent =
    PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent)

Java

String ACTION_SNOOZE = "snooze"

Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(ACTION_SNOOZE);
snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
PendingIntent snoozePendingIntent =
        PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent);

Per ulteriori informazioni sulla creazione di un BroadcastReceiver per eseguire il lavoro in background, consulta la Panoramica delle trasmissioni.

Se invece stai cercando di creare una notifica con i pulsanti di riproduzione dei contenuti multimediali, ad esempio per mettere in pausa e saltare i brani, scopri come creare una notifica con i controlli multimediali.

Aggiungere un'azione di risposta diretta

L'azione di risposta diretta, introdotta in Android 7.0 (livello API 24), consente agli utenti di inserire il testo direttamente nella notifica. Il testo viene quindi inviato all'app senza aprire un'attività. Ad esempio, puoi utilizzare un'azione di risposta diretta per consentire agli utenti di rispondere ai messaggi o aggiornare gli elenchi di attività dalla notifica.

Figura 4. Toccando il pulsante "Rispondi" si apre l'inserimento di testo.

L'azione di risposta diretta viene visualizzata come pulsante aggiuntivo nella notifica che apre un input di testo. Quando l'utente termina di digitare, il sistema associa la risposta di testo all'intent specificato per l'azione di notifica e invia l'intent alla tua app.

Aggiungere il pulsante Rispondi

Per creare un'azione di notifica che supporti la risposta diretta:

  1. Crea un'istanza di RemoteInput.Builder che puoi aggiungere all'azione di notifica. Il costruttore di questa classe accetta una stringa utilizzata dal sistema come chiave per l'input di testo. In un secondo momento, l'app userà questa chiave per recuperare il testo dell'input.

    Kotlin

      // Key for the string that's delivered in the action's intent.
      private val KEY_TEXT_REPLY = "key_text_reply"
      var replyLabel: String = resources.getString(R.string.reply_label)
      var remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {
          setLabel(replyLabel)
          build()
      }
      

    Java

      // Key for the string that's delivered in the action's intent.
      private static final String KEY_TEXT_REPLY = "key_text_reply";
    
      String replyLabel = getResources().getString(R.string.reply_label);
      RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
              .setLabel(replyLabel)
              .build();
      
  2. Crea un PendingIntent per l'azione di risposta.

    Kotlin

      // Build a PendingIntent for the reply action to trigger.
      var replyPendingIntent: PendingIntent =
          PendingIntent.getBroadcast(applicationContext,
              conversation.getConversationId(),
              getMessageReplyIntent(conversation.getConversationId()),
              PendingIntent.FLAG_UPDATE_CURRENT)
      

    Java

      // Build a PendingIntent for the reply action to trigger.
      PendingIntent replyPendingIntent =
              PendingIntent.getBroadcast(getApplicationContext(),
                      conversation.getConversationId(),
                      getMessageReplyIntent(conversation.getConversationId()),
                      PendingIntent.FLAG_UPDATE_CURRENT);
      
  3. Collega l'oggetto RemoteInput a un'azione utilizzando addRemoteInput().

    Kotlin

      // Create the reply action and add the remote input.
      var action: NotificationCompat.Action =
          NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
              getString(R.string.label), replyPendingIntent)
              .addRemoteInput(remoteInput)
              .build()
      

    Java

      // Create the reply action and add the remote input.
      NotificationCompat.Action action =
              new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
                      getString(R.string.label), replyPendingIntent)
                      .addRemoteInput(remoteInput)
                      .build();
      
  4. Applica l'azione a una notifica ed emettila.

    Kotlin

      // Build the notification and add the action.
      val newMessageNotification = Notification.Builder(context, CHANNEL_ID)
              .setSmallIcon(R.drawable.ic_message)
              .setContentTitle(getString(R.string.title))
              .setContentText(getString(R.string.content))
              .addAction(action)
              .build()
    
      // Issue the notification.
      with(NotificationManagerCompat.from(this)) {
          notificationManager.notify(notificationId, newMessageNotification)
      }
      

    Java

      // Build the notification and add the action.
      Notification newMessageNotification = new Notification.Builder(context, CHANNEL_ID)
              .setSmallIcon(R.drawable.ic_message)
              .setContentTitle(getString(R.string.title))
              .setContentText(getString(R.string.content))
              .addAction(action)
              .build();
    
      // Issue the notification.
      NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
      notificationManager.notify(notificationId, newMessageNotification);
      

Il sistema chiede all'utente di inserire una risposta quando attiva l'azione di notifica, come mostrato nella figura 4.

Recupera l'input dell'utente dalla risposta

Per ricevere l'input dell'utente dall'interfaccia utente per la risposta alla notifica, chiama RemoteInput.getResultsFromIntent(), trasmettendo il valore Intent ricevuto dal tuo BroadcastReceiver:

Kotlin

private fun getMessageText(intent: Intent): CharSequence? {
    return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)
}

Java

private CharSequence getMessageText(Intent intent) {
    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
    if (remoteInput != null) {
        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
    }
    return null;
 }

Dopo aver elaborato il testo, aggiorna la notifica chiamando NotificationManagerCompat.notify() con lo stesso ID e tag, se utilizzati. Questo è necessario per nascondere l'interfaccia utente della risposta diretta e confermare all'utente che la sua risposta è stata ricevuta ed elaborata correttamente.

Kotlin

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
val repliedNotification = Notification.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_message)
        .setContentText(getString(R.string.replied))
        .build()

// Issue the new notification.
NotificationManagerCompat.from(this).apply {
    notificationManager.notify(notificationId, repliedNotification)
}

Java

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
Notification repliedNotification = new Notification.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_message)
        .setContentText(getString(R.string.replied))
        .build();

// Issue the new notification.
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, repliedNotification);

Quando utilizzi questa nuova notifica, utilizza il contesto passato al metodo onReceive() del destinatario.

Aggiungi la risposta alla parte inferiore della notifica chiamando setRemoteInputHistory(). Tuttavia, se stai creando un'app di messaggistica, crea una notifica in stile messaggistica e aggiungi il nuovo messaggio alla conversazione.

Per ulteriori consigli sulle notifiche da un'app di messaggistica, consulta la sezione sulle best practice per le app di messaggistica.

Aggiungere una barra di avanzamento

Le notifiche possono includere un indicatore di avanzamento animato che mostra agli utenti lo stato di un'operazione in corso.

Figura 5. La barra di avanzamento durante un'operazione.

Se puoi stimare in qualsiasi momento la percentuale di completamento dell'operazione, utilizza la forma "determinata" dell'indicatore, come mostrato nella figura 5, chiamando setProgress(max, progress, false). Il primo parametro è il valore di "complete", ad esempio 100. Il secondo è quanto è completato. L'ultimo indica che si tratta di una determinata barra di avanzamento.

Man mano che l'operazione procede, chiama continuamente setProgress(max, progress, false) con un valore aggiornato per progress e emetti di nuovo la notifica, come mostrato nell'esempio seguente.

Kotlin

val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
    setContentTitle("Picture Download")
    setContentText("Download in progress")
    setSmallIcon(R.drawable.ic_notification)
    setPriority(NotificationCompat.PRIORITY_LOW)
}
val PROGRESS_MAX = 100
val PROGRESS_CURRENT = 0
NotificationManagerCompat.from(this).apply {
    // Issue the initial notification with zero progress.
    builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
    notify(notificationId, builder.build())

    // Do the job that tracks the progress here.
    // Usually, this is in a worker thread.
    // To show progress, update PROGRESS_CURRENT and update the notification with:
    // builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
    // notificationManager.notify(notificationId, builder.build());

    // When done, update the notification once more to remove the progress bar.
    builder.setContentText("Download complete")
            .setProgress(0, 0, false)
    notify(notificationId, builder.build())
}

Java

...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setContentTitle("Picture Download")
        .setContentText("Download in progress")
        .setSmallIcon(R.drawable.ic_notification)
        .setPriority(NotificationCompat.PRIORITY_LOW);

// Issue the initial notification with zero progress.
int PROGRESS_MAX = 100;
int PROGRESS_CURRENT = 0;
builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
notificationManager.notify(notificationId, builder.build());

// Do the job that tracks the progress here.
// Usually, this is in a worker thread.
// To show progress, update PROGRESS_CURRENT and update the notification with:
// builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
// notificationManager.notify(notificationId, builder.build());

// When done, update the notification once more to remove the progress bar.
builder.setContentText("Download complete")
        .setProgress(0,0,false);
notificationManager.notify(notificationId, builder.build());

Al termine dell'operazione, progress deve essere uguale a max. Puoi lasciare la barra di avanzamento per indicare che l'operazione è stata completata o rimuoverla. In entrambi i casi, aggiorna il testo della notifica per indicare che l'operazione è stata completata. Per rimuovere la barra di avanzamento, chiama setProgress(0, 0, false).

Per visualizzare una barra di avanzamento indeterminata (una barra che non indica la percentuale di completamento), chiama setProgress(0, 0, true). Il risultato è un indicatore che ha lo stesso stile della barra di avanzamento precedente, tranne per il fatto che si tratta di un'animazione continua che non indica il completamento. L'animazione di avanzamento viene eseguita fino a quando non chiami setProgress(0, 0, false) e poi aggiorni la notifica per rimuovere l'indicatore di attività.

Ricordati di modificare il testo della notifica per indicare che l'operazione è completata.

Impostare una categoria a livello di sistema

Android utilizza categorie predefinite a livello di sistema per determinare se disturbare l'utente con una determinata notifica quando l'utente attiva la modalità Non disturbare.

Se la notifica rientra in una delle categorie di notifica definite in NotificationCompat, ad esempio CATEGORY_ALARM, CATEGORY_REMINDER, CATEGORY_EVENT o CATEGORY_CALL, dichiarala come tale passando la categoria appropriata a setCategory():

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE);

Il sistema utilizza queste informazioni relative alla categoria di notifica per prendere decisioni in merito alla visualizzazione della notifica quando sul dispositivo è attiva la modalità Non disturbare. Tuttavia, non è necessario impostare una categoria a livello di sistema. Procedi solo se le notifiche corrispondono a una delle categorie definite in NotificationCompat.

Mostra un messaggio urgente

L'app potrebbe dover mostrare un messaggio urgente e urgente, ad esempio una chiamata in arrivo o una sveglia che suona. In queste situazioni, puoi associare un intento a schermo intero alla notifica.

Quando viene richiamata la notifica, gli utenti visualizzano una delle seguenti opzioni, a seconda dello stato di blocco del dispositivo:

  • Se il dispositivo dell'utente è bloccato, viene visualizzata un'attività a schermo intero che copre la schermata di blocco.
  • Se il dispositivo dell'utente è sbloccato, la notifica viene visualizzata in un formato espanso che include opzioni per gestirla o ignorarla.

Il seguente snippet di codice mostra come associare la notifica a un intento a schermo intero:

Kotlin

val fullScreenIntent = Intent(this, ImportantActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
    fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true)

Java

Intent fullScreenIntent = new Intent(this, ImportantActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
        fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true);

Impostare la visibilità della schermata di blocco

Per controllare il livello di dettaglio visibile nella notifica dalla schermata di blocco, chiama setVisibility() e specifica uno dei seguenti valori:

  • VISIBILITY_PUBLIC: i contenuti completi della notifica vengono visualizzati sulla schermata di blocco.

  • VISIBILITY_SECRET: nessuna parte della notifica viene visualizzata sulla schermata di blocco.

  • VISIBILITY_PRIVATE: sulla schermata di blocco vengono visualizzate solo le informazioni di base, come l'icona della notifica e il titolo dei contenuti. I contenuti completi della notifica non vengono visualizzati.

Quando imposti VISIBILITY_PRIVATE, puoi anche fornire una versione alternativa dei contenuti della notifica che nasconde determinati dettagli. Ad esempio, un'app di messaggistica potrebbe mostrare una notifica che indica "Hai 3 nuovi messaggi", ma nasconde i contenuti e i mittenti dei messaggi. Per fornire questa notifica alternativa, crea prima la notifica alternativa con NotificationCompat.Builder come di consueto. Quindi, allega la notifica alternativa alla notifica normale con setPublicVersion().

Tieni presente che l'utente ha sempre il controllo finale sulla visibilità delle notifiche nella schermata di blocco e può controllarle in base ai canali di notifica della tua app.

Aggiornare una notifica

Per aggiornare una notifica dopo averla emessa, chiama nuovamente NotificationManagerCompat.notify() passando lo stesso ID utilizzato in precedenza. Se la notifica precedente viene ignorata, viene creata una nuova notifica.

Facoltativamente, puoi chiamare setOnlyAlertOnce() in modo che la notifica interrompa l'utente con suono, vibrazione o indizi visivi solo la prima volta che viene visualizzata la notifica, non per aggiornamenti successivi.

Rimuovere una notifica

Le notifiche rimangono visibili fino a quando si verifica una delle seguenti condizioni:

  • L'utente ignora la notifica.
  • L'utente tocca la notifica, se chiami il numero setAutoCancel() quando crei la notifica.
  • Chiami cancel() per un ID notifica specifico. Questo metodo elimina anche le notifiche in corso.
  • Chiami cancelAll(), che rimuove tutte le notifiche che hai emesso in precedenza.
  • Se imposti un timeout durante la creazione della notifica, utilizzando setTimeoutAfter(), la durata specificata scade. Se necessario, puoi annullare una notifica prima che scada la durata del tempo di attesa specificato.

Best practice per le app di messaggistica

Tieni presenti le best practice elencate qui quando crei notifiche per le tue app di messaggistica e chat.

Utilizzare MessagingStyle

A partire da Android 7.0 (livello API 24), Android fornisce un modello di stile di notifica specifico per i contenuti di messaggistica. Utilizzando la classe NotificationCompat.MessagingStyle, puoi modificare diverse etichette visualizzate nella notifica, tra cui il titolo della conversazione, i messaggi aggiuntivi e la visualizzazione del contenuto della notifica.

Il seguente snippet di codice mostra come personalizzare lo stile di una notifica utilizzando la classe MessagingStyle.

Kotlin

val user = Person.Builder()
    .setIcon(userIcon)
    .setName(userName)
    .build()

val notification = NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("2 new messages with $sender")
    .setContentText(subject)
    .setSmallIcon(R.drawable.new_message)
    .setStyle(NotificationCompat.MessagingStyle(user)
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
        .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
    )
    .build()

Java

Person user = new Person.Builder()
    .setIcon(userIcon)
    .setName(userName)
    .build();

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("2 new messages with " + sender)
    .setContentText(subject)
    .setSmallIcon(R.drawable.new_message)
    .setStyle(new NotificationCompat.MessagingStyle(user)
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
        .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
    )
    .build();

A partire da Android 9.0 (livello API 28), è inoltre necessario utilizzare la classe Person per ottenere un rendering ottimale della notifica e dei suoi avatar.

Quando usi NotificationCompat.MessagingStyle, segui questi passaggi:

  • Chiamate MessagingStyle.setConversationTitle() per impostare un titolo per le chat di gruppo con più di due persone. Un buon titolo per una conversazione potrebbe essere il nome della chat di gruppo o, se non ha un nome, un elenco dei partecipanti alla conversazione. In caso contrario, il messaggio potrebbe essere scambiato per appartenente a una conversazione privata con il mittente del messaggio più recente nella conversazione.
  • Utilizza il metodo MessagingStyle.setData() per includere messaggi multimediali come le immagini. I tipi MIME del pattern image/* sono supportati.

Usa la risposta diretta

La risposta diretta consente a un utente di rispondere a un messaggio in linea.

  • Dopo che un utente risponde con l'azione di risposta in linea, utilizza MessagingStyle.addMessage() per aggiornare la notifica MessagingStyle e non ritirarla o annullarla. Se non annulli la notifica, l'utente può inviare più risposte dalla notifica.
  • Per rendere l'azione di risposta in linea compatibile con Wear OS, chiama Action.WearableExtender.setHintDisplayInlineAction(true).
  • Utilizza il metodo addHistoricMessage() per fornire il contesto a una conversazione con risposta diretta aggiungendo messaggi storici alla notifica.

Attivare la funzionalità Risposta rapida

  • Per attivare Risposta rapida, chiama setAllowGeneratedResponses(true) nell'azione di risposta. In questo modo le risposte di Risposta rapida sono disponibili per gli utenti quando la notifica è collegata a un dispositivo Wear OS. Le risposte di Risposta intelligente vengono generate da un modello di machine learning completamente on-watch che utilizza il contesto fornito dalla notifica NotificationCompat.MessagingStyle e nessun dato viene caricato su internet per generare le risposte.

Aggiungi metadati delle notifiche