Android-Benachrichtigungen verwenden

Dieses Codelab ist Teil des Kurses „Advanced Android in Kotlin“. Sie profitieren von diesem Kurs, wenn Sie die Codelabs nacheinander durcharbeiten. Das ist aber nicht zwingend erforderlich. Alle Kurs-Codelabs finden Sie auf der Landingpage für Codelabs auf Android-Geräten für Fortgeschrittene.

Einführung

Benachrichtigungen sind Nachrichten, die Nutzern außerhalb der App angezeigt werden. Benachrichtigungen werden oben auf dem Bildschirm angezeigt, wenn das Gerät entsperrt ist. Je nach Sicherheitseinstellungen wird der Sperrbildschirm auf dem Sperrbildschirm angezeigt.

Eine typische Benachrichtigung besteht aus einem Titel, einer Beschreibung und einem Symbol. Eine Benachrichtigung kann auch anklickbare Aktionen, eine schnelle Antwort, erweiterbare Inhalte und Bilder enthalten.

Benachrichtigungen können rechtzeitig versendet werden und über Schaltflächen verfügen, über die Nutzer schnell Aktionen ausführen können, wie etwa als Antwort senden oder die Schlummerfunktion für Wecker aktivieren. Durch Klicken auf eine Benachrichtigung wird der Nutzer zu einer Ansicht in Ihrer App weitergeleitet, in der es um den Benachrichtigungsinhalt geht.

Benachrichtigungen sind eine gute Möglichkeit, um Nutzer an eine wichtige Aufgabe zu erinnern, sie darüber zu informieren oder etwas Wichtiges zu vermitteln, während Ihre App im Hintergrund ausgeführt wird. Sie sollten Benachrichtigungen sparsam verwenden. Dadurch wird nicht nur die Wahrnehmung von Nutzern gewahrt, sondern auch die Wahrscheinlichkeit erhöht, dass ihre Benachrichtigung die Aufmerksamkeit erhält, die sie verdient.

In diesem Codelab lernen Sie, wie Sie Benachrichtigungen in einer Android-App erstellen und verwenden.

Was Sie bereits wissen sollten

Sie sollten mit Folgendem vertraut sein:

  • Android-Apps in Kotlin erstellen Das ist insbesondere mit dem Android SDK möglich.
  • Hier erfahren Sie, wie Sie Anwendungen mithilfe der Architekturkomponenten und der Datenbindung erstellen.
  • Grundlegendes Verständnis von BroadcastReceiver
  • Grundlegendes Verständnis von AlarmManager

Lerninhalte

  • Benachrichtigungen erstellen, gestalten und senden
  • Benachrichtigungen kündigen
  • Benachrichtigungskanäle erstellen
  • Schnellaktionen für Benachrichtigungen hinzufügen
  • Benachrichtigungslogos auf dem App-Symbol anzeigen

Aufgaben

  • Benachrichtigung zur Starter-App hinzufügen
  • Brechen Sie die zuvor gesendete Benachrichtigung ab.
  • Kanäle für verschiedene Arten von Benachrichtigungen erstellen
  • Benutzerdefinierte Benachrichtigungen in der App starten
  • Füge Kurzaktionen hinzu, um deine Benachrichtigung interaktiv zu gestalten.
  • Benachrichtigungslogos deaktivieren

Das Kochen von Eiern ist ganz einfach, aber schwierig, wenn man die Zeit nicht verfolgt. In diesem Codelab arbeitest du an einer Ei-Timer-App und kreiere sie genau wie deine zukünftigen Eier. Du beginnst mit einer funktionierenden Ei-Timer-App, mit der der Nutzer verschiedene Einstellungen für die Kochzeit verschiedener Eierarten festlegen kann. Der Timer zählt vom ausgewählten Zeitintervall ab und zeigt eine Toast-Nachricht an, wenn die Eier bereit sind.

Auf den ersten Blick scheint das sicher zu sein, doch er ist alles andere als perfekt und nicht wirklich nutzerfreundlich. Die Toast-Meldung erscheint anfangs nur für kurze Zeit, sodass sie leicht übersehen werden kann. Wenn sich die App nicht im Vordergrund befindet oder das Gerät gesperrt ist, wird der Timer-Status durch eine visuelle Anzeige nicht mehr angezeigt.

Idealerweise sollten die Eiuhr per Benachrichtigung benachrichtigt werden, wenn die Zeit um ist. Der Nutzer muss sofort wissen, dass die Eier bereit sind. Benachrichtigungen sind gut sichtbar, können Töne enthalten und können das Gerät vibrieren lassen. So kannst du auf jeden Fall die Aufmerksamkeit des Nutzers erregen. So kannst du perfekte Eier und zufriedene Nutzer ernähren.

Sie haben folgende Möglichkeiten, die Beispiel-App abzurufen:

Klonen Sie das Repository aus GitHub und wechseln Sie zum Zweig starter.

$  git clone https://github.com/googlecodelabs/android-kotlin-notifications


Alternativ können Sie das Repository als ZIP-Datei herunterladen, entpacken und in Android Studio öffnen.

Zip herunterladen

  1. Öffne die App und führe sie in Android Studio aus.

Sie sehen ein Ei-Bild und ein Drop-down-Menü mit einer Liste vordefinierter Zeitintervalle, in denen ein Ei zubereitet wird. Klicke auf das Dreieck für das Drop-down-Menü Soft Soiled. Die erste Option in der Liste ist zu Testzwecken gedacht und stellt den Wecker auf nur zehn Sekunden. Neben der Liste befindet sich ein Schalter, der den Ei-Timer startet. Mit diesem Schalter können Sie den Ei-Timer jederzeit starten und stoppen. Der Starter-Code ist voll funktionsfähig. Sie können also den Ei-Timer einrichten und sehen, dass er auf null zurückgesetzt wird. Sobald der Timer abgeschlossen ist, wird eine Toast-Meldung angezeigt, wie unten dargestellt.

  1. Prüfen Sie den Quellcode. Die Starter-App besteht aus einer einzelnen Aktivität namens MainActivity. Es gibt drei Unterpakete namens receiver, ui und util.

  • /empfänger: Das Paket receiver enthält zwei Übertragungsempfänger: AlarmReceiver und SnoozeReceiver. AlarmReceiver wird von AlarmManager ausgelöst, um die Benachrichtigung zu senden, wenn der benutzerdefinierte Timer abgelaufen ist. SnoozeReceiver behandelt den Klick des Nutzers, um die Benachrichtigung zurückzustellen.
  • /ui: Enthält den EggTimerFragment, der Teil der UI der App ist. EggTimerViewModel ist dafür verantwortlich, den Timer zu starten und abzubrechen und andere Lebenszyklus-App-Aufgaben auszuführen.
  • /util: Dieses Paket enthält zwei Dateien. BindingUtils.kt hat Bindungsadapter, um die Datenbindung zwischen der App-UI und der ViewModel zu aktivieren. NotificationUtils.kt hat Erweiterungsmethoden für das NotificationManager.

Benachrichtigungen sind eine gute Möglichkeit, die Aufmerksamkeit der Nutzer auf Ihre App zu lenken. Ob Ihre App nicht im Vordergrund ausgeführt wird oder nicht, stattdessen zeigt eine Benachrichtigung oben im Bildschirm ein Pop-up-Fenster an, das möglicherweise Ton oder Vibrationen enthält. Zum Erstellen einer Benachrichtigung müssen Sie ein Benachrichtigungs-Builder verwenden und einen Titeltext, einen Inhaltstext und ein Symbol angeben. Sobald alle relevanten Felder im Tool erstellt wurden, können Sie mithilfe des Systemdienstes NotificationManager diesen Inhalt anzeigen. NotificationManager ist dafür verantwortlich, eine Benachrichtigung zu senden, deren Inhalt zu aktualisieren und die Benachrichtigung abzubrechen. In den folgenden Schritten fügen Sie die Erweiterungsmethoden in NotificationManager hinzu. So können Sie bei jeder Verwendung von NotificationManager diese Erweiterungsfunktionen verwenden, um die erforderlichen Funktionen zu nutzen.

Schritt 1: Grundlegende Benachrichtigung erstellen

In dieser Aufgabe erstellen Sie eine neue Benachrichtigung, legen eine Nachricht für Ihren Nutzer fest und senden die Benachrichtigung.

  1. Öffnen Sie den Kurs NotificationUtils.kt und suchen Sie nach TODO: Step 1.1. In diesem Codelab und im App-Code finden Sie passende Aufgaben.
  2. Sehen Sie sich die angegebene sendNotification()-Funktion an. Erweitern Sie diese Erweiterungsfunktion auf NotificationManager, um Benachrichtigungen zu senden.
//NotificationUtils.kt
// TODO: Step 1.1 extension function to send messages (GIVEN)
/**
 * Builds and delivers a notification.
 *
 * @param messageBody, notification text.
 * @param context, activity context.
 */
fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
  1. Erstelle eine Instanz des Builders für Benachrichtigungen, übergib den App-Kontext und eine Kanal-ID. Die Kanal-ID ist ein Stringwert für den Kanal.

Über Benachrichtigungskanäle lassen sich Benachrichtigungen gruppieren. Durch die Gruppierung ähnlicher Benachrichtigungen können Entwickler und Nutzer alle Benachrichtigungen im Kanal verwalten. Sobald ein Kanal erstellt wurde, kann er für beliebig viele Benachrichtigungen verwendet werden.

//NotificationUtils.kt
// TODO: Step 1.2 get an instance of NotificationCompat.Builder
val builder = NotificationCompat.Builder(
        applicationContext,
        applicationContext.getString(R.string.egg_notification_channel_id)
)
  1. Legen Sie das Benachrichtigungssymbol fest, das Ihre App, einen Titel und den Inhaltstext für die Mitteilung darstellt, die Sie dem Nutzer vermitteln möchten. Im Codelab sehen Sie weitere Optionen, mit denen Sie Ihre Benachrichtigung weiter anpassen können. Das ist aber die Mindestmenge an Daten, die festgelegt werden muss, bevor eine Benachrichtigung gesendet werden kann.
//NotificationUtils.kt
   // TODO: Step 1.3 set title, text and icon to builder
   .setSmallIcon(R.drawable.cooked_egg)
   .setContentTitle(applicationContext.getString(R.string.notification_title))
   .setContentText(messageBody)
  1. Als Nächstes rufen Sie notify() mit einer eindeutigen ID für die Benachrichtigung und dem Notification-Objekt Ihres Builders auf.

Die ID stellt die aktuelle Benachrichtigungsinstanz dar. Sie wird benötigt, um diese Benachrichtigung zu aktualisieren oder abzubrechen. Da Ihre App immer nur eine aktive Benachrichtigung hat, können Sie für alle Benachrichtigungen dieselbe ID verwenden. Sie haben bereits eine Konstante mit dem Namen NOTIFICATION_ID in NotificationUtils.kt erhalten. Sie können notify() direkt aufrufen, da Sie den Aufruf über eine Erweiterungsfunktion in derselben Klasse ausführen.

//NotificationUtils.kt
   // TODO: Step 1.4 call notify to send the notification
    // Deliver the notification
    notify(NOTIFICATION_ID, builder.build())
  1. Öffne ui/EggTimerViewModel.kt und suche die Funktion startTimer(). Diese Funktion erstellt einen Alarm mit dem ausgewählten Zeitintervall, wenn der Nutzer den Ei-Timer aktiviert.
  2. Sie lösen in dieser Funktion eine Benachrichtigung aus, wenn der Nutzer den Timer startet. Zum Aufrufen der zuvor implementierten Funktion sendNotification() benötigst du eine Instanz von NotificationManager. NotificationManager ist ein Systemdienst, der alle Funktionen bereitstellt, die für die Notifications API verfügbar sind. Dazu gehören auch die von Ihnen hinzugefügten Erweiterungsfunktionen. Wenn Sie eine Benachrichtigung senden, stornieren oder aktualisieren möchten, müssen Sie jederzeit eine Instanz von NotificationManager anfordern. Rufe die Funktion sendNotification()| mit der Benachrichtigung und mit dem Kontext auf.
// EggTimerViewModel.kt
// TODO: Step 1.5 get an instance of NotificationManager 
// and call sendNotification

val notificationManager = ContextCompat.getSystemService(
    app, 
    NotificationManager::class.java
) as NotificationManager
                notificationManager.sendNotification(app.getString(R.string.timer_running), app)

Du hast es fast geschafft. Wenn du deine App jetzt startest und den Timer stellst, erhältst du keine Benachrichtigung.

  1. Öffne logcat und suche nach "No Channel found". Es wird eine Fehlermeldung angezeigt, dass egg_channel nicht vorhanden ist. In den folgenden Schritten erfährst du mehr über Benachrichtigungskanäle und kannst das Problem beheben.

Schritt 2: Benachrichtigungskanäle

Ab API-Level 26 müssen alle Benachrichtigungen einem Kanal zugewiesen werden. Wenn Sie das App Launcher-Symbol berühren und halten, die App-Info auswählen und auf „Benachrichtigungen“ tippen, sehen Sie eine Liste der mit der App verknüpften Benachrichtigungskanäle. Derzeit ist die Liste leer, da für Ihre App keine Kanäle erstellt wurden.

Kanäle stellen eine Art von Benachrichtigung dar. Beispielsweise kann Ihr Ei-Timer eine Benachrichtigung erhalten, wenn das Ei gekocht wird. Über einen anderen Kanal können Sie sich auch täglich mit Erinnerungen benachrichtigen, damit Sie Eier beim Frühstück erhalten. Alle Benachrichtigungen von Channels werden gruppiert und Nutzer können Benachrichtigungseinstellungen für einen gesamten Kanal konfigurieren. So können Nutzer ihre Benachrichtigungseinstellungen personalisieren, indem sie festlegen, welche Benachrichtigungen sie interessieren. Beispielsweise können Nutzer die Frühstücksbenachrichtigungen deaktivieren, aber dennoch die Benachrichtigungen des Timers sehen.

Entwickler legen die Anfangseinstellungen, die Wichtigkeit und das Verhalten auf alle Benachrichtigungen eines Kanals fest. Nachdem Sie die Ersteinstellungen festgelegt haben, können Nutzer die Einstellungen überschreiben.

In Schritt 1.1 hast du egg_notification_channel_id als Benachrichtigungskanal verwendet. Jetzt musst du die Benachrichtigungseinstellungen und das Verhalten dieses Kanals tatsächlich erstellen und anpassen.

  1. Öffne EggTimerFragment.kt und suche die Funktion createChannel().
  2. Übergib die eindeutige Kanal-ID an den Konstruktor von NotificationChannel.
  3. Übergeben Sie den Namen des Benachrichtigungskanals, den Nutzer auch auf dem Bildschirm Einstellungen sehen.
  4. Übergeben Sie als letzten Parameter die Wichtigkeitsstufe für den Benachrichtigungskanal. Die Wichtigkeitsstufen werden später in diesem Codelab behandelt. Bis dahin können Sie also NotificationManager.IMPORTANCE_LOW verwenden.
  5. Setzen Sie für das notificationChannel-Objekt enableLights auf „true“. Bei dieser Einstellung wird das Licht eingeschaltet, wenn eine Benachrichtigung angezeigt wird.
  6. Setzen Sie notificationChannelauf das Objekt lightColor auf Rot, um bei Benachrichtigung ein rotes Licht anzuzeigen.
  7. Setzen Sie für das notificationChannel-Objekt enableVibration auf „true“, um die Vibration zu aktivieren.
  8. Legen Sie für das notificationChannel-Objekt die Kanalbeschreibung auf ‘Time for breakfast' fest.
  9. Rufen Sie eine Instanz von NotificationManager ab, indem Sie getSystemService() aufrufen.
  10. Rufen Sie createNotificationChannel() in NotificationManager auf und übergeben Sie das notificationChannel-Objekt, das Sie im vorherigen Schritt erstellt haben.
//EggTimerFragment.kt
private fun createChannel(channelId: String, channelName: String) {
    // TODO: Step 1.6 START create a channel
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val notificationChannel = NotificationChannel(
            channelId,
            channelName,
            // TODO: Step 2.4 change importance
            NotificationManager.IMPORTANCE_LOW
        )
        // TODO: Step 2.6 disable badges for this channel

        notificationChannel.enableLights(true)
        notificationChannel.lightColor = Color.RED
        notificationChannel.enableVibration(true)
        notificationChannel.description = "Time for breakfast"

        val notificationManager = requireActivity().getSystemService(
            NotificationManager::class.java
        )
        notificationManager.createNotificationChannel(notificationChannel)
    }
    // TODO: Step 1.6 END create channel
}
  1. Der nächste Schritt besteht darin, den Channel createChannel() zu erstellen (Schritt 1.7). Für diese Funktion sind zwei Parameter erforderlich: die Kanal-ID und der Kanalname. Suche nach der Kanal-ID und dem Kanalnamen aus den String-Ressourcen, die bereits in deinem Projekt vorhanden sind.
// EggTimerFragment.kt
    // TODO: Step 1.7 call createChannel
    createChannel(
          getString(R.string.egg_notification_channel_id),
          getString(R.string.egg_notification_channel_name)
    )
  1. Du musst die Kanal-ID an das Builder für Benachrichtigungen übergeben. Dies haben Sie bereits in Schritt 1.2 getan. Wenn Sie einen falschen Wert als Kanal-ID festlegen, schlägt die Benachrichtigung fehl. Öffne NotificationUtils.kt, um zu prüfen, ob die zuvor festgelegte Kanal-ID korrekt ist.
// NotificationUtils.kt
val builder = NotificationCompat.Builder(
        applicationContext,
       // TODO: Step 1.8 verify the notification channel name
        applicationContext.getString(R.string.egg_notification_channel_id)
)
  1. Wenn Sie die App ausführen, erhalten Sie bei jedem Start des Timers eine Benachrichtigung.
  2. Prüfen Sie, ob der Titel, der Inhalt und das Symbol der Benachrichtigung korrekt sind.
  3. Wenn Sie den neu erstellten Kanal bestätigen möchten, schließen Sie die App und suchen Sie das App-Symbol. Lange auf das App-Symbol tippen und App-Info auswählen

  1. Wählen Sie aus der Liste der Einstellungen Benachrichtigungen aus. Direkt unter der Einstellung Benachrichtigungen anzeigen sollte der neue Kanal Ei angezeigt werden.

Wenn Sie die App ausführen, wird die Benachrichtigung angezeigt. Sowohl du als der App-Entwickler als auch deine Nutzer können die Einstellungen und das Verhalten für alle auf diesem Kanal gesendeten Benachrichtigungen anpassen. Glückwunsch, Sie haben eine Benachrichtigung erstellt.

Schritt 3: Benachrichtigungen zu Ihrer App hinzufügen

Bisher wird die grundlegende Verwendung der Notifications API veranschaulicht. Es ist jedoch nicht sinnvoll, eine Benachrichtigung direkt nach dem Starten des Timers zu senden. Nutzer werden lieber benachrichtigt, wenn das Ei bereit ist. Im folgenden Teil des Codelabs beheben Sie das Problem und ändern die Toast-Nachricht zu einer Benachrichtigung.

Sie haben die Benachrichtigung bereits gesendet und beobachtet, wie sie den Nutzern angezeigt wird. Das war aber nur der erste Schritt. In diesem Schritt ändern Sie Ihre Benachrichtigung so, dass sie zu einem besseren Zeitpunkt gesendet wird.

Deine App nutzt AlarmManager, um einen Wecker einzurichten. Der Code für AlarmManager ist bereits im Starter-Code enthalten und wird verwendet, um die Toast-Meldung anzuzeigen. AlarmManager zeichnet die gewünschte Zeitauswahl auf und löst die onReceive()-Funktion von AlarmReceiver.kt aus, wenn die Zeit abgelaufen ist. Wenn Sie AlarmReceiver.kt öffnen und onReceive() aufrufen, sollte die Toast-Meldung angezeigt werden, die jedes Mal angezeigt wird, wenn Sie einen Ei-Timer einrichten.

  1. Öffnen Sie AlarmReceiver.kt als Instanz von NotificationManager und rufen Sie die Funktion sendNotification() mit dem Nachrichtentext und Kontextparametern auf.
// AlarmReceiver.kt
   // TODO: Step 1.9 add call to sendNotification
   val notificationManager = ContextCompat.getSystemService(
       context, 
       NotificationManager::class.java
   ) as NotificationManager
             
   notificationManager.sendNotification(
       context.getText(R.string.eggs_ready).toString(), 
       context
   )
  1. Sie können den Toast auch entfernen, weil Ihre App bei Ablauf des Timers eine Benachrichtigung sendet.
// AlarmReceiver.kt
     // TODO: Step 1.10 [Optional] remove toast
//   Toast.makeText(
//       context, 
//       context.getText(R.string.eggs_ready),
//       Toast.LENGTH_SHORT
//   ).show()
  1. Führe deine App aus . Du solltest jedes Mal eine Benachrichtigung sehen, wenn du den Timer startest oder wenn der Timer abgelaufen ist.

Das ist nicht ideal. Sie möchten nicht zu viele Benachrichtigungen an Nutzer senden. Sie können die erste Benachrichtigung entfernen, die gesendet wird, wenn der Nutzer den Timer startet.

  1. Öffnen Sie EggTimerFragment.kt und entfernen Sie den Benachrichtigungscode für Schritt 1.5.
// EggTimeViewModel.kt

// TODO: Step 1.5 get an instance of NotificationManager 
// and call sendNotification
// val notificationManager = ContextCompat.getSystemService(
//      app,
//      NotificationManager::class.java
// ) as NotificationManager
// notificationManager.sendNotification(app.getString(R.string.eggs_ready), app)
  1. Führen Sie Ihre App noch einmal aus.
  2. Sie können einen Timer stellen, ihn im Hintergrund platzieren und warten, bis er abgeschlossen ist. Eine Benachrichtigung wird angezeigt. Diese Benachrichtigung ist viel nützlicher.

Schritt 4: Intent hinzufügen

  1. Führe die App noch einmal aus, falls sie noch nicht ausgeführt wird.
  2. Klicken Sie auf die Benachrichtigung. Es passiert nichts.

Es ist toll, die Benachrichtigung anzuzeigen und den Nutzer zu informieren. Wenn ein Nutzer jedoch auf eine Benachrichtigung klickt, erwartet er, zur entsprechenden App zurückzukehren. In diesem Teil des Codelabs fügst du deiner Benachrichtigung einen Intent hinzu, um den Nutzer zurück zum Timer-Bildschirm zu bringen.

Ein Intent ist ein Nachrichtenobjekt, mit dem Sie eine Aktion aus einer anderen App-Komponente anfordern können. Intents können zum Starten einer Aktivität, eines Dienstes oder zum Senden einer Übertragung verwendet werden. In diesem Fall teilen Sie dem System mit, dass MainActivity geöffnet werden soll, wenn der Nutzer auf die Benachrichtigung tippt. Da Ihre App nur aus einer einzigen Ansicht besteht, stehen Ihnen hier nicht viele Optionen zur Verfügung. In einer größeren App sollte die Benachrichtigung jedoch ein nahtloses Erlebnis bieten, da der Nutzer auf einen Bildschirm weitergeleitet wird, der für die Interaktion mit der Benachrichtigung sinnvoll ist.

  1. Öffnen Sie NotificationUtils.kt und suchen Sie die Erweiterungsfunktion sendNotification().
  2. Erstelle eine Intent mit deiner applicationContext und der Aktivität, die gestartet werden soll, MainActivity::class.java.
// NotificationUtils.kt

fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
    // Create the content intent for the notification, which launches
    // this activity
   // TODO: Step 1.11 create intent
    val contentIntent = Intent(applicationContext, MainActivity::class.java)

Sie haben den Intent erstellt, aber die Benachrichtigung wird außerhalb Ihrer App angezeigt. Wenn Sie einen Intent außerhalb der App funktionieren möchten, müssen Sie ein neues PendingIntent erstellen.

PendingIntent gewährt einer anderen App oder dem System Rechte, um im Namen Ihrer App einen Vorgang auszuführen. Ein PendingIntent selbst ist einfach ein Verweis auf ein Token, das vom System verwaltet wird und eine Beschreibung der ursprünglichen Daten enthält, mit denen es abgerufen wurde. Das bedeutet, dass die PendingIntent selbst von anderen Prozessen weiterhin verwendet werden kann, selbst wenn der eigene Prozess beendet wird. In diesem Fall verwendet das System den ausstehenden Intent, um die App in Ihrem Namen zu öffnen, unabhängig davon, ob die Timer-App ausgeführt wird oder nicht.

  1. Erstellen Sie eine PendingIntent mit applicationContext, NOTIFICATION_ID, der contentIntent im vorherigen Schritt und dem Flag PendingIntent. Das Flag PendingIntent gibt die Option zum Erstellen eines neuen PendingIntent oder zur Verwendung eines vorhandenen an. Sie müssen PendingIntent.FLAG_UPDATE_CURRENT als Flag festlegen, da Sie keine neue Benachrichtigung erstellen möchten, wenn bereits eine vorhanden ist. Auf diese Weise ändern Sie den aktuellen PendingIntent, der mit dem bereitgestellten Intent verknüpft ist.
// NotificationUtils.kt
   // TODO: Step 1.12 create PendingIntent
    val contentPendingIntent = PendingIntent.getActivity(
        applicationContext, 
        NOTIFICATION_ID,
        contentIntent,
        PendingIntent.FLAG_UPDATE_CURRENT
    )
  1. Gib PendingIntent an deine Benachrichtigung weiter. Rufen Sie dazu setContentIntent() in NotificationBuilder auf. Wenn Sie jetzt auf die Benachrichtigung klicken, wird PendingIntent ausgelöst, wodurch Ihr MainActivity geöffnet wird.
  2. Setzen Sie setAutoCancel() außerdem auf true, damit die Benachrichtigung geschlossen wird, wenn der Nutzer auf die Benachrichtigung tippt.
// NotificationUtils.kt
    // TODO: Step 1.13 set content intent
    .setContentIntent(contentPendingIntent)
    .setAutoCancel(true)
  1. Führen Sie die App noch einmal aus.
  2. Stellen Sie einen Timer ein, platzieren Sie die App im Hintergrund und warten Sie, bis die Benachrichtigung angezeigt wird.
  3. Sobald Sie die Benachrichtigung sehen, können Sie auf die Benachrichtigung klicken, indem Sie die Statusleiste nach unten ziehen. Jetzt sehen Sie, wie die App in den Vordergrund gebracht wird.

Schritt 5: Benachrichtigung stornieren

Sie haben einen funktionsfähigen Ei-Timer mit Benachrichtigungen. Es gibt jedoch ein kleines Problem. Wenn Sie den Timer stellen, eine Benachrichtigung erhalten und den Timer noch einmal stellen, bleibt die vorherige Benachrichtigung in der Statusleiste, während der neue Timer läuft. Das kann für den Nutzer verwirrend sein, wenn die App im Hintergrund ausgeführt wird, was zu ungenauen Eiern führen kann.

Wenn Sie einen neuen Timer starten möchten, müssen Sie die vorherige Benachrichtigung löschen. Erstellen Sie zuerst eine weitere Erweiterungsfunktion in der NotificationUtils.kt. NotificationManager hat eine API, mit der alle aktiven Benachrichtigungen namens cancelAll() abgebrochen werden.

  1. Öffnen Sie NotificationsUtil.kt.
  2. Fügen Sie unter NotificationManager eine Erweiterungsfunktion hinzu, die cancelAll() aufruft.
// NotificationUtils.kt

// TODO: Step 1.14 Cancel all notifications
/**
 * Cancels all notifications.
 *
 */
fun NotificationManager.cancelNotifications() {
    cancelAll()
}
  1. Öffnen Sie EggTimerViewModel.kt und gehen Sie zur Funktion startTimer().
  2. Rufen Sie in startTimer() eine Instanz von NotificationManager aus dem System ab und rufen Sie cancelNotifications() auf.
//  EggTimerViewModel.kt
   //TODO Step 1.15 call cancel notification
    val notificationManager =
       ContextCompat.getSystemService(
            app,
            NotificationManager::class.java
        ) as NotificationManager
    notificationManager.cancelNotifications()       
  1. Führe die App aus und starte den Timer.
  2. Starten Sie den Timer erneut, um zu sehen, wie die vorherige Benachrichtigung automatisch von der Statusleiste gelöscht wird.

Das Benachrichtigungs-Framework bietet eine Vielzahl von Anpassungsoptionen, mit denen Entwickler benutzerdefinierte Aktionen festlegen und ihre Benachrichtigungen nach Bedarf gestalten können. In dieser Aufgabe erfahren Sie, wie Sie die Benachrichtigungen zum Ei-Timer anpassen können.

Schritt 1: Benachrichtigung gestalten

Wenn Sie die Benachrichtigung an die Anforderungen und den Inhalt der Benachrichtigung anpassen, heben sie sich von der Masse ab. Das Benachrichtigungs-Framework umfasst verschiedene integrierte Stile, die Sie verwenden können, und Sie können jederzeit eigene Designs erstellen.

NotificationCompat bietet integrierte Stile für:

  • BigTextStyle, die einen großen Textblock anzeigen können, beispielsweise den Inhalt einer E-Mail, wenn der Text maximiert ist
  • BigPictureStyle, die Benachrichtigungen im großen Format enthalten, die einen großen Bildanhang enthalten
  • InboxStyle mit einem Textinhalt für eine Unterhaltung.
  • MediaStyle zur Steuerung der Medienwiedergabe.
  • MessagingStyle, die Benachrichtigungen im großen Format enthalten, die mehrere Nachrichten von einer beliebigen Person enthalten

In der Dokumentation unter Expandable-Benachrichtigungen erstellen finden Sie Informationen zu weiteren Stilen. In diesem Schritt erstellen Sie mit NotificationCompat.BigPictureStyle eine erweiterbare Benachrichtigung, in der ein großes Ei-Bild angezeigt wird.

  1. Öffne NotificationUtils.kt und suche die Funktion sendNotification().
  2. Lade zuerst ein Bild aus resources mithilfe von BitmapFactory.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
  1. Erstellen Sie eine neue BigPictureStyle und legen Sie das Bild fest.
  2. Setzen Sie bigLargeIcon() auf null, damit das große Symbol ausgeblendet wird, wenn die Benachrichtigung maximiert wird.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
val bigPicStyle = NotificationCompat.BigPictureStyle()
        .bigPicture(eggImage)
        .bigLargeIcon(null)
  1. Setze den Stil mit setStyle() auf bigPicStyle.
  2. Setzen Sie das große Symbol mit setLargeIcon() auf eggImage, damit das Bild beim Minimieren der Benachrichtigung als kleineres Symbol angezeigt wird.
// NotificationUtils.kt
// TODO: Step 2.1 add style to builder
.setStyle(bigPicStyle)
.setLargeIcon(eggImage)
  1. App ausführen und Timer einstellen Wenn die Benachrichtigung zum ersten Mal angezeigt wird, ist sie in der minimierten Benachrichtigungsleiste minimiert. Wenn Sie die Benachrichtigung maximieren, wird im erweiterten Benachrichtigungsbereich ein großes Bild angezeigt.

Schritt 2: Benachrichtigungsaktionen

Benachrichtigungsaktionen sind eine weitere Anpassung, die Sie Ihren Benachrichtigungen hinzufügen können. Ihre Benachrichtigungen werden derzeit an Ihre App weitergeleitet, wenn Nutzer darauf klicken. Zusätzlich zu dieser Standardaktion können Sie Aktionsschaltflächen hinzufügen, mit denen eine App-bezogene Aktion in der Benachrichtigung ausgeführt wird.

Eine Benachrichtigung kann bis zu drei Aktionsschaltflächen enthalten, mit denen der Nutzer schnell reagieren kann. So kann er beispielsweise eine Erinnerung zurückstellen oder auf eine SMS antworten. Durch diese Schaltflächen sollte die Aktion nicht dupliziert werden, auf die der Nutzer auf die Benachrichtigung tippt.

Übergeben Sie ein PendingIntent an die addAction() -Funktion im Builder, um eine Aktionsschaltfläche hinzuzufügen. Das ist wie beim Einrichten der Standard-Touch-Aktion für die Benachrichtigung, indem setContentIntent() aufgerufen wird. Anstatt eine Aktivität zu starten, kannst du verschiedene Aktionen ausführen. So kannst du beispielsweise eine BroadcastReceiver starten, die einen Job im Hintergrund ausführt, sodass die App, die bereits geöffnet ist, nicht unterbrochen wird.

In diesem Codelab haben Sie bereits ein BoadcastReceiver-Objekt mit dem Namen SnoozeReceiver. Sie verwenden SnoozeReceiver, um den Nutzer auf die Benachrichtigungsaktion zu erhalten. In den folgenden Schritten fügen Sie Code hinzu, um die Benachrichtigung zum Ei-Timer 60 Sekunden lang zu pausieren, wenn der Nutzer auf die Schaltfläche zum Zurückstellen der Aktion klickt. Wenn auf die Aktion zum Zurückstellen geklickt wird, erhält die SnoozeReceiver eine Intent und erstellt nach 60 Sekunden einen neuen Wecker, um eine neue Benachrichtigung zu senden.

  1. Öffnen Sie SnoozeReceiver.kt. Dieser Kurs ähnelt dem AlarmReceiver, den Sie zuvor verwendet haben. Mit den folgenden Schritten wird Code hinzugefügt, der die Funktion onReceive() von SnoozeReceiver auslöst. Kurz gesagt: Durch den Code in SnoozeReceiver wird ein neuer Wecker erstellt, um eine Minute später eine neue Benachrichtigung zu senden. Scrollen Sie in der Funktion „onReceive“ nach unten, rufen Sie eine „notificationManager“-Instanz aus und rufen Sie „cancelAll“ auf.
// SnoozeReceiver.kt
        val notificationManager = ContextCompat.getSystemService(
            context,
            NotificationManager::class.java
        ) as NotificationManager
        notificationManager.cancelAll()
  1. Öffnen Sie NotificationUtils.kt, um SnoozeReceiver zu verwenden.
  2. Erstellen Sie eine neue Intent snoozeIntent für die SnoozeReceiver kurz nach dem Stil in der sendNotification()-Funktion.
  3. Erstellen Sie einen ausstehenden Intent, indem Sie die Methode getBroadcast() für PendingIntent aufrufen, die in den folgenden Schritten die Parameter erwartet. PendingIntent verwendet das System, um nach 60 Sekunden eine neue Benachrichtigung einzurichten, damit der Nutzer eine neue Benachrichtigung senden kann, wenn er auf die Schlummertaste klickt.
  4. Der erste Parameter ist der Anwendungskontext, in dem dieser PendingIntent die Aktivität starten soll.
  5. Der zweite Parameter ist der Anfragecode, d. h. der Anfragecode für diesen ausstehenden Intent. Wenn Sie diesen ausstehenden Intent aktualisieren oder abbrechen möchten, müssen Sie mit diesem Code auf den ausstehenden Intent zugreifen.
  6. Als Nächstes fügen Sie das Objekt snoozeIntent hinzu. Dies ist der Zweck der Aktivität, die gestartet werden soll.
  7. Fügen Sie schließlich den Flag-Wert #FLAG_ONE_SHOT hinzu, da der Intent nur einmal verwendet wird. Die Schnellaktion und die Benachrichtigung verschwinden nach dem ersten Antippen, weshalb der Intent nur einmal verwendet werden kann.
// NotificationUtils.kt

// TODO: Step 2.2 add snooze action
val snoozeIntent = Intent(applicationContext, SnoozeReceiver::class.java)
val snoozePendingIntent: PendingIntent = PendingIntent.getBroadcast(
    applicationContext, 
    REQUEST_CODE, 
    snoozeIntent, 
    FLAGS
)
  1. Rufen Sie als Nächstes die Funktion addAction() für notificationBuilder auf. Diese Funktion erwartet ein Symbol und einen Text, um deine Aktion dem Nutzer zu beschreiben. Sie müssen auch die snoozeIntent hinzufügen. Dieser Intent wird verwendet, um den richtigen boadcastReceiver auszulösen, wenn auf Ihre Aktion geklickt wird.
// NotificationUtils.kt
// TODO: Step 2.3 add snooze action
.addAction(
    R.drawable.egg_icon, 
    applicationContext.getString(R.string.snooze),
    snoozePendingIntent
)
  1. Führe die Ei-Timer-App aus, um die Schlummerfunktion zu testen.
  2. Den Timer ausführen und die App im Hintergrund platzieren Wenn der Timer abgelaufen ist, maximieren Sie die Benachrichtigung. Die Benachrichtigung enthält jetzt eine Schaltfläche zum Zurückstellen der Eieruhr.

Schritt 3: Wichtigkeit der Benachrichtigung

Die Wichtigkeit legt fest, wie stark die Benachrichtigung den Nutzer visuell und akustisch unterbrechen soll. Benachrichtigungen mit höherer Wichtigkeit sind für den Nutzer störender.

Sie müssen die Wichtigkeitsstufe im NotificationChannel-Konstruktor angeben. Du hast ursprünglich eine niedrige Wichtigkeit für die Ei-Timer-App festgelegt. Du kannst eine von fünf Wichtigkeitsstufen auswählen, von IMPORTANCE_NONE(0) bis IMPORTANCE_HIGH(4). Die Wichtigkeitsstufe, die du einem Kanal zuweist, gilt für alle Benachrichtigungen, die du auf diesem Kanal postest.

Wichtigkeitsstufen von Kanälen

Für Nutzer sichtbare Wichtigkeitsstufe

Wichtigkeit (Android 8.0 und höher)

Priorität (Android 7.1 und niedriger)

akustische Signale, die als „Vorsicht“-Benachrichtigung angezeigt werden (am oberen Rand des Bildschirms)

IMPORTANCE_HIGH

PRIORITY_HIGH / PRIORITY_MAX

Hat einen Ton

IMPORTANCE_STANDARD

PRIORITY_STANDARD

Kein Ton

IMPORTANCE_LOW

PRIORITY_LOW

Kein Ton und erscheint nicht in der Statusleiste

IMPORTANCE_MIN.

PRIORITY_MIN

Informationen zur Auswahl einer passenden Prioritätsstufe finden Sie im Leitfaden zum Erstellen von Benachrichtigungen. Du solltest vorsichtig sein, wenn du eine Wichtigkeitsstufe für die Benachrichtigungen in deiner App auswählst. Die Wichtigkeit des Kanals sollte unter Berücksichtigung der Zeit und Aufmerksamkeit des Nutzers ausgewählt werden. Wenn eine unwichtige Benachrichtigung als dringend getarnt ist, kann dies zu unnötigem Alarm führen und ablenken. Die Nutzer bestimmen selbst, wie wichtig Benachrichtigungen sind. Wenn du also eine lästige Benachrichtigung erstellst, kann sie deinen Benachrichtigungskanal vollständig deaktivieren.

Als Sie die Benachrichtigung in Schritt 1.6 erstellt haben, wurde der Ei-Timer so eingerichtet, dass Benachrichtigungen mit niedriger Priorität gesendet werden, da er Nutzer mit Benachrichtigungen nicht stören soll. Es kann jedoch sinnvoll sein, die Aufmerksamkeit des Nutzers zu erhalten, bevor das Ei zu kochen. Wenn du die Wichtigkeitsstufe der Benachrichtigung ändern möchtest, beginne mit den Kanaleinstellungen. Die Wichtigkeit eines Kanals wirkt sich auf die Unterbrechungsstufe aller Benachrichtigungen aus, die auf dem Kanal gepostet werden. Sie muss im NotificationChannel-Konstruktor angegeben werden.

  1. Wenn du die Wichtigkeitsstufe deiner Benachrichtigungskanal ändern möchtest, öffne EggTimerFragment.kt und rufe createChannel() auf. Ändern Sie die Wichtigkeitsstufe von IMPORTANCE_LOW in IMPORTANCE_HIGH.
// EggTimerFragment.kt
    val notificationChannel = NotificationChannel(
        channelId,
        channelName,
        // TODO: Step 2.4 change importance
        NotificationManager.IMPORTANCE_HIGH
    )

Um Geräte mit Android 7.1 (API-Level 25) oder niedriger zu unterstützen, müssen Sie auch setPriority() für jede Benachrichtigung mit einer Prioritätskonstante aus der NotificationCompat-Klasse aufrufen.

  1. Öffnen Sie NotificationUtils.kt und fügen Sie dem Benachrichtigungs-Builder-Objekt das folgende hinzu.
// NotificationUtils.kt
   .addAction(
       R.drawable.common_google_signin_btn_icon_dark,
       applicationContext.getString(R.string.snooze),
       snoozePendingIntent
    )
   // TODO: Step 2.5 set priority
    .setPriority(NotificationCompat.PRIORITY_HIGH)
  1. Bevor Sie die App ausführen, müssen Sie auf Ihrem Gerät oder Emulator lange auf das App-Symbol klicken und „Deinstallieren“ auswählen, um die vorherigen Kanaleinstellungen zu löschen. Wenn du die App nicht deinstallierst, werden die Einstellungen für die Kanalpriorität nicht geändert. Dadurch ändert sich auch das Verhalten der Benachrichtigung nicht.
  2. Führe die App noch einmal aus und starte den Timer. Bei der Übermittlung der Benachrichtigung sollte dieses Mal ein Pop-up oben auf dem Bildschirm angezeigt werden, unabhängig davon, ob Ihre App im Vordergrund oder im Hintergrund ausgeführt wird.

Schritt 4: Benachrichtigungslogos

Benachrichtigungslogos sind kleine Punkte, die auf dem Launcher-Symbol der verknüpften App angezeigt werden, wenn die App eine aktive Benachrichtigung hat. Drücken Sie lange auf das App-Symbol, um die Benachrichtigungen aufzurufen.

Diese Punkte, sogenannte Logos, werden standardmäßig angezeigt. Sie brauchen nichts weiter zu tun. Aber es gibt Situationen, in denen Logos keine Benachrichtigungen ergeben. Wenn du möchtest, kannst du sie für einzelne Kanäle deaktivieren. Rufe dazu setShowBadge(false) in deinem NotificationChannel-Objekt auf. Da die Ei-Timer jeweils nur eine aktive Benachrichtigung haben, zeigt das Logo auf Ihrem App-Symbol Ihren Nutzern keinen großen Vorteil. In den folgenden Schritten wird das Logo deaktiviert und es wird nur eine Benachrichtigung für den Ei-Timer angezeigt.

  1. Füge setShowBadge(false) zum Kanalerstellungscode für den Ei-Timer hinzu, um Logos zu deaktivieren.
// EggTimerFragment.kt

    ).apply {
        // TODO: Step 2.6 disable badges for this channel
        setShowBadge(false)
    }
  1. Führe die App noch einmal aus, starte den Timer und sieh dir das App-Symbol an. Es sollten keine Logos auf dem App-Symbol angezeigt werden.

Der Lösungscode befindet sich im Master-Branch des heruntergeladenen Codes.

Udacity-Kurs:

Android-Entwicklerdokumentation:

Links zu weiteren Codelabs in diesem Kurs finden Sie auf der Landingpage des erweiterten Android-Tools in Kotlin.