Dieses Codelab ist Teil des Kurses „Advanced Android in Kotlin“. Sie können den größten Nutzen aus diesem Kurs ziehen, wenn Sie die Codelabs der Reihe nach durcharbeiten. Das ist jedoch nicht zwingend erforderlich. Alle Codelabs des Kurses sind auf der Landingpage für Codelabs zu „Android für Fortgeschrittene mit Kotlin“ aufgeführt.
Einführung
Benachrichtigungen sind Nachrichten, die dem Nutzer außerhalb der Benutzeroberfläche Ihrer App angezeigt werden. Benachrichtigungen werden oben auf dem Display angezeigt, wenn das Gerät entsperrt ist. Je nach Sicherheitseinstellungen werden sie auch auf dem Sperrbildschirm angezeigt, wenn das Gerät gesperrt ist.
Eine typische Benachrichtigung besteht aus einem Titel, einer Beschreibung und einem Symbol. Eine Benachrichtigung kann auch anklickbare Aktionen, eine Schnellantwort, erweiterbare Inhalte und Bilder enthalten.
Benachrichtigungen können zeitnah Informationen liefern und Schaltflächen enthalten, über die Nutzer Schnellaktionen ausführen können, z. B. eine Antwort senden oder einen Wecker zurückstellen. Wenn ein Nutzer auf eine Benachrichtigung klickt, wird er zu einer Ansicht in Ihrer App weitergeleitet, die sich auf den Inhalt der Benachrichtigung bezieht.
Benachrichtigungen sind eine gute Möglichkeit, Nutzer an eine wichtige Aufgabe zu erinnern, sie über ein Ereignis zu informieren oder ihnen wichtige Informationen mitzuteilen, die sie sofort benötigen, während Ihre App im Hintergrund ausgeführt wird. Verwenden Sie Benachrichtigungen sparsam. Das ist nicht nur respektvoll gegenüber den Nutzern, sondern erhöht auch die Wahrscheinlichkeit, dass die Benachrichtigung Ihrer App die Aufmerksamkeit erhält, die sie verdient.
In diesem Codelab erfahren 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 Insbesondere mit dem Android SDK.
- Apps mit Architekturkomponenten und Datenbindung entwickeln
- Grundlegendes Verständnis von BroadcastReceivers
- Grundlegendes Verständnis von AlarmManager
Lerninhalte
- So erstellen, gestalten und senden Sie eine Benachrichtigung.
- Benachrichtigungen deaktivieren
- Benachrichtigungskanäle erstellen
- So fügen Sie Benachrichtigungen Schnellaktionen hinzu.
- So werden Benachrichtigungsbadges auf dem App-Symbol angezeigt.
Aufgaben
- Fügen Sie der Starter-App eine Benachrichtigung hinzu.
- Die zuvor gesendete Benachrichtigung abbrechen.
- Kanäle für verschiedene Arten von Benachrichtigungen erstellen
- Passen Sie die Benachrichtigungen in der Starter-App an.
- Fügen Sie Schnellaktionen hinzu, um Ihre Benachrichtigung interaktiv zu gestalten.
- Deaktivieren Sie Benachrichtigungskennzeichen.
Eier zu kochen ist einfach, kann aber schwierig werden, wenn Sie die Zeit nicht im Blick behalten. In diesem Codelab arbeiten Sie an einer Eieruhr-App und machen sie perfekt – genau wie Ihre zukünftigen Eier. Sie beginnen mit einer funktionierenden Eieruhr-App, mit der der Nutzer verschiedene Garzeit-Einstellungen für verschiedene Eierarten festlegen kann. Der Timer zählt das ausgewählte Zeitintervall herunter und zeigt eine Benachrichtigung an, wenn die Eier fertig sind.
Das mag zwar funktionieren, ist aber alles andere als perfekt und nicht wirklich nutzerfreundlich. Die Benachrichtigung wird nur kurz angezeigt und kann daher leicht übersehen werden. Wenn die App nicht im Vordergrund ist oder das Gerät gesperrt ist, gibt es nach dem Verschwinden der Benachrichtigung keine visuelle Anzeige für den Status des Timers.
Idealerweise sollte der Eieruhr-Skill Benachrichtigungen verwenden, um Nutzer darüber zu informieren, wenn die Zeit abgelaufen ist. Der Nutzer muss wirklich wissen, dass die Eier sofort fertig sind, da sie sonst zu lange gekocht werden. Benachrichtigungen sind visuell, können Töne enthalten und das Gerät kann vibrieren – alles Möglichkeiten, die Aufmerksamkeit des Nutzers zu erregen. So können Sie perfekte Eier zubereiten und zufriedene, gut genährte Nutzer erreichen.
Sie haben folgende Möglichkeiten, die Beispiel-App zu erhalten:
Klonen Sie das Repository von 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, entzippen und in Android Studio öffnen.
- Öffnen Sie die App in Android Studio und führen Sie sie aus.
Sie sehen ein Bild eines Eis und ein Drop-down-Menü mit einer Liste vordefinierter Zeitintervalle zum Kochen eines Eis. Klicken Sie auf das Dreieck für das Drop-down-Menü Weichgekocht. Die erste Option in der Liste dient zu Testzwecken und stellt den Alarm auf nur 10 Sekunden ein. Neben der Liste befindet sich ein Schalter, mit dem der Eieruhr-Timer gestartet wird. Mit diesem Schalter können Sie den Eieruhr-Timer jederzeit starten und stoppen. Der Startercode ist voll funktionsfähig. Sie können also den Eieruhr-Timer einstellen und beobachten, wie er bis auf 0 herunterzählt. Wenn der Timer abgelaufen ist, wird eine Benachrichtigung wie unten dargestellt angezeigt.
- Quellcode prüfen Die Starter-App besteht aus einer einzelnen Aktivität mit dem Namen
MainActivity
. Es gibt drei Unterpakete mit den Namenreceiver
,ui
undutil
.
- /receiver: Das
receiver
-Paket enthält zwei Broadcast-Empfänger mit den NamenAlarmReceiver
undSnoozeReceiver
.AlarmReceiver
wird vonAlarmManager
ausgelöst, um die Benachrichtigung zu senden, wenn der benutzerdefinierte Timer abgelaufen ist.SnoozeReceiver
verarbeitet den Nutzerklick zum Schlummern der Benachrichtigung. - /ui: Dieses Verzeichnis enthält
EggTimerFragment
, das Teil der Benutzeroberfläche der App ist.EggTimerViewModel
ist für das Starten und Abbrechen des Timers sowie für andere App-Aufgaben im Zusammenhang mit dem Lebenszyklus verantwortlich. - /util: Dieses Paket enthält zwei Dateien.
BindingUtils.kt
hat Bindungsadapter, um die Datenbindung zwischen der App-Benutzeroberfläche undViewModel
zu ermöglichen.NotificationUtils.kt
hat Erweiterungsmethoden fürNotificationManager
.
Benachrichtigungen sind eine gute Möglichkeit, die Aufmerksamkeit der Nutzer auf Ihre App zu lenken. Unabhängig davon, ob Ihre App nicht ausgeführt wird oder im Vordergrund ausgeführt wird, wird durch eine Benachrichtigung ein Pop-up-Fenster oben auf dem Bildschirm angezeigt, das möglicherweise einen Ton oder eine Vibration enthält. Zum Erstellen einer Benachrichtigung benötigen Sie einen Benachrichtigungs-Builder sowie einen Titeltext, einen Inhaltstext und ein Symbol. Sobald der Builder alle erforderlichen Felder enthält, hilft Ihnen NotificationManager
, ein Systemdienst, dabei, diesen Inhalt als Benachrichtigung anzuzeigen. NotificationManager
ist für das Senden einer Benachrichtigung, das Aktualisieren des Inhalts und das Abbrechen der Benachrichtigung verantwortlich. In den folgenden Schritten fügen Sie NotificationManager
Erweiterungsmethoden hinzu. So können Sie jedes Mal, wenn Sie NotificationManager
verwenden müssen, diese Erweiterungsfunktionen nutzen, um die benötigte Funktionalität zu erhalten.
Schritt 1: Einfache Benachrichtigung erstellen
In dieser Aufgabe erstellen Sie eine neue Benachrichtigung, legen eine Nachricht für den Nutzer fest und senden die Benachrichtigung.
- Öffnen Sie den Kurs
NotificationUtils.kt
und suchen Sie nachTODO: Step 1.1
. In diesem Codelab und im App-Code finden Sie entsprechende TODOs. - Sehen Sie sich die angegebene Funktion
sendNotification()
an. Sie erweitern diese Erweiterungsfunktion aufNotificationManager
, 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) {
- Rufen Sie eine Instanz des Benachrichtigungs-Builders ab, übergeben Sie den App-Kontext und eine Channel-ID. Die Channel-ID ist ein Stringwert für den Channel.
Mit Benachrichtigungskanälen können Sie Benachrichtigungen gruppieren. Durch das Gruppieren ähnlicher Benachrichtigungstypen können Entwickler und Nutzer alle Benachrichtigungen im Channel steuern. Nachdem ein Kanal erstellt wurde, kann er zum Senden einer beliebigen Anzahl von 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)
)
- Legen Sie das Benachrichtigungssymbol für Ihre App, einen Titel und den Inhaltstext für die Nachricht fest, die Sie dem Nutzer senden möchten. Im Codelab finden Sie weitere Optionen zum Anpassen Ihrer Benachrichtigung. Dies ist jedoch die Mindestmenge an Daten, die Sie festlegen müssen, um eine Benachrichtigung zu senden.
//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)
- Als Nächstes müssen Sie
notify()
mit einer eindeutigen ID für Ihre Benachrichtigung und mit demNotification
-Objekt aus Ihrem Builder aufrufen.
Diese ID steht für die aktuelle Benachrichtigungsinstanz und ist erforderlich, um diese Benachrichtigung zu aktualisieren oder abzubrechen. Da Ihre App zu einem bestimmten Zeitpunkt nur eine aktive Benachrichtigung hat, können Sie für alle Benachrichtigungen dieselbe ID verwenden. Dazu gibt es bereits eine Konstante mit dem Namen NOTIFICATION_ID
in NotificationUtils.kt
. Beachten Sie, dass Sie notify()
direkt aufrufen können, da der Aufruf aus einer Erweiterungsfunktion in derselben Klasse erfolgt.
//NotificationUtils.kt
// TODO: Step 1.4 call notify to send the notification
// Deliver the notification
notify(NOTIFICATION_ID, builder.build())
- Öffnen Sie
ui/EggTimerViewModel.kt
und suchen Sie nach der FunktionstartTimer()
. Mit dieser Funktion wird ein Alarm mit dem ausgewählten Zeitintervall erstellt, wenn der Nutzer den Eieruhr-Timer aktiviert. - In dieser Funktion lösen Sie eine Benachrichtigung aus, wenn der Nutzer den Timer startet. Um die zuvor implementierte Funktion
sendNotification()
aufzurufen, benötigen Sie eine Instanz vonNotificationManager
.NotificationManager
ist ein Systemdienst, der alle für die Notifications API bereitgestellten Funktionen bereitstellt, einschließlich der von Ihnen hinzugefügten Erweiterungsfunktion. Wenn Sie eine Benachrichtigung senden, abbrechen oder aktualisieren möchten, müssen Sie eine Instanz vonNotificationManager
vom System anfordern. Rufen Sie die FunktionsendNotification()|
mit der Benachrichtigungsnachricht und 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)
Fast geschafft. Wenn Sie Ihre App jetzt ausführen und den Timer einstellen, erhalten Sie jedoch keine Benachrichtigung.
- Öffnen Sie
logcat
und suchen Sie nach"No Channel found"
. Es sollte eine Fehlermeldung angezeigt werden, dassegg_channel
nicht vorhanden ist. In den folgenden Schritten erfahren Sie mehr über Benachrichtigungskanäle und wie Sie das Problem beheben können.
Schritt 2: Benachrichtigungskanäle
Ab API-Ebene 26 müssen alle Benachrichtigungen einem Kanal zugewiesen werden. Wenn Sie das App-Launcher-Symbol gedrückt halten, „App-Info“ und dann „Benachrichtigungen“ auswählen, wird eine Liste der Benachrichtigungskanäle angezeigt, die mit der App verknüpft sind. Derzeit ist die Liste leer, da für Ihre App noch keine Kanäle erstellt wurden.
Kanäle stellen einen „Typ“ von Benachrichtigung dar. Ihr Eierkocher kann beispielsweise eine Benachrichtigung senden, wenn das Ei fertig gekocht ist, und über einen anderen Kanal tägliche Benachrichtigungen senden, um Sie daran zu erinnern, dass Sie zum Frühstück Eier essen sollen. Alle Benachrichtigungen in einem Channel werden gruppiert und Nutzer können die Benachrichtigungseinstellungen für einen ganzen Channel konfigurieren. So können Nutzer ihre Benachrichtigungseinstellungen an die Art der Benachrichtigung anpassen, die sie erhalten möchten. Nutzer können beispielsweise die Benachrichtigungen zum Frühstück deaktivieren, aber weiterhin Benachrichtigungen vom Timer erhalten.
Entwickler legen die anfänglichen Einstellungen, die Wichtigkeit und das Verhalten fest, die auf alle Benachrichtigungen in einem Kanal angewendet werden sollen. Nachdem Sie die anfänglichen Einstellungen festgelegt haben, können Nutzer diese Einstellungen überschreiben.
In Schritt 1.1 haben Sie egg_notification_channel_id
als Benachrichtigungskanal verwendet. Jetzt müssen Sie die Benachrichtigungseinstellungen und das Verhalten dieses Kanals erstellen und anpassen.
- Öffnen Sie
EggTimerFragment.kt
und suchen Sie nach der FunktioncreateChannel()
. - Übergeben Sie die eindeutige Channel-ID an den Konstruktor von
NotificationChannel
. - Übergeben Sie den Namen des Benachrichtigungschannels, den Nutzer auch auf dem Bildschirm Einstellungen sehen.
- Übergeben Sie als letzten Parameter den Wichtigkeitsgrad für den Benachrichtigungschannel. Wichtigkeitsstufen werden später in diesem Codelab behandelt. Verwenden Sie vorerst
NotificationManag
er.IMPORTANCE_LOW
. - Legen Sie für das
notificationChannel
-ObjektenableLights
auf „true“ fest. Mit dieser Einstellung werden die Lichter eingeschaltet, wenn eine Benachrichtigung angezeigt wird. - Legen Sie für das
notificationChannel
-ObjektlightColor
auf „red“ (rot) fest, damit bei einer Benachrichtigung ein rotes Licht angezeigt wird. - Setzen Sie im
notificationChannel
-ObjektenableVibration
auf „true“, um die Vibration zu aktivieren. - Legen Sie für das
notificationChannel
-Objekt die Kanalbeschreibung auf‘Time for breakf
ast' fest. - Rufen Sie
getSystemService()
auf, um eine Instanz vonNotificationManager
zu erhalten. - Rufen Sie
createNotificationChannel()
fürNotificationManager
auf und übergeben Sie dasnotificationChannel
-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
}
- Als Nächstes müssen Sie die gerade geschriebene Funktion
createChannel()
(Schritt 1.7) aufrufen, um einen Channel zu erstellen. Diese Funktion verwendet zwei Parameter: die Kanal-ID und den Kanalnamen. Sie müssen Ihre Kanal-ID und Ihren Kanalnamen aus den String-Ressourcen abrufen, die bereits in Ihrem 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)
)
- Sie müssen die Kanal-ID an den Benachrichtigungs-Builder übergeben. Das haben Sie bereits in Schritt 1.2 erledigt. Wenn Sie einen falschen Wert als Channel-ID festlegen, schlägt die Benachrichtigung fehl. Öffnen Sie
NotificationUtils.kt
, um zu prüfen, ob die von Ihnen 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)
)
- Führen Sie die App aus. Sie werden sehen, dass die App jedes Mal, wenn Sie den Timer starten, eine Benachrichtigung sendet.
- Ziehen Sie die Statusleiste nach unten und prüfen Sie, ob Titel, Inhalt und Symbol der Benachrichtigung den Einstellungen entsprechen, die Sie in den vorherigen Schritten vorgenommen haben.
- Schließe die App und suche nach dem App-Symbol, um den neu erstellten Kanal zu prüfen. Halten Sie das App-Symbol gedrückt und wählen Sie App-Info aus.
- Wählen Sie in der Liste der Einstellungen Benachrichtigungen aus. Unter der Einstellung Benachrichtigungen anzeigen sollte ein neuer Kanal mit dem Namen Egg angezeigt werden.
Wenn Sie die App ausführen, wird die Benachrichtigung jetzt angezeigt. Sowohl Sie als App-Entwickler als auch Ihre Nutzer können die Einstellungen und das Verhalten für alle Benachrichtigungen anpassen, die über diesen Kanal gesendet werden. Glückwunsch, Sie haben eine Benachrichtigung erstellt.
Schritt 3: Benachrichtigungen in Ihre App einfügen
Bisher wird nur die grundlegende Verwendung der Notifications API gezeigt. Es ist jedoch nicht sinnvoll, eine Benachrichtigung direkt nach dem Starten des Timers zu senden. Nutzer würden wahrscheinlich lieber benachrichtigt werden, wenn das Ei fertig ist. Im nächsten Teil des Codelabs beheben Sie dieses Problem und ändern die Toast-Nachricht in eine Benachrichtigung.
Sie haben die Benachrichtigung bereits gesendet und beobachtet, wie sie den Nutzern angezeigt wird. Das war jedoch nur der erste Schritt, um ansprechende Benachrichtigungen zu erstellen. In diesem Schritt ändern Sie den Zeitpunkt, zu dem die Benachrichtigung gesendet wird.
In Ihrer App wird AlarmManager
verwendet, um einen Wecker zu stellen. Der Code für AlarmManager
ist bereits im Startcode enthalten und wird zum Anzeigen der Toast-Meldung verwendet. AlarmManager
behält die gewünschte Zeit im Blick und löst die onReceive()
-Funktion von AlarmReceiver.kt
aus, wenn die Zeit abgelaufen ist. Wenn Sie AlarmReceiver.kt
öffnen und zu onReceive()
navigieren, sollte die Kurzmitteilung angezeigt werden, die jedes Mal eingeblendet wird, wenn Sie einen Kurzzeitwecker einstellen.
- Öffnen Sie
AlarmReceiver.kt
, eine Instanz vonNotificationManager
, und rufen Sie die FunktionsendNotification()
mit dem Nachrichtentext und den 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
)
- Optional können Sie den Toast entfernen, da Ihre App eine Benachrichtigung sendet, wenn der Timer abgelaufen ist.
// AlarmReceiver.kt
// TODO: Step 1.10 [Optional] remove toast
// Toast.makeText(
// context,
// context.getText(R.string.eggs_ready),
// Toast.LENGTH_SHORT
// ).show()
- Führen Sie Ihre App aus . Sie sollten jedes Mal, wenn Sie den Timer starten und wenn er abgelaufen ist, eine Benachrichtigung erhalten.
Das ist nicht ideal. Sie möchten nicht zu viele Benachrichtigungen an Ihre Nutzer senden. Sie können die erste Benachrichtigung entfernen, die gesendet wird, wenn der Nutzer den Timer startet.
- Ö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)
- Führen Sie die App noch einmal aus.
- Stellen Sie einen Timer ein, minimieren Sie die App und warten Sie, bis die Zeit abgelaufen ist. Sie sehen eine Benachrichtigung. Das ist eine viel nützlichere Benachrichtigung.
Schritt 4: Inhaltsabsicht hinzufügen
- Führen Sie die App noch einmal aus, falls sie noch nicht ausgeführt wird.
- Klicken Sie auf die Benachrichtigung. Es passiert nichts!
Es ist gut, 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ügen Sie Ihrer Benachrichtigung einen Intent hinzu, um den Nutzer zum Timerbildschirm zurückzubringen.
Ein Intent
ist ein Messaging-Objekt, mit dem Sie eine Aktion von einer anderen App-Komponente anfordern können. Intents können verwendet werden, um eine Aktivität oder einen Dienst zu starten oder eine Broadcast-Nachricht zu senden. In diesem Fall verwenden Sie diesen Intent, um dem System mitzuteilen, dass MainActivity
geöffnet werden soll, wenn der Nutzer auf die Benachrichtigung tippt. Da Ihre App nur aus einer einzigen Ansicht besteht, haben Sie hier nicht viele Möglichkeiten. Bei einer größeren App sollte die Benachrichtigung jedoch für eine nahtlose Nutzererfahrung sorgen, indem der Nutzer zu einem Bildschirm weitergeleitet wird, der für die Interaktion mit der Benachrichtigung sinnvoll ist.
- Öffnen Sie
NotificationUtils.kt
und suchen Sie nach der ErweiterungsfunktionsendNotification()
. - Erstellen Sie einen
Intent
mit IhremapplicationContext
und der zu startenden AktivitätMainActivity::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, die Benachrichtigung wird aber außerhalb Ihrer App angezeigt. Damit ein Intent außerhalb Ihrer App funktioniert, müssen Sie einen neuen PendingIntent
erstellen.
PendingIntent
gewährt einer anderen Anwendung oder dem System Rechte, um eine Aktion im Namen Ihrer Anwendung auszuführen. Eine PendingIntent
ist lediglich ein Verweis auf ein vom System verwaltetes Token, das die Originaldaten beschreibt, die zum Abrufen verwendet wurden. Das bedeutet, dass das PendingIntent
auch dann noch von anderen Prozessen verwendet werden kann, an die es übergeben wurde, wenn der Prozess der zugehörigen Anwendung 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.
- Erstellen Sie ein
PendingIntent
mitapplicationContext
,NOTIFICATION_ID
, demcontentIntent
, das Sie im vorherigen Schritt erstellt haben, und dem FlagPendingIntent
. Mit dem FlagPendingIntent
wird angegeben, ob eine neuePendingIntent
erstellt oder eine vorhandene verwendet werden soll. Sie müssenPendingIntent.FLAG_UPDATE_CURRENT
als Flag festlegen, da Sie keine neue Benachrichtigung erstellen möchten, wenn bereits eine vorhanden ist. So ändern Sie den aktuellenPendingIntent
, der mit dem von Ihnen angegebenen Intent verknüpft ist.
// NotificationUtils.kt
// TODO: Step 1.12 create PendingIntent
val contentPendingIntent = PendingIntent.getActivity(
applicationContext,
NOTIFICATION_ID,
contentIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
- Übergeben Sie die
PendingIntent
an Ihre Benachrichtigung. Rufen Sie dazusetContentIntent()
für dieNotificationBuilder
auf. Wenn Sie jetzt auf die Benachrichtigung klicken, wirdPendingIntent
ausgelöst undMainActivity
wird geöffnet. - Setzen Sie
setAutoCancel()
außerdem auftrue
, damit die Benachrichtigung geschlossen wird, wenn der Nutzer darauf tippt und zur App weitergeleitet wird.
// NotificationUtils.kt
// TODO: Step 1.13 set content intent
.setContentIntent(contentPendingIntent)
.setAutoCancel(true)
- Starten Sie die App noch einmal.
- Stellen Sie einen Timer ein, minimieren Sie die App und warten Sie, bis die Benachrichtigung angezeigt wird.
- Wenn Sie die Benachrichtigung sehen, klicken Sie darauf, indem Sie die Statusleiste nach unten ziehen, und beobachten Sie, wie die App in den Vordergrund geholt wird.
Schritt 5: Benachrichtigung abbrechen
Sie haben einen funktionierenden Eieruhr-Skill mit Benachrichtigungen, aber es gibt 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 Nutzer verwirren, wenn die App im Hintergrund ausgeführt wird, und zu nicht durchgegarten Eiern führen.
Um das Problem zu beheben, müssen Sie die vorherige Benachrichtigung löschen, wenn Sie einen neuen Timer starten. Erstellen Sie zuerst eine weitere Erweiterungsfunktion in Ihrem NotificationUtils.kt
. NotificationManager
bietet eine API zum Abbrechen aller aktiven Benachrichtigungen namens cancelAll
()
.
- Öffnen Sie
NotificationsUtil.kt
. - Fügen Sie
NotificationManager
eine Erweiterungsfunktion hinzu, diecancelAll()
aufruft.
// NotificationUtils.kt
// TODO: Step 1.14 Cancel all notifications
/**
* Cancels all notifications.
*
*/
fun NotificationManager.cancelNotifications() {
cancelAll()
}
- Öffnen Sie
EggTimerViewModel.kt
und rufen Sie die FunktionstartTimer()
auf. - Rufen Sie in
startTimer()
eine Instanz vonNotificationManager
aus dem System ab und rufen SiecancelNotifications()
auf.
// EggTimerViewModel.kt
//TODO Step 1.15 call cancel notification
val notificationManager =
ContextCompat.getSystemService(
app,
NotificationManager::class.java
) as NotificationManager
notificationManager.cancelNotifications()
- Führen Sie die App aus und starten Sie den Timer.
- Nachdem Sie die Benachrichtigung gesehen haben, starten Sie den Timer noch einmal und beobachten Sie, wie unsere App die vorherige Benachrichtigung automatisch aus der Statusleiste löscht.
Das Benachrichtigungs-Framework bietet Entwicklern eine Vielzahl von Anpassungsoptionen, mit denen sie benutzerdefinierte Aktionen festlegen und ihre Benachrichtigungen nach Bedarf gestalten können. In dieser Aufgabe lernen Sie, wie Sie die Benachrichtigungen für den Eieruhr-Timer anpassen.
Schritt 1: Benachrichtigung gestalten
Wenn Sie das Design Ihrer Benachrichtigung an Ihre Anforderungen und den Benachrichtigungsinhalt anpassen, heben sich Ihre Benachrichtigungen ab und sehen eher wie eine Erweiterung Ihrer Anwendung aus. Das Benachrichtigungs-Framework bietet mehrere integrierte Stile, die Sie verwenden können. Sie können aber auch eigene Stile erstellen.
NotificationCompat
bietet integrierte Stile für:
BigTextStyle
, in dem ein großer Textblock angezeigt werden kann, z. B. der Inhalt einer E-Mail, wenn er maximiert wird.BigPictureStyle
, in dem großformatige Benachrichtigungen mit einem großen Bildanhang angezeigt werden.InboxStyle
, in dem Textinhalte im Konversationsstil angezeigt werden.MediaStyle
mit Steuerelementen für die Medienwiedergabe.MessagingStyle
: Hier werden großformatige Benachrichtigungen mit mehreren Nachrichten zwischen einer beliebigen Anzahl von Personen angezeigt.
Weitere Informationen zu anderen Stilen finden Sie in der Dokumentation unter Maximierbare Benachrichtigung erstellen. In diesem Schritt verwenden Sie NotificationCompat.BigPictureStyle
, um eine maximierbare Benachrichtigung zu erstellen, die im maximierten Zustand ein großes Bild eines Eis zeigt.
- Öffnen Sie
NotificationUtils.kt
und suchen Sie nach der FunktionsendNotification()
. - Laden Sie zuerst ein Bild aus
resources
mit demBitmapFactory
.
// NotificationUtils.kt
// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
applicationContext.resources,
R.drawable.cooked_egg
)
- Erstellen Sie ein neues
BigPictureStyle
und legen Sie Ihr Bild fest. - Legen Sie für
bigLargeIcon()
den Wertnull
fest, damit das große Symbol verschwindet, 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)
- Legen Sie den Stil mit
setStyle()
aufbigPicStyle
fest. - Legen Sie das große Symbol mit
setLargeIcon()
aufeggImage
fest, damit das Bild als kleineres Symbol angezeigt wird, wenn die Benachrichtigung minimiert ist.
// NotificationUtils.kt
// TODO: Step 2.1 add style to builder
.setStyle(bigPicStyle)
.setLargeIcon(eggImage)
- Führen Sie die App aus und stellen Sie einen Timer ein. Wenn die Benachrichtigung zum ersten Mal angezeigt wird, ist sie in der 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. Wenn Nutzer derzeit auf Ihre Benachrichtigungen klicken, werden sie zu Ihrer App weitergeleitet. Zusätzlich zu dieser Standardbenachrichtigungsaktion kannst du Aktionsschaltflächen hinzufügen, um dem Nutzer die Möglichkeit zu geben, eine auf die App bezogene Aufgabe über die Benachrichtigung auszuführen.
Eine Benachrichtigung kann bis zu drei Aktionsschaltflächen enthalten, über die der Nutzer schnell reagieren kann, z. B. eine Erinnerung zurückstellen oder auf eine SMS antworten. Diese Aktionsschaltflächen sollten die Aktion, die ausgeführt wird, wenn der Nutzer auf die Benachrichtigung tippt, nicht duplizieren.
Um eine Aktionsschaltfläche hinzuzufügen, übergeben Sie ein PendingIntent
an die Funktion addAction()
im Builder. Das ist ähnlich wie beim Einrichten der Standard-Tippaktion der Benachrichtigung durch Aufrufen von setContentIntent()
. Anstatt eine Aktivität zu starten, können Sie jedoch verschiedene andere Aktionen ausführen, z. B. einen BroadcastReceiver
starten, der einen Job im Hintergrund ausführt, damit die Aktion die bereits geöffnete App nicht unterbricht.
In diesem Codelab ist bereits ein BoadcastReceiver
mit dem Namen SnoozeReceiver
vorhanden. Mit SnoozeReceiver
erhalten Sie den Nutzerklick auf die Benachrichtigungsaktion. In den folgenden Schritten fügen Sie Code hinzu, um die Eieruhr-Benachrichtigung für 60 Sekunden zu verschieben, wenn der Nutzer auf die Schaltfläche zum Verschieben klickt. Wenn auf die Schlummerfunktion geklickt wird, erhält die SnoozeReceiver
einen Intent und erstellt einen neuen Wecker, um nach 60 Sekunden eine neue Benachrichtigung zu senden.
- Öffnen Sie
SnoozeReceiver.kt
. Diese Klasse ähneltAlarmReceiver
, die Sie bereits verwendet haben. In den folgenden Schritten fügen Sie Code hinzu, der dieonReceive()
-Funktion desSnoozeReceiver
auslöst. Kurz gesagt: Der Code inSnoozeReceiver
erstellt einen neuen Alarm, um eine Minute später eine neue Benachrichtigung zu senden. Scrolle in der Funktion „onReceive“ nach unten, rufe eine Instanz von „notificationManager“ vom System ab und rufe „cancelAll“ auf.
// SnoozeReceiver.kt
val notificationManager = ContextCompat.getSystemService(
context,
NotificationManager::class.java
) as NotificationManager
notificationManager.cancelAll()
- Wenn Sie
SnoozeReceiver
verwenden möchten, öffnen SieNotificationUtils.kt
. - Erstellen Sie ein neues
Intent
snoozeIntent
für dasSnoozeReceiver
direkt nach dem Stil in der FunktionsendNotification()
. - Erstellen Sie einen ausstehenden Intent, indem Sie die Methode
getBroadcast()
fürPendingIntent
aufrufen. Dazu sind die Parameter in den folgenden Schritten erforderlich. DiesePendingIntent
wird vom System verwendet, um einen neuen Wecker zu stellen, der 60 Sekunden nach dem Tippen auf die Schlummertaste eine neue Benachrichtigung sendet. - Der erste Parameter ist der Anwendungskontext, in dem diese
PendingIntent
die Aktivität starten soll. - Der zweite Parameter ist der Anfragecode für diesen ausstehenden Intent. Wenn Sie diesen ausstehenden Intent aktualisieren oder abbrechen möchten, müssen Sie mit diesem Code darauf zugreifen.
- Fügen Sie als Nächstes das
snoozeIntent
-Objekt hinzu. Das ist der Intent der zu startenden Aktivität. - Fügen Sie zum Schluss den Flag-Wert
#FLAG_ONE_SHOT
hinzu, da die Intention nur einmal verwendet wird. Die Schnellaktion und die Benachrichtigung werden nach dem ersten Tippen nicht mehr angezeigt. Der Intent kann also nur einmal verwendet werden.
// 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
)
- Rufen Sie als Nächstes die Funktion
addAction()
fürnotificationBuilder
auf. Diese Funktion erwartet ein Symbol und einen Text, um die Aktion für den Nutzer zu beschreiben. Außerdem müssen Sie diesnoozeIntent
hinzufügen. Mit diesem Intent wird der richtigeboadcastReceiver
ausgelöst, 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
)
- Führen Sie die Eieruhr-App aus, um die Schlummerfunktion zu testen.
- Starten Sie den Timer und minimieren Sie die App. Wenn der Timer abgelaufen ist, maximieren Sie die Benachrichtigung. Sie sehen nun, dass die Benachrichtigung eine Schaltfläche zum Schlummern hat, mit der der Eieruhr-Timer um eine weitere Minute verlängert wird.
Schritt 3: Wichtigkeit von Benachrichtigungen
Die Wichtigkeit bestimmt, in welchem Ausmaß der Nutzer durch die Benachrichtigung visuell und akustisch unterbrochen werden soll. Benachrichtigungen mit höherer Wichtigkeit unterbrechen Nutzer stärker.
Sie müssen die Wichtigkeitsstufe im NotificationChannel
-Konstruktor angeben. Du hast ursprünglich eine niedrige Priorität für die Eieruhr-App festgelegt. Du kannst eine von fünf Prioritätsstufen verwenden, die von IMPORTANCE_NONE(0)
bis IMPORTANCE_HIGH(4)
reichen. Die Wichtigkeitsstufe, die Sie einem Channel zuweisen, gilt für alle Benachrichtigungen, die Sie dort posten.
Wichtigkeitsstufen für Channels
Für Nutzer sichtbare Prioritätsstufe | Wichtigkeit (Android 8.0 und höher) | Priorität (Android 7.1 und niedriger) |
Akustisches Signal ertönt, Vorabbenachrichtigung wird angezeigt (oben auf dem Display) | ||
Akustisches Signal | ||
Kein Ton | ||
Kein Ton und wird nicht auf der Statusleiste angezeigt |
Informationen zur Auswahl einer geeigneten Prioritätsstufe finden Sie im Designleitfaden für Benachrichtigungen unter „Prioritätsstufen“. Sie sollten die Wichtigkeit von Benachrichtigungen in Ihrer App sorgfältig auswählen. Die Wichtigkeit von Channels sollte so gewählt werden, dass die Zeit und Aufmerksamkeit der Nutzer berücksichtigt werden. Wenn eine unwichtige Benachrichtigung als dringend getarnt wird, kann dies zu unnötiger Aufregung führen und ablenken. Nutzer haben die volle Kontrolle über die Wichtigkeit ihrer Benachrichtigungen. Wenn Sie also eine störende Benachrichtigung erstellen, können sie Ihren Benachrichtigungskanal vollständig deaktivieren.
Als Sie die Benachrichtigung in Schritt 1.6 erstellt haben, wurde der Eieruhr-Timer so eingestellt, dass Benachrichtigungen mit niedriger Priorität gesendet werden, da der Nutzer nicht durch Benachrichtigungen gestört werden soll. Es ist jedoch ratsam, die Aufmerksamkeit des Nutzers zu erregen, bevor das Ei zu lange gekocht wird. Wenn Sie die Wichtigkeit der Benachrichtigung ändern möchten, beginnen Sie mit den Kanaleinstellungen. Die Kanalwichtigkeit wirkt sich auf die Unterbrechungsstufe aller Benachrichtigungen aus, die im Kanal gepostet werden. Sie muss im NotificationChannel
-Konstruktor angegeben werden.
- Wenn Sie die Wichtigkeitsstufe des Benachrichtigungschannels Ihrer App ändern möchten, öffnen Sie
EggTimerFragment.kt
und rufen SiecreateChannel()
auf. Ändern Sie die Wichtigkeit vonIMPORTANCE_LOW
inIMPORTANCE_HIGH
.
// EggTimerFragment.kt
val notificationChannel = NotificationChannel(
channelId,
channelName,
// TODO: Step 2.4 change importance
NotificationManager.IMPORTANCE_HIGH
)
Wenn Sie Geräte mit Android 7.1 (API-Ebene 25) oder niedriger unterstützen möchten, müssen Sie auch für jede Benachrichtigung setPriority()
aufrufen und dabei eine Prioritätskonstante aus der Klasse NotificationCompat
verwenden.
- Öffnen Sie
NotificationUtils.kt
und fügen Sie dem Notification Builder-Objekt Folgendes 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)
- Bevor Sie die App ausführen, klicken Sie auf Ihrem Gerät oder Emulator lange auf das App-Symbol und wählen Sie „Deinstallieren“ aus, um vorherige Kanaleinstellungen zu löschen. Wenn Sie die App nicht deinstallieren, ändern sich die Einstellungen für die Kanalpriorität nicht und es kommt zu keiner Verhaltensänderung, wenn die Benachrichtigung gesendet wird.
- Führen Sie die App jetzt noch einmal aus und starten Sie den Timer. Wenn die Benachrichtigung zugestellt wird, sollte oben auf dem Bildschirm ein Pop-up-Fenster angezeigt werden, unabhängig davon, ob Ihre App im Vordergrund oder im Hintergrund ausgeführt wird.
Schritt 4: Benachrichtigungssymbole
Benachrichtigungskennzeichen sind kleine Punkte, die auf dem Launcher-Symbol der zugehörigen App angezeigt werden, wenn die App eine aktive Benachrichtigung hat. Nutzer können lange auf das App-Symbol drücken, um die Benachrichtigungen aufzurufen.
Diese Punkte, sogenannte Badges, werden standardmäßig angezeigt. Ihre App muss nichts weiter tun. Es kann jedoch Situationen geben, in denen Badges für Ihre Benachrichtigungen nicht sinnvoll sind. Sie können sie daher channelweise deaktivieren, indem Sie setShowBadge(false)
für Ihr NotificationChannel
-Objekt aufrufen. Da der Eieruhr-Timer jeweils nur eine aktive Benachrichtigung hat, bietet das Badge auf Ihrem App-Symbol für Ihre Nutzer keinen großen Vorteil. In den folgenden Schritten deaktivieren Sie das Symbol und lassen nur eine Benachrichtigung für den Eieruhr-Timer anzeigen.
- Fügen Sie dem Code zum Erstellen des Channels
setShowBadge(false)
hinzu, um Badges zu deaktivieren.
// EggTimerFragment.kt
).apply {
// TODO: Step 2.6 disable badges for this channel
setShowBadge(false)
}
- Führen Sie die App noch einmal aus, starten Sie den Timer und beobachten Sie das App-Symbol. Auf dem App-Symbol sollten keine Badges zu sehen sein.
Der Lösungscode befindet sich im Master-Branch des heruntergeladenen Codes.
- Mit der Klasse NotificationManager können Sie Benachrichtigungen erstellen, senden, aktualisieren und abbrechen.
- Verwenden Sie ein NotificationChannel-Objekt mit der Methode createNotificationChannel, um einen Kanal für die Benachrichtigung festzulegen.
- Verwenden Sie addAction(), um einer Benachrichtigung Schnellaktionen hinzuzufügen.
- Verwenden Sie setShowBadge(), um Badges zu aktivieren oder zu deaktivieren.
- Benachrichtigungen mit Stilen gestalten, die von Notification.Style abgeleitet sind
- Legen Sie den Wichtigkeitsgrad mit NotificationChannel.setImportance() fest.
Udacity-Kurs:
Android-Entwicklerdokumentation:
Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage für Codelabs zum Thema „Android für Fortgeschrittene mit Kotlin“.