Rheinwerk Computing < openbook >

 
Inhaltsverzeichnis
Vorwort
Teil I Grundlagen
1 Android – eine offene, mobile Plattform
2 Hallo Android!
3 Von der Idee zur Veröffentlichung
Teil II Elementare Anwendungsbausteine
4 Wichtige Grundbausteine von Apps
5 Benutzeroberflächen
6 Multitasking
Teil III Gerätefunktionen nutzen
7 Telefonieren und surfen
8 Sensoren, GPS und Bluetooth
Teil IV Dateien und Datenbanken
9 Dateien lesen, schreiben und drucken
10 Datenbanken
Teil V Multimedia und Produktivität
11 Multimedia
12 Kontakte und Organizer
A Einführung in Kotlin
B Jetpack Compose
C Häufig benötigte Codebausteine
D Literaturverzeichnis
E Die Begleitmaterialien
Stichwortverzeichnis

Ihre Meinung?
Spacer
<< zurück
Android 11 von Thomas Künneth
Das Praxisbuch für App-Entwickler
Buch: Android 11

Android 11
Pfeil 5 Benutzeroberflächen
Pfeil 5.1 Views und ViewGroups
Pfeil 5.1.1 Views
Pfeil 5.1.2 Positionierung von Bedienelementen mit ViewGroups
Pfeil 5.1.3 Alternative Layouts
Pfeil 5.2 Vorgefertigte Bausteine für Oberflächen
Pfeil 5.2.1 Listen darstellen mit ListFragment
Pfeil 5.2.2 Programmeinstellungen mit dem PreferencesFragment
Pfeil 5.2.3 Dialoge
Pfeil 5.2.4 Menüs und Action Bar
Pfeil 5.3 Nachrichten und Hinweise
Pfeil 5.3.1 Toast und Snackbar
Pfeil 5.3.2 Benachrichtigungen
Pfeil 5.3.3 App Shortcuts
Pfeil 5.4 Trennung von Oberfläche und Logik
Pfeil 5.4.1 Bedienelemente ohne »findViewById()«
Pfeil 5.4.2 Android Architecture Components
Pfeil 5.5 Dark Mode
Pfeil 5.5.1 Das DayNight-Theme
Pfeil 5.5.2 Dark Mode in eigenen Themes
Pfeil 5.6 Zusammenfassung
 
Zum Seitenanfang

5.3    Nachrichten und Hinweise Zur vorigen ÜberschriftZur nächsten Überschrift

Nachrichten und Hinweise spielen in Android seit der ersten Version eine wichtige Rolle. An den Implementierungen feilt Google in fast jedem Release. Insbesondere Benachrichtigungen (Notifications) sind in keinem anderen Betriebssystem so konsequent und benutzerfreundlich umgesetzt. Welche Möglichkeiten Ihnen zur Verfügung stehen, sehen wir uns in diesem Abschnitt an.

 
Zum Seitenanfang

5.3.1    Toast und Snackbar Zur vorigen ÜberschriftZur nächsten Überschrift

Manchmal möchte man dem Benutzer eine Information geben, ohne ihn aus seinem Arbeitsfluss herauszureißen. Beispiele hierfür sind Meldungen wie »Speichern erfolgreich« oder »Verbindung hergestellt«. Weil man davon ausgeht, dass solche Aktionen klappen, muss man das nicht an prominenter Stelle anzeigen. Und es macht auch nichts, wenn der Anwender den Hinweis nicht wahrnimmt (was bei Fehlermeldungen natürlich problematisch wäre). Hierfür bietet Android Toasts und Snackbars an. Diese Infotäfelchen zeigen unaufdringlich Text an und verschwinden nach einer bestimmten Zeit automatisch wieder vom Bildschirm.

Für Toasts ist die Klasse android.widget.Toast zuständig. Sie ist seit der ersten Plattform-Version vorhanden. Die statische Methode makeText() erzeugt eine Toast-Instanz. Deren Methode show() zeigt sie an. Sie können die Anzeigedauer auf kurz (LENGTH_SHORT) oder lang (LENGTH_LONG) stellen. Bis einschließlich Android 10 ist es möglich, die Position auf dem Bildschirm zu beeinflussen (setGravity()) und einen Rand zu definieren (setMargin()). Ab Android 11 sind diese Methoden für Apps mit API-Level 30 oder neuer als targetSdkVersion funktionslos.

Ebenfalls nicht mehr verwenden sollten Sie setView(). Damit war es möglich, anstelle von einfachem Text eigene Views darzustellen. Ab Android 11 gilt sie aber als veraltet. Dafür ist addCallback() hinzugekommen. Das Interface Toast.Callback definiert die beiden Methoden onToastHidden() und onToastShown(). Sie werden aufgerufen, wenn ein Toast aus- bzw. eingeblendet wird. Wie das funktioniert, zeigt mein Beispiel ToastDemo (Abbildung 5.14).

Die App »ToastDemo«

Abbildung 5.14    Die App »ToastDemo«

Dessen Klasse ToastDemoActivity ist im folgenden Listing zu sehen. In der Methode onCreate() wird mit setContentView() die Benutzeroberfläche geladen und angezeigt. setOnClickListener() fügt einen Listener hinzu, der beim Anklicken des Buttons Toast anzeigen mit Toast.makeText() ein Toast erzeugt und mit show() anzeigt. Solange das Toast zu sehen ist, soll die Schaltfläche nicht noch einmal angeklickt werden können. Das lässt sich sehr einfach mit button.isEnabled und Toast.Callback erreichen. Dessen Methoden onToastHidden() und onToastShown() müssen nur den Button-Status entsprechend setzen. Da addCallback() und das Interface aber erst ab Android 11 zur Verfügung stehen, muss die App anhand des Wertes Build.VERSION.SDK_INT prüfen, ob das der Fall ist. Unter älteren Android-Versionen kann der Button also mehrfach hintereinander geklickt werden. Die Plattform zeigt das Infotäfelchen dann entsprechend oft an.

package com.thomaskuenneth.androidbuch.toastdemo

import android.os.*
import android.widget.*
import android.widget.Toast.Callback
import androidx.appcompat.app.AppCompatActivity

class ToastDemoActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
val toast = Toast.makeText(this, R.string.app_name,
Toast.LENGTH_LONG)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
toast.addCallback(object : Callback() {
override fun onToastHidden() {
button.isEnabled = true
}

override fun onToastShown() {
button.isEnabled = false
}
})
}
toast.show()
}
button.isEnabled = true
}
}

Listing 5.27    Die Klasse »ToastDemoActivity«

Toasts sind sehr praktisch, um kurze Textmeldungen anzuzeigen. Manchmal möchte man neben der Botschaft aber auch eine Aktion unterbringen. Hat der Benutzer beispielsweise eine E-Mail in den Papierkorb verschoben, wäre es praktisch, dies mit einem Klick auf Widerrufen rückgängig machen zu können. Das ist mit Snackbars sehr einfach möglich.

Snackbar

Snackbars funktionieren wie Toasts: Erzeugen Sie mit Snackbar.make() eine Instanz und rufen deren Methode show() auf, um die Snackbar anzuzeigen (Abbildung 5.15). Mit setAction() können Sie eine Aktion definieren, die beim Anklicken ausgeführt wird. Wie das funktioniert, zeigt mein Beispiel SnackbarDemo. Dessen Hauptklasse SnackbarDemoActivity ist in Listing 5.28 zu sehen.

Die App »SnackbarDemo«

Abbildung 5.15    Die App »SnackbarDemo«

com.google.android.material.snackbar.Snackbar gehört zu Googles Material Components. Sie haben die Bibliothek in Abschnitt 4.5, »Navigation«, bereits kennengelernt. Dort beschreibe ich Ihnen, wie Sie sie Ihren Projekten hinzufügen.

package com.thomaskuenneth.androidbuch.snackbardemo

import android.os.Bundle
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar

class SnackbarDemoActivity : AppCompatActivity() {

private var count = 0

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button)
val info = findViewById<TextView>(R.id.info)
button.setOnClickListener {
val snackbar = Snackbar.make(button,
R.string.info, Snackbar.LENGTH_LONG)
snackbar.setAction(R.string.action) {
info.text = getString(R.string.template, ++count)
}
snackbar.addCallback(object : Snackbar.Callback() {
override fun onShown(sb: Snackbar?) {
button.isEnabled = false
}

override fun onDismissed(transientBottomBar: Snackbar?,
event: Int) {
button.isEnabled = true
}
})
snackbar.show()
}
}
}

Listing 5.28    Die Klasse »SnackbarDemoActivity«

Außer LENGTH_SHORT und LENGTH_LONG kennt Snackbar noch einen dritten Wert für die Anzeigedauer: LENGTH_INDEFINITE. In diesem Fall bleibt sie so lange sichtbar, bis sie verworfen, ihre Aktion angeklickt oder eine andere Snackbar angezeigt wird. Das Verwerfen funktioniert mit einer Wischgeste oder mittels Code (dismiss()). Wie bei Toasts können Sie sich informieren lassen, wenn eine Snackbar angezeigt oder verworfen wird. Die Methode addCallback() erhält ein Objekt des Typs Snackbar.Callback.

[»]  Hinweis

Ist Ihnen aufgefallen, dass die Schaltfläche Snackbar anzeigen irgendwie anders aussieht? Material Components bringen einen eigenen ViewInflater mit, der beispielsweise <Button ... />-Einträge in Layoutdateien zu Instanzen der Klasse com.google.android.material.button.MaterialButton entfaltet.

Mit Toast und Snackbar ist es sehr einfach, dem Anwender kurze Textnachrichten anzuzeigen. Android kann aber noch viel mehr. In Abschnitt 4.2.3, »Broadcast Receiver«, habe ich Ihnen schon einen ersten Einblick in Benachrichtigungen gegeben. Der nächste vertieft dies.

 
Zum Seitenanfang

5.3.2    Benachrichtigungen Zur vorigen ÜberschriftZur nächsten Überschrift

Benachrichtigungen gehörten von Anfang an zu den wichtigsten Funktionen in Android. Sie erinnern, informieren oder stellen situationsabhängige Inhalte dar. Google hat die kleinen Infohäppchen im Laufe der Jahre konsequent erweitert. Benachrichtigungen sind schon lange keine reinen Anzeigetäfelchen mehr, sondern können Schaltflächen zum Auslösen von Aktionen enthalten. Vieles lässt sich direkt erledigen, ohne erst eine App aufrufen zu müssen. Wie das geht, zeige ich Ihnen anhand der Beispiel-App NotificationDemo. Da Benachrichtigungen viele Einstellungsmöglichkeiten bieten, zeige ich Ihnen deren Verwendung nicht in einem langen Listing. Die Version der Klasse NotificationDemoActivity in Listing 5.29 bildet den Einstieg. Sie demonstriert, wie man eine einfache Benachrichtigung erzeugt und anzeigt. Schritt für Schritt kommt dann Code hinzu. Die Begleitmaterialien enthalten die fertige Klasse mit allen Erweiterungen.

NotificationDemo stellt den Button Benachrichtigung anzeigen dar. Wird er angeklickt, erscheint eine Benachrichtigung, und die App beendet sich. Alle weiteren Aktionen finden in createAndSendNotification() statt. Dort wird als Erstes mit PendingIntent.getActivity() ein PendingIntent-Objekt erzeugt. Normale Intents beschreiben ja eine Aktion, die jemand anderes ausführen soll. Mit einem PendingIntent geben Sie einer anderen App oder dem System die Möglichkeit, Code Ihrer App auszuführen. Bei Benachrichtigungen wird das verwendet, um auf deren Anklicken zu reagieren. getActivity() erzeugt ein PendingIntent zum Starten einer Activity, getBroadcast() eines zum Aufrufen eines Broadcast Receivers.

Das PendingIntent wird mit setContentIntent() an ein Objekt des Typs NotificationCompat.Builder übergeben. Der Builder konfiguriert und erstellt (builder.build()) eine Benachrichtigung. Er bietet zahlreiche set...()-Methoden an, um diese zu konfigurieren. setContentTitle() (Überschrift), setContentText() (Text der Benachrichtigung) und setSmallIcon() sollten Sie auf jeden Fall setzen. setPriority() legt fest, wie wichtig eine Benachrichtigung ist, also wie sehr der Benutzer durch sie in seiner Arbeit gestört werden darf. Da das seit Android 8 durch den sogenannten Benachrichtigungskanal gesteuert wird (dazu gleich mehr), müssen Sie die Methode nur dann aufrufen, wenn Sie ältere Plattformen unterstützen möchten. setAutoCancel() steuert, ob eine Benachrichtigung nach dem Antippen automatisch geschlossen wird. Bei false müssen Sie dies mit der NotificationManagerCompat-Methode cancel() selbst erledigen.

package com.thomaskuenneth.androidbuch.notificationdemo

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.os.Bundle
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat

private const val NOTIFICATION_ID = 42
private const val CHANNEL_ID = "channel01"
private const val RESULT_KEY = "resultKey"
class NotificationDemoActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
createAndSendNotification()
finish()
}
}

private fun createAndSendNotification() {
val pendingIntent = PendingIntent.getActivity(this, 0,
Intent(this, NotificationDemoActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.notification_text))
.setSmallIcon(R.mipmap.ic_launcher_round)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(false)
val manager = NotificationManagerCompat.from(this)
val channel = NotificationChannel(CHANNEL_ID,
getString(R.string.channel_name),
NotificationManager.IMPORTANCE_DEFAULT
)
manager.createNotificationChannel(channel)
manager.notify(NOTIFICATION_ID, builder.build())
}
}

Listing 5.29    Die Klasse »NotificationDemoActivity«

Benachrichtigungskanäle bündeln Benachrichtigungen, die thematisch zusammengehören. Wenn Ihre App beispielsweise mehrere Konten verwaltet, könnten Sie für jedes Konto einen eigenen Kanal erstellen. Das ist praktisch, weil ein Kanal Auswirkungen auf das Anzeigen einer zu ihm gehörenden Benachrichtigung hat. So legt das Attribut importance fest, wie wichtig sie ist (und damit, wie Android die Benachrichtigung anzeigt). Sie können unter anderem Sounds und Vibrationsmuster festlegen, die Anzeige auf dem Sperrbildschirm konfigurieren oder das Verhalten bei Bitte nicht stören einstellen.

Das Anlegen eines Kanals geschieht üblicherweise in onCreate() oder einer daraus aufgerufenen Methode. Erzeugen Sie eine NotificationChannel-Instanz und konfigurieren diese, zum Beispiel mit setVibrationPattern() oder setLightColor(). Nun können Sie das Objekt der Methode createNotificationChannel() einer NotificationManagerCompat-Instanz übergeben. Sie wird mit NotificationManagerCompat.from() instanziiert.

[»]  Hinweis

Das wiederholte Anlegen eines Kanals ist gemäß Googles Dokumentation unproblematisch. Bitte beachten Sie aber, dass die meisten Kanaleigenschaften nach dem Aufruf von createNotificationChannel() nicht mehr programmatisch geändert werden können, sondern nur noch durch den Anwender. Möchten Sie Änderungen vornehmen, müssen Sie den Kanal mit deleteNotificationChannel() löschen und danach neu anlegen.

Als letzten Schritt zeigen Sie mit der NotificationManagerCompat-Methode notify() die Benachrichtigung schließlich an. Sie ist in Abbildung 5.16 zu sehen.

Eine einfache Benachrichtigung

Abbildung 5.16    Eine einfache Benachrichtigung

Mit NotificationCompat.BigTextStyle lassen sich großformatige Benachrichtigungen, die viel Text enthalten, erzeugen. Fügen Sie das Codefragment einfach der Builder-Kette hinzu (in meinem Beispiel ist die Zeile nach setAutoCancel() ein guter Ort dafür):

// BigTextStyle
.setStyle(
NotificationCompat.BigTextStyle()
.bigText(getString(R.string.notification_text))
)

Normalerweise können Benutzer eine Benachrichtigung durch eine Wischgeste verwerfen. Das ist bei Benachrichtigungen, die einen laufenden Vorgang (Download, Wiedergabe eines Musikstücks ...) repräsentieren, natürlich ungünstig. Mit setOngoing(true) können Sie dies verhindern.

Aktionen

Mit der Methode addAction() können Sie eine Benachrichtigung dazu befähigen, auf Benutzereingaben zu reagieren. Ihr wird eine NotificationCompat.Action-Instanz übergeben, die Sie ganz einfach mit einem NotificationCompat.Action.Builder erzeugen. Neben einem Icon und dem anzuzeigenden Text erhält dieser ein PendingIntent. Es repräsentiert die auszuführende Aktion und den Empfänger.

// Aktion mit PendingIntent
val actionBuilder = NotificationCompat.Action.Builder(
R.mipmap.ic_launcher,
"Eine Aktion",
pendingIntent)
builder.addAction(actionBuilder.build())

Listing 5.30    Eine Aktion definieren

Möchten Sie, dass der Anwender direkt in einer Benachrichtigung Eingaben machen kann, fügen Sie dem Action.Builder mit addRemoteInput() eine androidx.core. app.RemoteInput-Instanz hinzu (bitte denken Sie an die entsprechende import-Anweisung). Ein RemoteInput wird, Sie ahnen es sicher, mit einem Builder erzeugt:

// Eingaben machen
val remoteInput = RemoteInput.Builder(RESULT_KEY)
.setLabel(getString(R.string.reply))
.build()
actionBuilder.addRemoteInput(remoteInput)

Listing 5.31    Eingaben in Benachrichtigungen erlauben

RESULT_KEY ist ein String, mit dem wir später die Eingabe wiederfinden. Ich komme gleich darauf zurück. Vorher möchte ich Ihnen noch zeigen, wie der Nutzer Antworten aus einer Liste mit vorgefertigten Texten auswählen kann. Fügen Sie der Builder-Kette am besten nach setLabel() die folgende Zeile hinzu:

.setChoices(resources.getStringArray(R.array.choices))

In meinem Beispiel sind die Texte in der Datei res/choices.xml gespeichert. Sie ist in Listing 5.32 dargestellt.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="choices">
<item>#1</item>
<item>#2</item>
<item>#3</item>
</string-array>
</resources>

Listing 5.32    Die Datei »choices.xml«

Wie eine solche Benachrichtigung aussieht, zeigt Abbildung 5.17.

Aber was passiert eigentlich mit der Antwort? Activities können mit getIntent() (oder einfacher: intent) abfragen, ob ihnen ein Intent übergeben wurde. In diesem Fall rufe ich die private Methode getMessageText() auf.

// Wurde ein Intent empfangen?
intent?.let {
// Dann verarbeiten
getMessageText(it)?.let { text ->
findViewById<TextView>(R.id.textview).text = text
NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID)
}
}

Listing 5.33    Antworttext anzeigen

Eine Benachrichtigung mit vorgefertigten Antworten

Abbildung 5.17    Eine Benachrichtigung mit vorgefertigten Antworten

Wenn diese einen Wert ungleich null liefert, übertrage ich den Text in eine TextView. getMessageText() wiederum ruft die RemoteInput-Methode getResultsFromIntent() auf und wertet das gelieferte Bundle aus. Hierzu greift sie mit getCharSequence() auf einen Eintrag zu, der über den Schlüssel RESULT_KEY identifiziert wird. Diesen haben wir beim Erzeugen des RemoteInput.Builder-Objekts übergeben.

private fun getMessageText(intent: Intent): CharSequence? =
RemoteInput.getResultsFromIntent(intent)?.getCharSequence(RESULT_KEY)

Listing 5.34    Den Antworttext ermitteln

Haben Sie sich in Listing 5.33 über die Zeile

NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID)

gewundert? Beim Versenden von Antworten erscheint in der Benachrichtigung eine Fortschrittsanzeige. Um sie verschwinden zu lassen, müssen Sie die Benachrichtigung mit cancel() abbrechen oder mit notify() aktualisieren.

 
Zum Seitenanfang

5.3.3    App Shortcuts Zur vorigen ÜberschriftZur nächsten Überschrift

Mit App Shortcuts können Benutzer direkt vom Homescreen aus zu bestimmten Bereichen Ihrer App navigieren. Die Sprungziele erscheinen nach Tippen und Halten des Programm-Icons (sofern der verwendete Programmstarter dies unterstützt). Jeder Shortcut repräsentiert ein Intent, das eine bestimmte Aktion innerhalb der App auslöst, zum Beispiel das Senden einer Nachricht oder das Anzeigen einer geografischen Position in einer Karten-App.

Die App »AppShortcutDemo«

Abbildung 5.18    Die App »AppShortcutDemo«

Man unterscheidet zwischen statischen und dynamischen Shortcuts. Erstere repräsentieren »fest verdrahtete« Sprungziele. Stellen Sie sich eine App zum Umrechnen von Einheiten vor. Üblicherweise enthält deren Einstiegsseite Symbole oder Links, die zur Strecken-, Temperatur- und Gewichtsumrechnung führen. App Shortcuts bringen den Benutzer direkt vom Homescreen aus zum gewünschten Modul. Dynamische Shortcuts können auf Benutzereinstellungen, den aktuellen Standort, das aktuelle Datum oder die gegenwärtige Uhrzeit reagieren. Sie werden programmatisch erzeugt.

Wie, das zeige ich Ihnen anhand der Beispiel-App AppShortcutDemo (Abbildung 5.18). Sie legt zwei Shortcuts an und gibt nach dem Anklicken je nach Art des Shortcuts den Text »statisch« oder die Webadresse des Rheinwerk Verlags aus. Statische App Shortcuts werden in einer XML-Datei im Verzeichnis res/xml eingetragen. Ihr Name kann, abgesehen von der Endung, beliebig vergeben werden. Listing 5.35 zeigt die Datei shortcuts.xml meiner Beispiel-App.

<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:enabled="true"
android:icon="@drawable/ic_save"
android:shortcutId="static1"
android:shortcutShortLabel="@string/static_shortcut">
<intent
android:action=
"com.thomaskuenneth.androidbuch.appshortcutdemo.AppShortcut"
android:targetClass=
"com.thomaskuenneth.androidbuch.appshortcutdemo.AppShortcutActivity"
android:targetPackage=
"com.thomaskuenneth.androidbuch.appshortcutdemo" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
</shortcuts>

Listing 5.35    Die Datei »shortcuts.xml«

Jeder statische Shortcut wird durch ein korrespondierendes <shortcut />-Element repräsentiert. Shortcuts enthalten üblicherweise ein Icon, eine kurze und eine lange Beschreibung sowie eine eindeutige Kennung. Aus Platzgründen habe ich die lange Beschreibung hier weggelassen. Das <categories />-Element ist in dieser Form obligatorisch. <intent /> schließlich legt das Ziel des Shortcuts fest. Wie die App auf einen Shortcut reagiert, zeige ich Ihnen gleich. Lassen Sie uns vorher noch einen kurzen Blick auf die Manifestdatei werfen (siehe Listing 5.36). Sie folgt im Wesentlichen dem Ihnen vertrauten Muster.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.thomaskuenneth.androidbuch.appshortcutdemo">
<application
...
android:theme=
"@style/AppTheme">
<activity android:name=".AppShortcutActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
</application>
</manifest>

Listing 5.36    Die Manifestdatei von »AppShortcutDemo«

Es gibt allerdings eine wichtige Erweiterung: Ein <meta-data />-Element referenziert die XML-Datei, die die Beschreibung der statischen Shortcuts enthält. Wichtig ist, es der Hauptaktivität zuzuordnen. Diese ist leicht am Intent-Filter mit der Aktion android.intent.action.MAIN und der Kategorie android.intent.category.LAUNCHER zu erkennen. Eine App kann übrigens maximal fünf statische und dynamische Shortcuts gleichzeitig bereitstellen. Allerdings können Anwender diese kopieren und als eine Art Verknüpfung auf dem Homescreen ablegen. Die Zahl solcher Pinned Shortcuts ist nicht limitiert.

Die Hauptklasse AppShortcutActivity ist in Listing 5.37 zu sehen. Sie zeigt, wie Sie auf das Aktivieren von Shortcuts reagieren und wie Sie dynamische Shortcuts registrieren. In onCreate() wird nur die Benutzeroberfläche geladen und angezeigt. Die eigentliche Arbeit findet in onStart() statt. Zunächst wird mit ACTION == intent?.action geprüft, ob der Activity ein passendes Intent zugestellt wurde. Dies geschieht zum Beispiel beim Antippen des statischen Shortcuts, weil ich in der Datei shortcuts.xml mit android:targetClass diese Klasse als Ziel angegeben habe. Das dort definierte Intent hat die nur von meiner App verwendete Aktion com.thomaskuenneth.androidbuch.appshortcutdemo.AppShortcut.

package com.thomaskuenneth.androidbuch.appshortcutdemo

import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.drawable.Icon
import android.net.Uri
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.util.*

private const val ACTION =
"com.thomaskuenneth.androidbuch.appshortcutdemo.AppShortcut"
private const val ID = "dynamic1"
class AppShortcutActivity : AppCompatActivity() {

private lateinit var textview: TextView

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textview = findViewById(R.id.textview)
}

override fun onStart() {
super.onStart()
var message = getString(R.string.app_name)
if (ACTION == intent?.action) {
val uri = intent.data
message = uri?.toString() ?: getString(R.string.txt_static)
}
// dynamischer Shortcut
val shortcutIntent = Intent(this, AppShortcutActivity::class.java)
shortcutIntent.action = ACTION
shortcutIntent.data = Uri.parse("https://www.rheinwerk-verlag.de/")
getSystemService(ShortcutManager::class.java)?.let {
val shortcut = ShortcutInfo.Builder(this,
ID)
.setShortLabel(getString(R.string.dynamic_shortcut))
.setIcon(Icon.createWithResource(this,
R.drawable.ic_cloud))
.setIntent(shortcutIntent)
.build()
it.dynamicShortcuts = Collections.singletonList(shortcut)
}
textview.text = message
}
}

Listing 5.37    Die Klasse »AppShortcutActivity«

Nur wenn die Aktion des an die Activity übergebenen Intents mit der Konstante ACTION übereinstimmt (deren Wert entspricht dem aus shortcuts.xml), wird ein Text ausgegeben. Diese Prüfung ist erforderlich, weil Intents nicht nur beim Antippen von Shortcuts gefeuert werden, sondern auch aus vielen weiteren möglichen Gründen.

Dynamische Shortcuts werden mit einem ShortcutInfo.Builder erzeugt. Analog zu statischen Shortcuts können Sie unter anderem ein Icon (setIcon()), eine kurze Beschreibung (setShortLabel()) sowie ein Intent (setIntent()) setzen. Die ShortcutManager-Methode setDynamicShortcuts() registriert alle dynamischen Shortcuts einer App »in einem Rutsch«. Darüber hinaus können Sie einzelne Shortcuts aktualisieren, deaktivieren oder entfernen. Ein Objekt dieses Typs erhalten Sie mit getSystemService().

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
Zur Rheinwerk-Konferenz für Kotlin
 Buchempfehlungen
Zum Rheinwerk-Shop: Kotlin

Kotlin


Zum Rheinwerk-Shop: Praxisbuch Usability und UX

Praxisbuch Usability und UX


Zum Rheinwerk-Shop: Flutter und Dart

Flutter und Dart


Zum Rheinwerk-Shop: App-Design

App-Design


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2023
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern