Tworzenie powiadomienia

Powiadomienia dostarczają krótkie i aktualne informacje o zdarzeniach w aplikacji, gdy nie jest ona używana. W tym dokumencie opisujemy, jak utworzyć powiadomienie z różnymi funkcjami. Wstępne informacje o tym, jak powiadomienia wyświetlają się na Androidzie, znajdziesz w omówieniu powiadomień. Przykładowy kod, który korzysta z powiadomień, znajdziesz na tej stronie na GitHubie.

Kod na tej stronie korzysta z interfejsów API NotificationCompat z biblioteki AndroidX. Pozwalają dodawać funkcje dostępne tylko w nowszych wersjach Androida, zachowując zgodność z Androidem 9 (poziom API 28). Jednak niektóre funkcje, takie jak działanie wbudowanej odpowiedzi, we wcześniejszych wersjach nie będą działać.

Dodawanie biblioteki AndroidX Core

Choć większość projektów tworzonych za pomocą Android Studio zawiera zależności wymagane do korzystania z NotificationCompat, sprawdź, czy plik build.gradle na poziomie modułu zawiera tę zależność:

Odlotowy

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

Kotlin

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

Tworzenie podstawowego powiadomienia

W najbardziej podstawowej i kompaktowej formie powiadomienia (nazywanej też zwiniętym) wyświetla się ikona, tytuł i niewielką ilość tekstu. Z tej sekcji dowiesz się, jak utworzyć powiadomienie, które użytkownik może kliknąć, aby uruchomić działanie w aplikacji.

Rysunek 1. Powiadomienie z ikoną, tytułem i tekstem.

Więcej informacji o poszczególnych częściach powiadomień znajdziesz w artykule na temat anatomii powiadomień.

Deklarowanie uprawnień w czasie działania

Android 13 (poziom interfejsu API 33) i nowsze obsługują uprawnienia w czasie działania do publikowania niewykluczonych (w tym usług działających na pierwszym planie) powiadomień z aplikacji.

Uprawnienia, które musisz zadeklarować w pliku manifestu aplikacji, znajdziesz w tym fragmencie kodu:

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

Więcej informacji o uprawnieniach w czasie działania znajdziesz w artykule Uprawnienia czasu działania powiadomień.

Ustawianie treści powiadomień

Zacznij od ustawienia treści i kanału powiadomienia za pomocą obiektu NotificationCompat.Builder. Z przykładu poniżej dowiesz się, jak utworzyć powiadomienie o:

  • Niewielka ikona ustawiona przez setSmallIcon(). To jedyna wymagana treść widoczna dla użytkownika.

  • Tytuł ustawiony przez zasadę setContentTitle().

  • Tekst główny ustawiony przez zasadę setContentText().

  • Priorytet powiadomień ustawiony przez zasadę setPriority(). Priorytet określa, jak uciążliwe jest powiadomienie w Androidzie 7.1 i starszych. W przypadku Androida 8.0 i nowszych ustaw znaczenie kanału w sposób podany w następnej sekcji.

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);

Konstruktor NotificationCompat.Builder wymaga podania identyfikatora kanału. Jest to wymagane do zapewnienia zgodności z Androidem 8.0 (poziom interfejsu API 26) i nowszymi wersjami, ale jest ignorowane we wcześniejszych wersjach.

Domyślnie tekst powiadomienia jest przycinany tak, aby mieścił się w jednym wierszu. Dodatkowe informacje można wyświetlić, tworząc powiadomienie rozwijane.

Rysunek 2. Rozwijane powiadomienie w zwiniętej i rozwiniętej postaci.

Jeśli chcesz, aby powiadomienie było dłuższe, możesz je włączyć, dodając szablon stylu w polu setStyle(). Na przykład ten kod tworzy większy obszar tekstowy:

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);

Więcej informacji o innych dużych stylach powiadomień, w tym o tym, jak dodać obraz i elementy sterujące odtwarzaniem multimediów, znajdziesz w artykule Tworzenie rozwijalnego powiadomienia.

Utwórz kanał i określ, jak ważny jest Twój kanał

Zanim będzie można dostarczyć powiadomienie na Androidzie 8.0 i nowszych, zarejestruj w systemie kanał powiadomień swojej aplikacji, przekazując wystąpienie NotificationChannel do createNotificationChannel(). Ten kod jest blokowany przez warunek w wersji 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);
    }
}

W Androidzie 8.0 i nowszych wersjach przed opublikowaniem jakichkolwiek powiadomień musisz utworzyć kanał powiadomień, dlatego ten kod należy uruchamiać od razu po uruchomieniu aplikacji. Najlepiej jest wywoływać tę funkcję wielokrotnie, bo utworzenie istniejącego kanału powiadomień nie powoduje wykonania żadnej operacji.

Konstruktor NotificationChannel wymaga importance, używając jednej ze stałych klasy NotificationManager. Ten parametr określa, w jaki sposób przerywać działanie użytkownika w odpowiedzi na dowolne powiadomienie należące do tego kanału. Ustaw priorytet za pomocą atrybutu setPriority(), aby umożliwić obsługę Androida 7.1 i starszych wersji, jak pokazano w poprzednim przykładzie.

Musisz ustawić ważność lub priorytet powiadomień zgodnie z poniższym przykładem, ale system nie gwarantuje, że otrzymasz alert. W niektórych przypadkach system może zmienić poziom ważności na podstawie innych czynników, a użytkownik może w każdej chwili zmienić definicję poziomu ważności dla danego kanału.

Więcej informacji o znaczeniu poszczególnych poziomów znajdziesz w artykule o poziomach ważności powiadomień.

Ustaw kliknięcie powiadomienia

Każde powiadomienie musi zareagować na kliknięcie. Zwykle powoduje to otwarcie aktywności w aplikacji powiązanej z powiadomieniem. Aby to zrobić, określ intencję treści zdefiniowaną za pomocą obiektu PendingIntent i przekaż ją do setContentIntent().

Ten fragment kodu pokazuje, jak utworzyć podstawową intencję, która otwiera działanie, gdy użytkownik kliknie powiadomienie:

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);

Ten kod wywołuje metodę setAutoCancel(), która automatycznie usuwa powiadomienie, gdy użytkownik go kliknie.

Wskazana w poprzednim przykładzie metoda setFlags() zachowuje oczekiwane wrażenia z nawigacji użytkownika po otwarciu aplikacji za pomocą powiadomienia. Może Ci się przydać w zależności od typu rozpoczynanej aktywności – może to być jedna z tych opcji:

  • Działanie, które występuje tylko w przypadku odpowiadania na powiadomienie. Nie ma powodu, dla którego użytkownik przechodzi do tej aktywności podczas normalnego używania aplikacji, więc uruchomi ona nowe zadanie, a nie zostanie dodana do istniejącego stosu zadań i cofania aplikacji. To jest typ intencji utworzonej w poprzedniej próbce.

  • Aktywność występująca w ramach zwykłego przepływu pracy aplikacji. W tym przypadku uruchomienie działania spowoduje utworzenie stosu wstecznego, dzięki czemu zostaną zachowane oczekiwania użytkownika dotyczące przycisków Kopia zapasowa i w górę.

Więcej informacji o różnych sposobach konfigurowania intencji powiadomienia znajdziesz w artykule o rozpoczynaniu działania z poziomu powiadomienia.

Wyświetlanie powiadomienia

Aby powiadomienie się pojawiło, wywołaj metodę NotificationManagerCompat.notify() i przekaż mu unikalny identyfikator powiadomienia oraz wynik działania NotificationCompat.Builder.build(). Widać to w tym przykładzie:

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())
}

Zapisz identyfikator powiadomienia, który przekazujesz do usługi NotificationManagerCompat.notify(), ponieważ będzie on potrzebny, gdy zechcesz zaktualizować lub usunąć powiadomienie.

Dodatkowo, aby przetestować podstawowe powiadomienia na urządzeniach z Androidem 13 lub nowszym, włącz powiadomienia ręcznie lub utwórz okno do wysyłania próśb o powiadomienia.

Dodaj przyciski poleceń

Powiadomienie może zawierać maksymalnie 3 przyciski polecenia, które pozwalają użytkownikowi szybko odpowiedzieć, np. odłożyć przypomnienie lub odpowiedzieć na SMS-a. Przyciski czynności nie mogą jednak powielać działania wykonanego, gdy użytkownik kliknie powiadomienie.

Rysunek 3. powiadomienie z jednym przyciskiem polecenia.

Aby dodać przycisk polecenia, przekaż znak PendingIntent do metody addAction(). Przypomina to konfigurowanie domyślnego działania kliknięcia w powiadomieniu. Jednak zamiast uruchamiać aktywność, możesz wykonać inne czynności, np. uruchomić BroadcastReceiver, który wykonuje zadanie w tle, tak aby działanie nie zakłócało już otwartej aplikacji.

Na przykład ten kod pokazuje, jak wysłać transmisję do określonego odbiornika:

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);

Więcej informacji o tworzeniu BroadcastReceiver w celu uruchamiania pracy w tle znajdziesz w artykule o transmisjach.

Jeśli zamiast tego próbujesz utworzyć powiadomienie z przyciskami odtwarzania multimediów, np. zatrzymywać i pomijać utwory, dowiedz się, jak utworzyć powiadomienie z elementami sterującymi multimediami.

Dodaj działanie polegające na bezpośredniej odpowiedzi

Wprowadzona w Androidzie 7.0 (poziom interfejsu API 24) funkcja odpowiedzi bezpośredniej umożliwia użytkownikom wpisywanie tekstu bezpośrednio w powiadomieniu. Następnie tekst jest dostarczany do aplikacji bez otwierania aktywności. W ten sposób możesz na przykład umożliwić użytkownikom odpowiadanie na SMS-y i aktualizowanie listy zadań z poziomu powiadomienia.

Rysunek 4. Dotknięcie przycisku „Odpowiedz” otwiera pole tekstowe.

Odpowiedź bezpośrednia wyświetla się jako dodatkowy przycisk w powiadomieniu otwierającym pole tekstowe. Gdy użytkownik skończy pisać, system dołączy odpowiedź tekstową do intencji, którą określisz dla działania powiadomienia, i wyśle intencję do aplikacji.

Dodaj przycisk odpowiedzi

Aby utworzyć działanie związane z powiadomieniem, które obsługuje bezpośrednią odpowiedź, wykonaj te czynności:

  1. Utwórz instancję RemoteInput.Builder, którą możesz dodać do działania związanego z powiadomieniami. Konstruktor tej klasy akceptuje ciąg znaków, którego system używa jako klucza do wprowadzania tekstu. Aplikacja używa później tego klucza do pobrania tekstu wejściowego.

    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. Utwórz PendingIntent dla odpowiedzi.

    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. Dołącz obiekt RemoteInput do działania za pomocą 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. Zastosuj działanie do powiadomienia i wyślij powiadomienie.

    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);
      

System prosi użytkownika o podanie odpowiedzi, gdy aktywuje działanie związane z powiadomieniem, jak pokazano na rysunku 4.

Pobierz dane wejściowe użytkownika z odpowiedzi

Aby odbierać odpowiedzi użytkownika z interfejsu odpowiedzi powiadomienia, wywołaj metodę RemoteInput.getResultsFromIntent() i przekaż mu kod Intent odebrany przez 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;
 }

Po przetworzeniu tekstu zaktualizuj powiadomienie, wywołując NotificationManagerCompat.notify() z tym samym identyfikatorem i tagiem (jeśli jest używany). Konieczne jest ukrycie interfejsu bezpośredniej odpowiedzi i potwierdzenie użytkownikowi, że jego odpowiedź jest prawidłowo odbierana i przetwarzana.

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);

Podczas pracy z nowym powiadomieniem używaj kontekstu przekazanego do metody onReceive() odbiorcy.

Dołącz odpowiedź u dołu powiadomienia, dzwoniąc pod numer setRemoteInputHistory(). Jeśli jednak tworzysz aplikację do obsługi wiadomości, utwórz powiadomienie w stylu wiadomości i dołącz do rozmowy nową wiadomość.

Więcej wskazówek dotyczących powiadomień z komunikatorów znajdziesz w sekcji poświęconej sprawdzonych metodach korzystania z aplikacji do obsługi wiadomości.

Dodaj pasek postępu

Powiadomienia mogą zawierać animowany wskaźnik postępu, który pokazuje użytkownikom stan trwającej operacji.

Rysunek 5. Pasek postępu w trakcie operacji.

Jeśli możesz oszacować, jaka część operacji została ukończona, użyj wskaźnika „determinate” (określonego) (jak pokazano na rysunku 5), wywołując metodę setProgress(max, progress, false). Pierwszy parametr to wartość „complete”, np. 100. Po drugie, stopień ukończenia. Ostatnia wskazuje, że jest to określony pasek postępu.

W miarę postępów operacji wywoływaj stale funkcję setProgress(max, progress, false) ze zaktualizowaną wartością dla progress i ponownie wysyłaj powiadomienie, jak pokazano w poniższym przykładzie.

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());

Na końcu operacji progress musi mieć wartość max. Możesz opuścić pasek postępu, aby wyświetlić informację o zakończeniu operacji, lub ją usunąć. W obu przypadkach zaktualizuj tekst powiadomienia, aby wskazać, że operacja została zakończona. Aby usunąć pasek postępu, wywołaj setProgress(0, 0, false).

Aby wyświetlić pasek postępu z nieokreślonym natężeniem (który nie wskazuje procentu ukończenia), wywołaj funkcję setProgress(0, 0, true). Wynik to wskaźnik, który ma ten sam styl co poprzedni pasek postępu, ale jest to animacja ciągła, która nie wskazuje zakończenia. Animacja postępu działa, dopóki nie wywołasz funkcji setProgress(0, 0, false), a następnie zaktualizujesz powiadomienie, aby usunąć wskaźnik aktywności.

Pamiętaj, aby zmienić tekst powiadomienia informujący o zakończeniu operacji.

Ustawianie kategorii systemowej

Android używa zdefiniowanych wstępnie kategorii obowiązujących w całym systemie do określania, czy przeszkadzać użytkownikowi dane powiadomienie, gdy włączy on tryb Nie przeszkadzać.

Jeśli Twoje powiadomienie należy do jednej z kategorii powiadomień zdefiniowanych w NotificationCompat, np. do CATEGORY_ALARM, CATEGORY_REMINDER, CATEGORY_EVENT lub CATEGORY_CALL, zadeklaruj je, przesyłając odpowiednią kategorię tutaj: 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);

System wykorzystuje te informacje o kategorii powiadomień do podjęcia decyzji o wyświetlaniu powiadomienia, gdy urządzenie jest w trybie Nie przeszkadzać. Nie musisz jednak ustawiać kategorii w całym systemie. Korzystaj z tej opcji tylko wtedy, gdy powiadomienia pasują do jednej z kategorii zdefiniowanych w zasadzie NotificationCompat.

Pokaż pilną wiadomość

Aplikacja może pokazywać pilną, pilną wiadomość, np. o nadchodzącym połączeniu telefonicznym lub dzwonku. W takich sytuacjach z powiadomieniem możesz powiązać intencję pełnoekranową.

Po wywołaniu powiadomienia użytkownicy zobaczą jedną z tych opcji w zależności od stanu blokady urządzenia:

  • Jeśli urządzenie użytkownika jest zablokowane, pojawi się aktywność na pełnym ekranie zasłaniająca ekran blokady.
  • Jeśli urządzenie użytkownika jest odblokowane, powiadomienie wyświetla się w rozwiniętej postaci i zawiera opcje obsługi lub zamknięcia powiadomienia.

Ten fragment kodu pokazuje, jak powiązać powiadomienie z intencją pełnoekranowym:

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);

Ustawianie widoczności ekranu blokady

Aby określić poziom szczegółowości powiadomienia na ekranie blokady, wywołaj metodę setVisibility() i określ jedną z tych wartości:

  • VISIBILITY_PUBLIC: pełna treść powiadomienia będzie widoczna na ekranie blokady.

  • VISIBILITY_SECRET: na ekranie blokady nie wyświetla się żadna część powiadomienia.

  • VISIBILITY_PRIVATE: na ekranie blokady wyświetlają się tylko podstawowe informacje, takie jak ikona powiadomienia i tytuł treści. Powiadomienie nie zawiera pełnej treści.

Gdy ustawisz VISIBILITY_PRIVATE, możesz też podać alternatywną wersję treści powiadomienia, która ukrywa pewne szczegóły. Na przykład aplikacja do obsługi SMS-ów może wyświetlać powiadomienie „Masz 3 nowe SMS-y”, ale ukrywa treść wiadomości i nadawców. Aby udostępnić to powiadomienie alternatywne, najpierw w zwykły sposób utwórz alternatywne powiadomienie w usłudze NotificationCompat.Builder. Następnie załącz alternatywne powiadomienie do zwykłego powiadomienia za pomocą setPublicVersion().

Pamiętaj, że użytkownik zawsze ma pełną kontrolę nad tym, czy jego powiadomienia mają być widoczne na ekranie blokady, oraz może je kontrolować za pomocą kanałów powiadomień aplikacji.

Aktualizowanie powiadomienia

Aby zaktualizować powiadomienie po jego wysłaniu, wywołaj ponownie zdarzenie NotificationManagerCompat.notify() i przekaż mu ten sam identyfikator, który został użyty wcześniej. Jeżeli poprzednie powiadomienie zostanie odrzucone, zostanie utworzone nowe powiadomienie.

Opcjonalnie możesz wywołać setOnlyAlertOnce(), aby powiadomienie zakłócało użytkownika (dźwiękiem, wibracjami lub wskazówkami wizualnymi) tylko przy pierwszym wyświetleniu powiadomienia, a nie w przypadku późniejszej aktualizacji.

Usuwanie powiadomienia

Powiadomienia pozostają widoczne do momentu, gdy wystąpi jedno z tych zdarzeń:

  • użytkownik odrzuca powiadomienie.
  • Użytkownik klika powiadomienie, jeśli podczas tworzenia powiadomienia wywołasz metodę setAutoCancel().
  • Wywołujesz metodę cancel(), aby podać konkretny identyfikator powiadomienia. Ta metoda usuwa również bieżące powiadomienia.
  • Wywołujesz metodę cancelAll(), co powoduje usunięcie wszystkich wcześniej wysłanych powiadomień.
  • Określony czas trwania, jeśli podczas tworzenia powiadomienia ustawisz limit czasu w metodzie setTimeoutAfter(). W razie potrzeby możesz anulować powiadomienie, zanim upłynie określony czas oczekiwania.

Sprawdzone metody dotyczące aplikacji do obsługi wiadomości

Podczas tworzenia powiadomień w aplikacjach do obsługi wiadomości i czatu weź pod uwagę wymienione tu sprawdzone metody.

Używanie MessagingStyle

Od Androida 7.0 (poziom interfejsu API 24) Android udostępnia szablon stylu powiadomień dotyczący treści wiadomości. Korzystając z klasy NotificationCompat.MessagingStyle, możesz zmienić niektóre etykiety wyświetlane w powiadomieniu, w tym tytuł wątku, dodatkowe wiadomości oraz widok treści powiadomienia.

Poniższy fragment kodu pokazuje, jak dostosować styl powiadomienia za pomocą klasy 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();

Od Androida 9.0 (poziom interfejsu API 28) wymagane jest też używanie klasy Person, aby optymalnie renderować powiadomienie i jego awatary.

Jeśli używasz NotificationCompat.MessagingStyle, wykonaj te czynności:

  • Zadzwoń pod numer MessagingStyle.setConversationTitle(), aby ustawić tytuł czatów grupowych z więcej niż 2 osobami. Dobrym tytułem rozmowy może być nazwa czatu grupowego lub lista uczestników rozmowy, jeśli nie ma ona nazwy. Bez niego wiadomość może zostać błędnie uznana za należącą do rozmowy 1:1 z nadawcą najnowszej wiadomości w danym wątku.
  • Aby uwzględnić wiadomości multimedialne, takie jak obrazy, użyj metody MessagingStyle.setData(). Obsługiwane są typy MIME obrazu/* wzorca.

Użyj bezpośredniej odpowiedzi

Bezpośrednia odpowiedź pozwala użytkownikowi odpowiedzieć bezpośrednio na wiadomość.

  • Gdy użytkownik odpowie przy użyciu wbudowanej odpowiedzi, zaktualizuj powiadomienie MessagingStyle za pomocą polecenia MessagingStyle.addMessage(). Nie wycofuj ani nie anuluj powiadomienia. Jeśli użytkownik nie anuluje powiadomienia, będzie mógł wysłać wiele odpowiedzi.
  • Aby działanie odpowiedzi w tekście było zgodne z Wear OS, wywołaj metodę Action.WearableExtender.setHintDisplayInlineAction(true).
  • Użyj metody addHistoricMessage(), aby nadać kontekst rozmowie z bezpośrednią odpowiedzią przez dodanie do powiadomienia wiadomości historycznych.

Włącz Inteligentną odpowiedź

  • Aby włączyć Inteligentną odpowiedź, zadzwoń pod numer setAllowGeneratedResponses(true) jako odpowiedź. Dzięki temu odpowiedzi Inteligentnej odpowiedzi są dostępne dla użytkowników, gdy powiadomienie jest połączone z urządzeniem z Wear OS. Odpowiedzi Inteligentnej odpowiedzi są generowane przez model systemów uczących się, który jest w pełni aktywny, z użyciem kontekstu podanego w powiadomieniu NotificationCompat.MessagingStyle. Do internetu nie są przesyłane żadne dane umożliwiające wygenerowanie tych odpowiedzi.

Dodaj metadane powiadomień