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 4 Wichtige Grundbausteine von Apps
Pfeil 4.1 Was sind Activities?
Pfeil 4.1.1 Struktur von Apps
Pfeil 4.1.2 Lebenszyklus von Activities
Pfeil 4.2 Kommunikation zwischen Anwendungsbausteinen
Pfeil 4.2.1 Intents
Pfeil 4.2.2 Kommunikation zwischen Activities
Pfeil 4.2.3 Broadcast Receiver
Pfeil 4.3 Fragmente
Pfeil 4.3.1 Grundlagen
Pfeil 4.3.2 Ein Fragment in eine Activity einbetten
Pfeil 4.3.3 Mehrspaltenlayouts
Pfeil 4.4 Berechtigungen
Pfeil 4.4.1 Normale und gefährliche Berechtigungen
Pfeil 4.4.2 Tipps und Tricks zu Berechtigungen
Pfeil 4.5 Navigation
Pfeil 4.5.1 Jetpack Navigation
Pfeil 4.5.2 Die Klasse »BottomNavigationView«
Pfeil 4.6 Zusammenfassung
 
Zum Seitenanfang

4.2    Kommunikation zwischen Anwendungsbausteinen Zur vorigen ÜberschriftZur nächsten Überschrift

Aus der Sicht des Benutzers repräsentieren Activities die Funktionen einer App. Technisch gesehen handelt es sich bei diesen Grundbausteinen um klassische Komponenten, denn Activities haben einen Zustand und können, wie Sie in diesem Abschnitt sehen werden, Nachrichten senden und empfangen.

 
Zum Seitenanfang

4.2.1    Intents Zur vorigen ÜberschriftZur nächsten Überschrift

Nachrichten werden in sogenannten Intents gekapselt. Android nutzt diese Boten aber nicht nur für die lose Kopplung von Activities, sondern auch für den Datenaustausch zwischen den anderen elementaren Anwendungsbausteinen Service und Broadcast Receiver.

Intents binden die Komponenten einer oder mehrerer Apps zur Laufzeit. Sie sind passive Datenstrukturen, die entweder die abstrakte Beschreibung einer auszuführenden Operation enthalten oder über ein eingetretenes Ereignis informieren. Auf welche Weise sie zugestellt werden, hängt von der Art der Komponente ab. Entsprechende Beschreibungen finden Sie deshalb in den Abschnitten zu den jeweiligen Komponenten.

Aufbau von Intents

Intent-Objekte übermitteln ihren »Empfängern«, welche Aktionen diese ausführen sollen, und liefern die hierfür benötigten Daten zum Teil gleich mit. Die sogenannte Kategorie hingegen wird durch Android selbst ausgewertet, denn sie beschreibt, welche Komponenten ein Intent behandeln bzw. erhalten können und wie diese gegebenenfalls zu starten sind.

Sie können den Empfänger eines Intents unmittelbar angeben, indem Sie den Komponentennamen setzen. Dieser besteht aus dem voll qualifizierten Klassennamen der Zielkomponente (eine Activity, ein Service oder ein Broadcast Receiver) und dem Paketnamen der App, die diese Komponente enthält. Sie finden diesen zum Beispiel im Attribut package der Manifestdatei. Beachten Sie, dass der Paketname der Anwendung und das Paket der Komponente keineswegs identisch sein müssen.

Intents, die die Zielkomponente mit einem Komponentennamen benennen, werden explizite Intents genannt. Da Paket- und Klasseninformationen den Entwicklern fremder Apps normalerweise nicht bekannt sind, werden solche Intents üblicherweise für den anwendungsinternen Nachrichtenaustausch verwendet. Implizite Intents hingegen nennen kein Ziel – der Komponentenname bleibt leer. Sie werden üblicherweise verwendet, um Komponenten anderer Apps zu aktivieren.

Vielleicht fragen Sie sich, wie der Empfänger ermittelt wird? Das System muss herausfinden, welche Komponenten am besten für die Behandlung bzw. Auswertung des Intents geeignet sind. Das können einzelne Activities oder Services sein, die die gewünschte Aktion ausführen. Die bestmöglichen Empfänger können aber auch Broadcast Receiver sein. Diese reagieren auf das Ereignis, das mit dem Intent beschrieben wurde. Hierzu wird der Inhalt eines Intents mit sogenannten Intent-Filtern verglichen.

Inhalt von Intents und Intent-Filtern

Intent-Filter werden in der Manifestdatei eingetragen und beschreiben, auf welche impliziten Intents eine Komponente reagieren möchte bzw. welche sie empfangen kann. Hierzu wird jedes Wurzelelement einer Komponente (wie etwa <activity />) mit dem Kindelement <intent-filter /> versehen. Werden keine Intent-Filter angegeben, kann die Komponente nur explizite Intents empfangen. Implizite Intents werden zugestellt, sofern ihre Eigenschaften zu den Filterkriterien passen, die von den Kindern des Elements <intent-filter /> angegeben werden.

Das Element <action /> muss mindestens einmal vorhanden sein; es speichert die Aktion, die ein empfangenes Intent auslösen soll. Beispiele hierfür sind Anruf tätigen, Fehlerbericht senden, Suche im Web durchführen und Verknüpfung anlegen. Die Klasse Intent enthält Konstanten für diese und viele weitere Aktionen. Die Namen dieser Konstanten beginnen mit dem Präfix ACTION_.

Um eine dieser Actions in der Manifestdatei anzugeben (weil Ihre Activity, Ihr Service oder Broadcast Receiver darauf reagieren soll), wird dem Attribut android:name des Elements <action /> die Zeichenkette android.intent.action., gefolgt vom Konstantennamen der Action ohne das Präfix ACTION_, zugewiesen. Hierzu zwei Beispiele: Möchten Sie, dass eine Ihrer Komponenten auf die Action ACTION_MAIN reagiert, weisen Sie android:name den Wert android.intent.action.MAIN zu. ACTION_WEB_SEARCH wird zu android.intent.action.WEB_SEARCH. Wie Sie Intents, die solche Aktionen auslösen, an Activities oder Broadcast Receiver übermitteln, zeige ich Ihnen in den folgenden Abschnitten. Ausführliche Informationen zu Services finden Sie in Kapitel 6, »Multitasking«.

Die Kategorien eines Intents legen fest, an welche Arten von Komponenten es übermittelt werden kann. Die Klasse Intent enthält Konstanten, die einige vordefinierte Kategorien repräsentieren. Beispielsweise bedeutet CATEGORY_BROWSABLE, dass eine Aktivität vom Webbrowser aufgerufen werden kann, um bestimmte Inhalte anzuzeigen.

Wenn eine Ihrer Activities diese Fähigkeit besitzt und Sie diese anderen Apps zur Verfügung stellen möchten, erweitern Sie das Element <intent-filter /> in der Manifestdatei um <category /> und weisen dessen Attribut android:name den Wert android.intent.category.BROWSABLE zu. Auch hier wird einem Präfix (android.intent.category.) der abschließende Teil eines Konstantennamens (in diesem Fall ohne CATEGORY_) hinzugefügt.

 
Zum Seitenanfang

4.2.2    Kommunikation zwischen Activities Zur vorigen ÜberschriftZur nächsten Überschrift

Activities repräsentieren die für den Benutzer sichtbaren Teile einer App. Indem er durch die verschiedenen Bereiche der Anwendung navigiert, startet und beendet der Benutzer unbewusst Activities, je nach Komplexität des Programms eine ganze Reihe. Diese Activities rufen ihren jeweiligen Nachfolger auf, indem sie an die Methode startActivity() ein Intent übergeben, das diesen Nachfolger näher beschreibt. Das Intent kann eine namentlich bekannte Activity sein. Solche expliziten Intents enthalten den Ihnen bereits bekannten Komponentennamen.

[+]  Tipp

Die Begleitmaterialien zum Buch enthalten das Projekt LeeresProjekt. Es ist ein Rumpfprojekt mit der Activity-Klasse MainActivity und einigen Layoutdateien, unter anderem activity_main.xml. Es eignet sich hervorragend als »Umgebung« für Quelltextfragmente.

Um die Activity SimpleActivity zu starten, fügen Sie der aufrufenden Aktivität die folgenden Zeilen hinzu:

val intent = Intent(this, SimpleActivity::class.java)
startActivity(intent)

Denken Sie daran, dass Sie jede Activity, die Sie mit startActivity() aufrufen möchten, in die Manifestdatei eintragen müssen. Android Studio erledigt dies für Sie, wenn Sie die neue Activity über File • New • Activity anlegen.

Bei impliziten Intents ist der konkrete Klassenname nicht bekannt. Das System sucht stattdessen anhand der Action die am besten geeignete Activity aus. Diese kann auch zu einer fremden App gehören.

Parameter übergeben

Mit dem folgenden Quelltextfragment können Sie im Android-Adressbuch einen neuen Kontakt anlegen.

val intent = Intent(Intent.ACTION_INSERT,
ContactsContract.Contacts.CONTENT_URI)
intent.putExtra("finishActivityOnSaveCompleted", true)
intent.putExtra(ContactsContract.Intents.Insert.NAME,
"Max Mustermann")
intent.putExtra(ContactsContract.Intents.Insert.PHONE,
"+49 (123) 45 67 89")
intent.putExtra(ContactsContract.Intents.Insert.PHONE_TYPE,
ContactsContract.CommonDataKinds.Phone.TYPE_WORK)
startActivity(intent)

Listing 4.8    Einen neuen Kontakt anlegen

Das Beispiel belegt den Namen und die geschäftliche Rufnummer des anzulegenden Kontakts vor. Wie dies zur Laufzeit aussieht, ist in Abbildung 4.6 dargestellt. Wenn Sie das Codefragment im Emulator ausführen, werden Sie möglicherweise darauf hingewiesen, dass der angelegte Kontakt nur lokal gespeichert und nicht synchronisiert wird. Stimmen Sie in diesem Fall einfach der lokalen Speicherung zu.

Einen neuen Kontakt anlegen

Abbildung 4.6    Einen neuen Kontakt anlegen

Dem Intent wird die Action ACTION_INSERT zugewiesen. Der zweite Parameter des Konstruktoraufrufes legt fest, auf welchem Datenbestand die Aktion ausgeführt werden soll. Die im Beispiel übergebene Konstante verweist auf die zentrale Kontaktdatenbank. Alternativ ist übrigens auch die folgende Schreibweise möglich:

val intent = Intent(Intent.ACTION_INSERT)
intent.data = ContactsContract.Contacts.CONTENT_URI

Mit der Methode putExtra() können Sie einem Intent beliebig viele Nutzdaten übergeben. Was diese bewirken und wie sie ausgewertet werden, ist letztlich von der Activity abhängig, die das Intent empfängt. In der Android-Dokumentation finden Sie entsprechende Beschreibungen bei den ACTION_-Konstanten der Klasse Intent.

Vielleicht fragen Sie sich, ob auf diese Weise auch mehrere Rufnummern übergeben werden können. Immerhin wurde in den Extras schon ein Wert für ContactsContract.Intents.Insert.PHONE eingetragen. Jedes weitere putExtra() wird deshalb den bereits vorhandenen Wert überschreiben. Android sieht in solchen Fällen vor, eine Liste von android.content.ContentValues-Instanzen zu übergeben:

val data = ArrayList<ContentValues>()
...
intent.putParcelableArrayListExtra(
ContactsContract.Intents.Insert.DATA, data)

Listing 4.9    Mehrere zusammengesetzte Werte übergeben

Die Werte eines ContentValues sind von den zu übergebenden Daten abhängig. Im Fall einer privaten sowie einer Mobilfunktelefonnummer sieht dies folgendermaßen aus:

val v1 = ContentValues()
v1.put(ContactsContract.Contacts.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
v1.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "123")
v1.put(ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.TYPE_HOME)
data.add(v1)
val v2 = ContentValues()
v2.put(ContactsContract.Contacts.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
v2.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "456")
v2.put(ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
data.add(v2)

Listing 4.10    »ContentValues« füllen

Wenn Sie im Quelltext Ihrer Activity unmittelbar nach dem Aufruf der Methode startActivity() eine Ausgabe mittels Log.d() hinzufügen, stellen Sie fest, dass Android nicht auf die Beendigung der nachgestarteten Activity wartet, obwohl dies aber unter Umständen gewünscht ist, damit das Ergebnis ausgewertet werden kann. In diesem Fall verwenden Sie anstelle von startActivity() die Methode startActivityForResult() – sie sorgt dafür, dass Ihre App zur richtigen Zeit benachrichtigt wird.

Rückgabewerte

Für Rückgabewerte ist die Methode onActivityResult() zuständig. Sie erhält als einen ihrer Parameter den sogenannten Request Code. Hierbei handelt es sich um einen Wert, den Sie beliebig vergeben können. Es bietet sich an, in der aufrufenden Klasse eine entsprechende Konstante zu definieren, zum Beispiel:

private val requestCodeInsertContact = 1234

Auf diese Weise können Sie sicherstellen, dass der Request Code innerhalb Ihrer Anwendung eindeutig ist. Sie kennzeichnen mit dem Request Code, wer eine Activity gestartet hat, und übergeben den Request Code als Parameter beim Aufruf von startActivityForResult().

val intent = Intent()
...
startActivityForResult(intent, requestCodeInsertContact)

Die Implementierung von onActivityResult() kann dann so aussehen:

override fun onActivityResult(requestCode: Int,
resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == requestCodeInsertContact) {
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
val i = Intent(Intent.ACTION_VIEW,
data.data)
startActivity(i)
}
}
}
}

Listing 4.11    Implementierung der Methode »onActivityResult()«

Bitte rufen Sie stets mit super.onActivityResult() die Implementierung der Elternklasse auf. Denn die nun beendete Activity könnte von ihr gestartet worden sein. In diesem Fall ist es natürlich wichtig, sie darüber zu informieren. Anschließend prüfen Sie, ob der Request Code dem von Ihnen definierten Wert entspricht. Dann war Ihre Activity der Aufrufer, und Sie können die Rückantwort der beendeten Aktivität auswerten. Auch hierfür verwendet Android Intents. Beispielsweise liefert die Activity zum Anlegen von Kontakten einen Uniform Resource Identifier, der den neuen Eintrag kennzeichnet. Mein Beispiel verwendet diese Referenz, um den Datensatz anzuzeigen. Denken Sie daran, vor Zugriffen das Intent auf null zu prüfen, weil Activities nicht zwingend eine Nachricht zurückliefern müssen.

Neben dem Intent signalisiert auch der Result Code das Ergebnis einer Activity, wobei üblicherweise RESULT_OK bedeutet, dass alles in Ordnung ist, wenn beispielsweise ein neuer Kontakt angelegt oder eine Änderung gespeichert wurde. Activities setzen den Rückgabewert durch Aufruf der Methode setResult().

[»]  Hinweis

In den Android-Versionen ab API-Level 14 gibt es ein Problem in der Kontakte-App, das unter Umständen die automatische Rückkehr zur aufrufenden Activity verhindert. Mit Android 4.0.3 (API-Level 15) hat Google hierfür eine Umgehungsmöglichkeit eingebaut. Es handelt sich um die folgende von mir bisher nicht weiter erklärte Zeile:

intent.putExtra("finishActivityOnSaveCompleted", true)

Fügen Sie diese Anweisung einfach Ihrem Code zum Befüllen der Extras beim Anlegen und Bearbeiten von Kontakten hinzu.

Im nächsten Abschnitt stelle ich Ihnen einen weiteren wichtigen Anwendungsbaustein vor.

 
Zum Seitenanfang

4.2.3    Broadcast Receiver Zur vorigen ÜberschriftZur nächsten Überschrift

Broadcast Receiver sind Komponenten, die auf systemweit versandte Nachrichten reagieren. Android verschickt solche Mitteilungen zum Beispiel, wenn der Batteriestand niedrig ist oder der Bildschirm ausgeschaltet wurde. Auch für normale Apps kann es interessant sein, solche Broadcasts zu initiieren. Denken Sie an ein Programm für Dateitransfers: Dieses möchte bestimmt darüber informieren, dass eine Übertragung abgeschlossen wurde, egal, ob erfolgreich oder mit Fehler.

Broadcast Receiver haben keine eigene Bedienoberfläche, können aber Benachrichtigungen in der Statuszeile hinterlassen. Generell fungieren sie allerdings eher als Schnittstellen zu anderen Komponenten. Insofern sollten Ihre Broadcast Receiver so wenig Logik wie möglich enthalten und diese möglichst an Activities oder Services delegieren. Übrigens kann Android diese Bausteine unabhängig von anderen Komponenten einer App aktivieren.

Broadcast Receiver implementieren

Die Klasse BootCompletedReceiver aus meinem Beispielprojekt BroadcastReceiverDemo implementiert einen einfachen Broadcast Receiver, der nach jedem Systemstart eine Benachrichtigung in der Statuszeile hinterlässt. Broadcast Receiver leiten von der Klasse android.content.BroadcastReceiver ab. Sie müssen die Methode onReceive() überschreiben, die aufgerufen wird, sobald der Receiver eine Nachricht empfängt. Die Methode erhält zwei Parameter: Der Kontext (android.content.Context) wird verwendet, um auf Systemressourcen oder Benutzereinstellungen zuzugreifen. Ein Intent beschreibt die übermittelte Nachricht. Beide Werte können null sein.

Die Ausführung von onReceive() erfolgt auf dem Mainthread, sofern nicht zum Beispiel über registerReceiver() ausdrücklich ein anderer angegeben wurde. Die Verarbeitung der Methode darf nicht sehr viel Zeit in Anspruch nehmen, denn nach zehn Sekunden kann Android den zugehörigen Prozess blockieren und beenden. Beachten Sie auch, dass das Receiver-Objekt nach dem Verlassen von onReceive() aus dem Speicher entfernt werden kann. Asynchron gestartete Operationen sollten ihm deshalb keine Ergebnisse übermitteln. Ausführliche Hinweise zur Kommunikation mit Services finden Sie in Kapitel 6, »Multitasking«.

Intent-Filter, die in der Manifestdatei eingetragen oder im Code mittels registerReceiver() gesetzt werden, legen fest, welche Intents an einen Receiver übermittelt werden sollen. Trotzdem ist es bewährte Praxis, ausdrücklich auf alle erwarteten Aktionen zu prüfen, wie im folgenden Listing zu sehen ist.

package com.thomaskuenneth.androidbuch.broadcastreceiverdemo

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.*
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import java.text.DateFormat
import java.util.*

private val ID = 42
private val CHANNEL_ID = "BCR_01"
class BootCompletedReceiver : BroadcastReceiver() {

override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null || context == null) return
if (Intent.ACTION_BOOT_COMPLETED == intent.action) {
// Benachrichtigung zusammenbauen
val msg = DateFormat.getDateTimeInstance().format(Date())
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
builder.setSmallIcon(
R.mipmap.ic_launcher
).setContentTitle(
context.getString(R.string.app_name)
).setContentText(msg).setWhen(System.currentTimeMillis())
val notification = builder.build()
val manager = NotificationManagerCompat.from(context)
// Kanal anlegen
val channel = NotificationChannel(
CHANNEL_ID,
context.getString(R.string.app_name),
NotificationManager.IMPORTANCE_DEFAULT
)
manager.createNotificationChannel(channel)
// anzeigen
manager.notify(ID, notification)
}
}
}

Listing 4.12    Die Klasse »BootCompletedReceiver«

Mein Beispiel zeigt eine Benachrichtigung in der Statuszeile an. Hierzu wird als Erstes mit NotificationCompat.Builder() ein Objekt erzeugt, das für den Bau der eigentlichen Benachrichtigung verwendet wird. Sie können in beliebiger Reihenfolge set…()-Aufrufe aneinanderreihen. Damit Android eine Benachrichtigung auch wirklich darstellt, müssen Sie mindestens ein kleines Icon (setSmallIcon()), einen Titel (setContentTitle()) und einen Text angeben, der den Inhalt beschreibt (setContentText()). builder.build() generiert die Notification-Instanz. Die Anzeige übernimmt NotificationManagerCompat. Sie ermitteln die Referenz auf ein solches Objekt durch Aufruf seiner statischen Methode from().

Seit Android 8 muss jede Benachrichtigung einem Benachrichtigungskanal zugeordnet werden. Dieser wird mit der NotificationManagerCompat-Methode createNotificationChannel() angelegt. Dem Konstruktor der Klasse NotificationChannel werden eine Kanal-ID, ein Klartextname sowie die Dringlichkeit übergeben. Weitere Werte, zum Beispiel Farbe, Sound und Vibrationsmuster, können Sie bei Bedarf über entsprechende set...()-Methoden konfigurieren. Da ich nicht direkt die Klassen der Plattform, sondern die Jetpack-Komponente Notifications verwende, muss ich mich übrigens nicht darum kümmern, ob auf dem ausführenden Gerät Kanäle überhaupt vorhanden sind. Die NotificationManagerCompat-Methode notify() setzt schließlich die Benachrichtigung ab.

Broadcast Receiver in der Manifestdatei definieren

Damit Android den Broadcast Receiver über einen abgeschlossenen Systemstart informiert, muss die zugehörige App die Berechtigung android.permission.RECEIVE_BOOT_COMPLETED anfordern. Dies geschieht mit einem entsprechenden <uses-permission />-Element in der Manifestdatei. RECEIVE_BOOT_COMPLETED ist eine sogenannte normale Berechtigung, was bedeutet, dass sie ohne ausdrückliche Zustimmung des Anwenders gewährt wird. Ausführliche Informationen zu Berechtigungen finden Sie in Abschnitt 4.4, »Berechtigungen«. Der Manifesteintrag für den Receiver sieht folgendermaßen aus:

<receiver android:name=".BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

Listing 4.13    Einen »Broadcast Receiver« definieren

Das Element <receiver /> kann zahlreiche Attribute erhalten. Ein paar davon werden Sie praktisch immer verwenden, andere hingegen eher selten. android:name verweist auf die voll qualifizierte Klasse, die den Receiver implementiert. Ist der Paketname leer (beginnt der Eintrag also mit einem Punkt, auf den der Klassenname folgt), wird als Paket dasjenige verwendet, das im <manifest />-Element spezifiziert ist. Dieses Attribut müssen Sie setzen.

android:enabled legt fest, ob ein Receiver vom System instanziiert werden kann (standardmäßig ist das der Fall). android:exported regelt, ob ein Receiver Nachrichten von Quellen erhalten kann, die außerhalb der eigenen App liegen. false legt fest, dass nur App-interne Komponenten Mitteilungen an den Receiver senden können. Der Standardwert hängt davon ab, ob ein Receiver Intent-Filter enthält. Ist dies nämlich nicht der Fall, kann er ausschließlich von Intents aufgerufen werden, die den exakten Klassennamen angeben. Dies impliziert, dass der Receiver nur für die anwendungsinterne Kommunikation vorgesehen ist, und deshalb ist in diesem Fall der Standardwert false. Das Vorhandensein von Intent-Filtern hingegen deutet darauf hin, dass ein Receiver Nachrichten des Systems oder von anderen Apps verarbeiten soll, daher ist in diesem Fall der Standardwert true.

Mit android:icon und android:label schließlich können Sie einem Broadcast Receiver individuelle Symbole und Bezeichnungen zuweisen. Fehlen die Attribute, werden stattdessen die korrespondierenden Einträge der App ausgewertet.

Sie haben gerade eben das Attribut android:exported kennengelernt, mit dem Sie die Nutzbarkeit von Receivern durch App-fremde Komponenten steuern können. Berechtigungen sind eine weitere Möglichkeit, den Zugriff auf Receiver zu regeln. android:permission erhält den Namen einer Berechtigung, die Broadcaster haben müssen, um einem Receiver eine Nachricht senden zu können. Wird dieses Attribut nicht gesetzt, so gelten die Berechtigungen, die innerhalb des <application />-Elements gesetzt wurden. Wurde keines der beiden Attribute gesetzt, ist ein Broadcast Receiver nicht durch eine Berechtigung geschützt.

Das Attribut android:process enthält den Namen eines Prozesses, in dem ein Broadcast Receiver ausgeführt werden sollte. Normalerweise laufen alle Komponenten einer App in ihrem Standardprozess, der den Namen des App-Packages trägt. Mit dem gleichnamigen Attribut des <application />-Elements kann für alle Komponenten ein alternativer Standardprozess gesetzt werden. Da alle Bausteine einer App das Attribut angeben können, lässt sich die Anwendung auf mehrere Prozesse verteilen. Wenn sich Komponenten mehrerer Apps einen Prozess teilen, spart dies Ressourcen. (Die Ausführung in einem bestimmten Prozess ist natürlich nur möglich, wenn der Broadcast Receiver eine entsprechende Berechtigung hat.)

Broadcast Receiver testen

Damit Apps dem Anwender keine ungewollten Aktionen unterschieben können, liefert Android Intents mit der Action ACTION_BOOT_COMPLETED erst aus, nachdem die Hauptaktivität mindestens einmal gestartet wurde. Sie müssen das Projekt deshalb auf dem Emulator oder einem echten Gerät installieren und starten. Erst dann können Sie einen Neustart auslösen. Nach Abschluss des Bootvorgangs erscheint die Benachrichtigung in der Statusleiste. Wie dies aussehen kann, zeigt Abbildung 4.7. Um den Emulator neu zu starten, klicken und halten Sie den virtuellen Power-Button (inline image), bis am rechten Bildschirmrand ein Panel eingeblendet wird – ganz wie auf echten Geräten.

Die Benachrichtigung der App »BroadcastReceiverDemo«

Abbildung 4.7    Die Benachrichtigung der App »BroadcastReceiverDemo«

Im nächsten Abschnitt stelle ich Ihnen einen weiteren Grundbaustein für Android-Apps vor. Fragmente haben mit Android-Version 3.0 zunächst auf Tablets Einzug gehalten und stehen seit Ice Cream Sandwich auch auf Smartphones zur Verfügung.

 


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