Android_Tutorial_Lektion30_fotolia_RA_Studio_46292813

Programmier Tutorial: Apps für Android entwickeln – Teil 30: Mit einem expliziten Intent eine Activity in Android starten

In dieser Lektion werden wir unsere Android App um eine zusätzliche Activity erweitern. Die neue Activity wird einen Zitattext zusammen mit einem großen Autorenbild auf dem Bildschirm des Android Geräts anzeigen. Sie wird von der MainActivity aus gestartet werden, sobald der Benutzer auf einen ListView-Eintrag klickt.

Zum Starten der neuen Activity werden wir den Intent Mechanismus von Android verwenden. Intents werden vor allem für das Starten von Activities verwendet. Durch sie können aber auch Services gestartet oder Daten an BroadcastReceiver gesendet werden.


Wir werden die neue Activity nicht nur mit Hilfe eines Intents starten, sondern ihr dabei auch durch das Intent-Objekt Daten zukommen lassen. Die so übertragenen Daten, das korrespondierende Quote-Objekt des angeklickten ListView-Eintrags, lassen wir von der Activity wieder ausgeben.

Wie dies mit Hilfe von Intents in Android realisiert wird, werden wir zuvor im theoretische Teil dieser Lektion kennenlernen. Wir werden erfahren aus welchen Komponenten ein Intent besteht, wie durch ihn eine Activity gestartet wird und welche Daten an die gestartete Activity durch den Intent übertragen werden können.

Anschließend werden wir im praktischen Teil dieser Lektion die neue Activity DetailActivity erstellen. Dazu werden wir zuerst die XML-Layout Datei und danach die Java Klasse der DetailActivity anlegen und mit Quellcode füllen. Danach werden wir die neu erstellte Activity im der AndroidManifest.xml Datei, dem App Manifest, bekanntgeben.

Nachdem alle Vorbereitungen abgeschlossen sind, werden wir die neue Activity von der MainActivity-Klasse aus per Intent starten. Das Starten werden wir vom OnItemClickListener des ListViews durchführen lassen, der überwacht, ob ein Eintrag des ListViews kurz angeklickt wurde.

Abschließend werden wir unsere Android App im Emulator auf einem Android Virtual Device ausführen und prüfen, ob die neue Activity per Intent gestartet wird und die übertragenen Daten korrekt von ihren View-Elementen ausgegeben werden.

1. Intents in Android

Intents nehmen im Android System eine sehr bedeutende Rolle ein. Mit Hilfe von Intents können klar definierte Aufgaben an andere Anwendungskomponenten delegiert werden. Eine per Intent aufgerufene Komponente führt die angeforderte Aufgabe selbständig aus und liefert, wenn erwünscht, das Ergebnis anschließend an die aufrufende Komponente zurück.

Bei diesem Vorgang tritt der Intent als Nachrichten-Objekt auf, mit dessen Hilfe eine bestimmte Aktion von einer App-Komponenten bei einer anderen App-Komponente angefordert wird. Das Intent-Objekt ist dabei die abstrakte Beschreibung des durchzuführenden Vorhabens. Auf diese Weise, also mit Hilfe von Intents, wird die bidirektionale Kommunikation zwischen App-Komponenten untereinander in Android ermöglicht.

In den meisten Fällen werden Intents zum Starten anderer Activities verwendet. Dabei kann man sie sich als Bindeglied zwischen den beiden Activities, zwischen der aufrufenden und der aufgerufenen, vorstellen. Das Intent-Objekt enthält dann in sich die Beschreibung der Aktion, die von der aufgerufenen Activity durchgeführt werden soll.

In Android werden Intents in den folgenden drei Anwendungsfällen eingesetzt:

  • Starten einer Activity – Mit Intents können Activities gestartet werden. Um eine neue Activity-Instanz zu starten, muss der startActivity() Methode ein Intent-Objekt übergeben werden. Das übergebene Intent-Objekt trägt eine Beschreibung der zu startenden Activity und die dafür benötigten Daten in sich. Falls die gestartete Activity ein Ergebnis zurückliefern soll, sobald diese beendet ist, muss anstelle der startActivity() die startActivityForResult() Methode verwendet werden. Die eigene Activity erhält dann das Ergebnis als separates Intent-Objekt in ihrer onActivityResult() Callback-Methode.

  • Starten eines Services – Ein Service ist eine Komponente die bestimmte Aufgaben im Hintergrund ohne eigene Benutzeroberfläche durchführt. Ein Service der eine einmalige Aufgabe ausführen soll, kann mit der startService() Methode gestartet werden. Der Methode muss dabei ein entsprechendes Intent-Objekt, welches den Service beschreibt und die zum Starten benötigten Daten in sich trägt, übergeben werden. Falls der Service eine Client-Server Schnittstelle besitzen soll, muss er mit der bindService() Methode und dem entsprechenden Intent aufgerufen werden.

  • Versenden einen Broadcasts – Ein Broadcast ist eine Nachricht die jede Android App empfangen kann. Das Android System liefert verschiedene Broadcasts zu Systemereignissen aus, wie bspw. wenn das System neu gestartet wird oder das Android Gerät beginnt aufzuladen. Eigene Broadcasts können durch Übergabe eines entsprechenden Intent-Objekts an die Methoden sendBroadcast() oder sendOrderedBroadcast() an andere Apps ausgestrahlt werden.

1.1 Das Zusammenspiel von Activities und Intents in Android

Normale PC-Anwendungen bestehen meist aus einem Hauptbildschirm, in dem der Benutzer seine Aktionen durchführen kann. Der Hauptbildschirm wird nur sehr selten verlassen. Android Apps sind anders aufgebaut. Sie bestehen aus einer beliebigen Menge an Bildschirmseiten. Jede Bildschirmseite ist einer bestimmten Aktivität gewidmet, daher die Bezeichnung Activity.

Android Apps bestehen meist aus mehreren Activities, von denen jede genau für eine exakt formulierte Aufgabe verantwortlich ist. Obwohl alle Activities zusammen die Android App ergeben, sind sie nur lose in die Anwendung eingebunden. Jede Activity agiert als eine in sich geschlossene Komponente. Und genau daraus ergibt sich der große Nutzen des Android Activity Mechanismus.

Denn aus diesem Grund können Activities von anderen App-Komponenten aufgerufen werden, sogar von Komponenten anderer Anwendungen. Der Aufruf erfolgt über den globalen Aufrufmechanismus von Android mit Hilfe von Intents. Es spielt dabei keine Rolle, ob eine App-eigene Activity oder eine Activity einer fremden Activity aufgerufen wird.

Wie der Aufruf der Activity vom Android System ausgeführt wird, ist von der Art des dazu verwendeten Intents abhängig. Android unterscheidet dabei zwischen den folgenden beiden Intent-Arten:

  • Expliziter Intent – Bei einem expliziten Intent wird direkt angegeben, welche App-Komponente die angeforderte Aufgabe erledigen soll. Dies geschieht durch Angabe des Package-Namen der App oder durch den vollqualifizierenden Namen der entsprechenden Klasse. In den meisten Fällen werden explizite Intents für das Starten von App-eigener Komponenten eingesetzt, da dafür der Klassenname der Activity oder des Services bekannt sein muss und nur dem Entwickler der App diese auch bekannt sind.

    Mit einem expliziten Intent startet man bspw. eine neue Activity der eigenen App als Reaktion auf eine Benutzereingabe oder einen Service der den Download einer Datei im Hintergrund ausführt.

  • Impliziter Intent – Es wird keine konkrete Activity als Empfänger (Adressat) angegeben. Dafür wird dem Android System aber mitgeteilt welche Aktion durchgeführt werden soll, durch Angabe von action, data und category. Das Android System bestimmt anschließend welche der auf dem Gerät vorhandenen Activities die Aktion durchführen können. Damit dieser Mechanismus reibungslos funktioniert, benötigt das Android System die Unterstützung der Activities, die mit Intent-Filtern über ihre Fähigkeiten berichten.

    Möchte man bspw. dem Nutzer eine bestimmte Position auf einer Karte zeigen, kann man diese Aufgabe mittels impliziten Intent an eine App-fremden Komponente delegieren. Dieser muss dazu die auszuführende Aktion durch Angabe der Parameter action, data und category ausreichend beschrieben worden sein.

1.2 Aufrufen einer Activity mit Hilfe eines expliziten Intents

Wir werden in dieser Lektion eine neue Activity mittels expliziten Intent starten lassen. Das Intent-Objekt wird dabei die lose Verbindung zwischen der aufrufenden (Adressant) und der aufgerufenen (Adressat) Activity darstellen. Diese Verbindung ist exakt definiert, so dass zum Starten einer Activity mit Hilfe eines expliziten Intents immer die folgenden Schritte durchzuführen sind:

  1. Erzeugen eines Intent-Objekts durch Angabe der aufzurufenden Activity mit vollqualifizierenden Klassennamen.
  2. Sollen der Activity auch Daten übermittelt werden, müssen diese per putExtra() in dem Intent abgelegt werden.
  3. Abschicken des Intents mit Hilfe der startActivity() oder startActivityForResult() Methode.

Mit folgendem Quellcode wird eine neue Activity per expliziten Intent gestartet:

Intent explicitIntent = new Intent(MainActivity.this, OtherActivity.class);
explicitIntent.putExtra(Intent.EXTRA_TEXT, "Diese Daten empfängt die andere Activity.");
startActivity(explicitIntent);

Der im oberen Quellcode erzeugte explizite Intent enthält den Name der zu startenden App-Komponente (Component Name) und einen kurzer Text als zusätzliche Information (Extras) in sich. Wir werden nun genauer auf den Inhalt des erzeugten Intents eingehen.

  • Component Name – Über das Component Name-Feld wird dem Intent-Objekt mitgeteilt welche App-Komponente gestartet werden soll. Diese Angabe ist zwar optional, jedoch von entscheidender Bedeutung für den Intent. Denn durch Angabe der Component Name wird der Intent zu einem expliziten Intent, mit der Konsequenz, dass der Intent nur an die App-Komponente ausgeliefert wird, deren vollqualifizierender Name dem Component Name entspricht.

    Ohne Angabe des Component Name bleibt der Intent implizit und das Android System entscheidet welche App-Komponente den Intent erhalten soll. Dies geschieht auf Grundlage der anderen Intent-Informationen wie action, data und category. Daher sollte immer der Component Name angegeben werden, wenn eine bestimmte App-Komponente der eigenen Anwendung per Intent aufgerufen werden soll.

    Der Component Name kann dem Intent auf zwei Wege zugewiesen werden. Entweder mit Hilfe des Konstruktors direkt beim Erzeugen der Intent-Instanz oder über eine der folgenden Methoden setComponent(), setClass() oder setClassName(), die auf dem Intent-Objekt aufgerufen werden. In dem Component Name-Feld des Intents wird dann ein ComponentName-Objekt abgelegt, das den vollqualifizierenden Namen der Klasse der aufzurufenden App-Komponenten und den Package-Namen der App enthält.

  • Extras – In das Extras-Feld können Schlüssel-Wert Paare (key-value pairs) abgelegt werden, die für die Ausführung der angeforderten Aufgabe benötigt werden. Die zusätzlichen Daten können mit Hilfe von verschiedenen putExtra() Methoden in das Intent-Objekt eingefügt werden. Jede dieser Methoden erwartet zwei Parameter: den Schlüssel und den dazugehörigen Wert. Es ist auch möglich alle Schlüssel-Wert Paare vorher in einem Bundle-Objekt zu speichern und dieses anschließend in das Intent-Objekt mittels der putExtra() Methode einzufügen.

    Von der Intent-Klasse werden bereits viele EXTRA_* Konstanten definiert. Diese können als Schlüssel zum Hinterlegen oft verwendeter Werte genutzt werden. So kann bspw. für den Schlüssel EXTRA_EMAIL die E-Mail Adresse oder für EXTRA_SUBJECT der E-Mail Betreff hinterlegt werden. Um Werte in das Extras-Feld abzuspeichern, können aber auch eigene Schlüssel verwendet werden. Diese müssen dann den Package-Namen als Präfix enthalten:

    public static final String EXTRA_QUOTE_TEXT = "de.codeyourapp.zitate.EXTRA_QUOTE_TEXT";

Nachdem der Intent abgeschickt wurde, kümmert sich das Android System um die weitere Verarbeitung. Es wird nach der auszuführenden Activity gesucht und, wenn eine passende gefunden wurde, diese gestartet.

1.3 Empfangen eines expliziten Intents in der aufgerufenen Activity

Die per Intent gestartete Activity kann auf das Intent-Objekt und somit auch auf dessen Daten zugreifen. Dies ist nicht in jedem Fall notwendig, bspw. wenn die Activity nur gestartet werden sollte und ihre Aufgabe ohne zusätzliche Daten ausführen kann. Werden jedoch weitere Daten zum Ausführen der Aufgabe benötigt, können diese aus dem Intent-Objekt extrahiert werden.

Mit folgendem Code wird das erhaltene Intent-Objekt angefordert und auf dessen EXTRA-Daten zugegriffen:

Intent receivedIntent = OtherActivity.getIntent();
if (receivedIntent != null && receivedIntent.hasExtra(Intent.EXTRA_TEXT)) {
    String receivedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT);
    // Die empfangenen Daten können nun verwendet werden ...
}

In Zeile 1 wird das empfangene Intent-Objekt mit Hilfe der getIntent() Methode angefordert. Diese Methode kann innerhalb der gestarteten Activity aufgerufen werden. Dies soll durch den Aufruf OtherActivity.getIntent() verdeutlicht werden. Im eigenen Quellcode würde der Aufruf einfach getIntent() lauten.

Bevor auf die Daten des Intent-Objekt zugegriffen werden kann, muss zunächst überprüft werden, ob überhaupt eine Intent-Objekt von der Activity empfangen wurde und falls dies so ist, ob diesem Objekt auch EXTRA-Daten bei der Erstellung des Intents hinzugefügt wurden. Die eben beschriebene Prüfung findet in Zeile 2 statt.

In Zeile 3 wird mit Hilfe der getStringExtra() Methode der für den EXTRA_TEXT-Schlüssel hinterlegte Wert ausgelesen und in einer String-Variable gespeichert. Der empfangene Text kann nun von der gestarteten Activity weiterverwendet werden, bspw. um ihn mit Hilfe eines TextView-Elements an den Benutzer auszugeben.

Auf die oben beschriebene Weise werden in Android Activities mit Hilfe von expliziten Intents gestartet und Daten an sie im Extras-Feld des Intent-Objekts übertragen. Wir werden nun dieses Wissen in die Praxis umsetzen und eine neue Activity mittels Intent starten lassen. Doch bevor wir dies tun können, müssen wir die Activity erstellen. Dies werden wir im nächsten Abschnitt vornehmen.

2. Erstellen der DetailActivity in Android Studio

Wir werden nun im praktischen Teil dieser Lektion eine neue Activity, die DetailActivity, erstellen. Die neue Activity wird Details zu dem jeweils angeklickten Zitat des ListViews der MainActivity anzeigen. Die DetailActivity werden wir mit Hilfe eines expliziten Intents vom Android System starten lassen.

Das Erstellen der DetailActivity wird in zwei Arbeitsschritten erfolgen:

  1. Erstellen der XML-Layout Datei – In dem layout-Ordner lassen wir von Android Studio eine neue XML-Layout Datei mit dem Dateinamen activity_detail.xml erstellen. Anschließend definieren wir in der erstellten Layout Datei die grafische Benutzeroberfläche unserer Detail-Activity per Android XML-Vokabular.
  2. Erstellen der Java Klassendatei – In dem package-Ordner unseres Projekts lassen wir von Android Studio eine neue Java Klassendatei mit dem Dateinamen DetailActivity.java erstellen. Anschließend implementieren wir in der erstellten Java Klasse die Programmlogik unserer Detail-Activity.

Beginnen wir nun mit dem ersten Arbeitsschritt.

2.1 Erstellen der XML-Layout Datei activity_detail.xml

Wir werden nun für unsere DetailActivity eine XML-Layout Datei erstellen und in ihr ein einfaches UI-Layout definieren. Dieses Layout werden wir anschließend der Activity als Benutzeroberfläche zuweisen. Die zu erstellende XML-Layout Datei muss in dem res/layout/ Ressourcen-Ordner abgelegt werden. Dieses Verzeichnis existiert bereits, wir hatten es in einer vorherigen Lektion angelegt, und muss daher nicht mehr von uns erstellt werden.

Hinweis: Alle XML-Layout Dateien müssen in dem layout-Ordner des Android Projekts abgelegt werden. Nur Layout Dateien die sich im res/layout/ Ordner befinden, werden beim Kompilieren der App in eine View-Ressource umgewandelt. Zudem wird beim Kompilieren auch die lokale Ressourcen-Klasse R generiert, welche die Ressourcen-IDs für alle Ressourcen innerhalb des gesamten res/ Verzeichnisses enthält.

Wir erstellen nun die XML-Layout Datei activity_detail.xml, mit welcher wir das Aussehen unserer DetailActivity definieren. Dazu führen wir die folgenden Schritte aus:

  1. Mit der rechten Maustaste auf den Ordner layout/ in dem Project Tool Window klicken.
  2. Anschließend den Eintrag New des Kontext-Menüs anklicken.
  3. Danach auf Layout resource file klicken.
create_detail_layout

Erstellen eines Layout Resource File für die activity_detail.xml XML-Layout Datei

Anschließend öffnet sich der New Layout Resource File-Dialog, der uns bei der Erstellung der XML-Ressourcen Datei unterstützt. Wir müssen nur die beiden Felder des Dialogs ausfüllen.

In dem New Layout Resource File-Dialog nehmen wir nun die folgenden Einstellungen vor:

  1. Als Dateinamen tragen wir activity_detail.xml in das Feld File name ein.
  2. Den Wert für das Root element (Wurzelelement des UI-Layouts) lassen wir auf LinearLayout stehen.
create_detail_layout_dialog

Dateinamen und Wurzelelement der neuen XML-Layout Datei vorgeben

Anschließend bestätigen wir den New Layout Resource File-Dialog mit einem Klick auf den OK Button, woraufhin die neue XML-Ressourcen Datei automatisch von Android Studio erstellt und im Editorfenster der IDE geöffnet wird.

Falls die Datei nicht automatisch geöffnet wurde, führen wir das Öffnen manuell durch. Dazu klicken wir doppelt auf ihren Dateinamen activity_detail.xml im Project Tool Window von Android Studio. Die Datei befindet sich im res/layout/ Ordner unseres Projekts.

Standardmäßig öffnet sich das Editorfenster in der Design-Ansicht. Damit der XML-Code der Layout Datei angezeigt wird, müssen wir unten im Editorfenster den Tab Text anklicken.

Den generierten XML-Code löschen wir vollständig und fügen an dessen Stelle den folgenden XML-Code ein:

activity_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar_detail_activity"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:layout_marginBottom="@dimen/default_margin"
        android:background="@color/colorPrimary"
        android:elevation="@dimen/toolbar_elevation"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <ImageView
        android:id="@+id/imageview_detail_activity"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_margin="@dimen/default_margin"
        android:layout_weight="2"
        android:src="@drawable/goethe" />

    <TextView
        android:id="@+id/textview_detail_activity"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_margin="@dimen/default_margin"
        android:layout_weight="1"
        android:scrollbars="vertical"
        android:text="@string/sample_quote"
        android:textAlignment="center"
        android:textSize="@dimen/quote_text_font_size"
        android:textStyle="bold|italic" />

</LinearLayout>

Mit dem oberen Quellcode definieren wir das UI-Layout für unsere DetailActivity. Die visuelle Struktur der Activity besteht aus je einem LinearLayout-, Toolbar-, ImageView– und TextView-Element. Das LinearLayout-Element ist das Wurzelelement des XML-Layouts und nimmt in sich die drei anderen UI-Elemente auf.

Für die drei inneren Layout-Elemente, das Toolbar-, ImageView– und TextView-Element, haben wir jeweils eine ID anlegen lassen. Dazu verwenden wir die folgende Schreibweise: android:id=“@+id/element_name“.

Über die ID kann später auf das jeweilige View-Objekt zur Laufzeit zugegriffen werden. Durch das @ Symbol weiß der XML-Parser, dass es sich um eine ID-Ressource handelt. Das + Symbol gibt an, dass die ID-Ressource in der R.java Datei neu angelegt werden muss.

Das LinearLayout ordnet seine inneren Elemente vertikal an. Dabei wird jedes Element horizontal zentriert. Als Bildschirmplatz nimmt das LinearLayout die gesamte zur Verfügung stehende Höhe und Breite ein. Die Toolbar ist das erste innere Element des LinearLayout. Sie besitzt exakt dieselben Eigenschaften, wie die Toolbar unserer MainActivity.

Nach der Toolbar folgt ein ImageView-Element, welches die gesamte Bildschirmbreite einnimmt. Als Wert für die Höhe des ImageViews haben wir den Wert 0 px und als Gewichtung den Wert 2 festgelegt. Was dies bedeutet werden wir gleich ausführlich besprechen. Der ImageView wird standardmäßig ein Bild von Goethe anzeigen, welches wir aber zur Laufzeit mit den jeweils passenden Autorenbild austauschen werden.

Als letztes inneres Element folgt ein TextView. Auch dieser nimmt wie die Toolbar und der ImageView die komplette Breite des Bildschirms in Anspruch. Als Wert für die Höhe ist 0 px und für die Gewichtung der Wert 1 vorgegeben worden. Dies ist erforderlich, damit das Android System die zur Verfügung stehenden Bildschirmhöhe zwischen den beiden Elementen ImageView und TextView dynamisch aufteilen kann.

Die jeweilig nutzbare Bildschirmhöhe ergibt sich dabei aus folgender Formel:

Nutzbare Bildschirmhöhe = Gewichtung des Kindelements / Summe aller Gewichtungen im LinearLayout

Für den ImageView ergibt sich die nutzbare Bildschirmhöhe wie folgt: Gewichtung des ImageViews ist 2, Summe aller Gewichtungen im LinearLayout ist 1 + 2 = 3, somit kann der ImageView 2/3 der restlichen Bildschirmhöhe nutzen. Der TextView besitzt eine Gewichtung von 1 und erhält daher 1/3 der restlichen Bildschirmhöhe zugewiesen.

Die Toolbar besitzt keine Gewichtung, dafür aber eine Höhenangabe. Dadurch kann die restliche Bildschirmhöhe, die dynamisch zwischen den ImageView und TextView aufgeteilt wird, exakt vom Android System bestimmt werden. Sie ergibt sich aus der gesamten Bildschirmhöhe verringert um die Höhe der Toolbar.

In Android Studio sollte die activity_detail.xml Datei nun wie folgt aussehen:

activity_detail_layout

Die XML-Layout Datei activity_detail.xml mit den vorgenommenen Änderungen

Nun haben wir das UI-Layout für unsere DetailActivity angelegt. Als Nächstes werden wir die DetailActivity-Klasse erstellen, die das eben erstellte XML-Layout zur Erzeugung ihrer Benutzeroberfläche nutzen wird.

2.2 Erstellen der Java Klassendatei DetailActivity.java

Wir werden nun den zweiten Arbeitsschritt ausführen und die Java Klasse DetailActivity unserem Android Studio Projekt hinzufügen. Sie wird für das Darstellen des im ListView angeklickten Zitats verantwortlich sein. Dafür wird sie das eben erstellte XML-Layout als ihre Benutzeroberfläche verwenden.

Um die neue Klasse DetailActivity anzulegen, muss eine neue Java Klassendatei in dem Package-Ordner des Projekts erstellt werden. Dafür gibt es zwei Vorgehensweisen: über die obere Menüleiste oder über den Package-Ordner in der Project-Ansicht. Wir werden den zweiten Weg wählen, da er intuitiver und weniger fehleranfällig ist.

Als Erstes muss dafür die Project-Ansicht exakt so wie in Lektion 4 Abschnitt 2 beschrieben aufgeklappt werden. In diesen Package-Ordner werden wir nun die neu Klassendatei mit Hilfe des Create New Class-Dialog von Android Studio anlegen lassen.

Die Klassendatei DetailActivity.java legen wir nun folgendermaßen an:

  1. Mit der rechten Maustaste auf den Package-Ordner de.codeyourapp.zitate klicken.
  2. Anschließend den Eintrag New des Kontext-Menüs anklicken.
  3. Danach auf den Eintrag Java Class klicken.
create_detail_activity

Erstellen der DetailActivity-Klasse in den Package-Ordner des Projekts

Anschließend öffnet sich der Create New Class-Dialog, der uns bei der Erstellung der neuen Java Klasse unterstützt. Wir müssen nur einige Felder des Dialogs ausfüllen.

In dem Create New Class-Dialog nehmen wir nun die folgenden Einstellungen vor:

  1. Als Klassennamen tragen wir in das Feld Name DetailActivity ein.
  2. Den Wert für Kind lassen wir auf Class stehen.
  3. Die Felder Superclass und Interface(s) lassen wir leer.
  4. Als Package sollte bereits automatisch unser Package-Ordner de.codeyourapp.zitate eingetragen sein.
  5. Alle anderen Einstellungen übernehmen wir unverändert.
  6. Den Dialog bestätigen wir mit einem Klick auf den OK Button.
create_detail_activity_dialog

Den Namen für die DetailActivity-Klasse vorgeben

Android Studio legt nun automatisch die neue Java Klasse an. Dabei wird auch der minimale Quellcode für das Klassengerüst erzeugt. Diesen benötigen wir aber nicht und werden ihn daher vollständig durch unseren eigenen Code ersetzen.

Dazu öffnen wir die Klassendatei DetailActivity.java im Editorfenster von Android Studio mit einem Doppelklick auf den entsprechenden Eintrag in der linken Project-Ansicht.

Anschließend ersetzen wir ihren gesamten Quelltext mit folgendem Code:

DetailActivity.java

package de.codeyourapp.zitate;

import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.text.method.ScrollingMovementMethod;
import android.widget.ImageView;
import android.widget.TextView;

public class DetailActivity extends AppCompatActivity {

    public static final String EXTRA_IMAGE_ID = "de.codeyourapp.zitate.EXTRA_IMAGE_ID";
    public static final String EXTRA_QUOTE_AUTHOR = "de.codeyourapp.zitate.EXTRA_QUOTE_AUTHOR";
    public static final String EXTRA_QUOTE_TEXT = "de.codeyourapp.zitate.EXTRA_QUOTE_TEXT";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);

        // Initialisieren der App Bar und Aktivieren des Up-Buttons
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_detail_activity);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);

        // Füllen der View-Elemente mit den empfangenen Daten des Intent-Objekts
        Intent receivedIntent = getIntent();
        if (receivedIntent != null && receivedIntent.hasExtra(EXTRA_IMAGE_ID)) {

            String imageID = receivedIntent.getStringExtra(EXTRA_IMAGE_ID);
            String quoteAuthor = receivedIntent.getStringExtra(EXTRA_QUOTE_AUTHOR);
            String quoteText = receivedIntent.getStringExtra(EXTRA_QUOTE_TEXT);

            actionBar.setTitle(quoteAuthor);

            TextView textView   = (TextView) findViewById(R.id.textview_detail_activity);
            textView.setText("\"" + quoteText + "\"");
            textView.setMovementMethod(new ScrollingMovementMethod());

            ImageView imageView  = (ImageView) findViewById(R.id.imageview_detail_activity);
            int imageResourceId = getResources().getIdentifier(imageID, "drawable", getPackageName());
            if (imageResourceId > 0) {
                imageView.setImageResource(imageResourceId);
            }
        }
    }

}

In Zeile 1 definieren wir zu welchem Package die DetailActivity-Klasse gehört. An dieser Stelle muss der Package-Name verwendet werden, der auch in dem Project-View angezeigt wird.

In den Zeilen 3 bis 10 befinden sich die Import-Anweisungen. Durch sie werden die benötigten externen Klassen eingebunden. Auf diese Weise ist es möglich, auf sie mit ihren einfachen Namen (z.B. Bundle) zuzugreifen, anstelle den vollqualifizierten Namen (z.B. android.os.Bundle) verwenden zu müssen.

In den Zeilen 12 bis 51 wird die Klasse DetailActivity definiert. Als Super-Klasse wurde die Klasse AppCompatActivity gewählt, welche indirekt von der Klasse Activity abgeleitet ist. Somit besitzt unsere DetailActivity-Klasse alle Eigenschaften der Activity-Klasse und zusätzliche Kompatibilitätsmechanismen der AppCompatActivity-Klasse, wodurch unsere App auch zu älteren Android Versionen kompatibel bleibt.

In den Zeilen 14 bis 16 werden drei Konstanten definiert, durch die später Inhalte im Extra-Feld des Intent-Objekts abgelegt und an die DetailActivity übermittelt werden können. Die Konstanten dienen dabei als Schlüssel unter denen einfache Werte hinterlegt werden können.

Die DetailActivity-Klasse besitzt genau eine Methode, die onCreate() Methode. Sie wird in den Zeilen 19 bis 49 definiert und ist eine Callback-Methode des Android Activity Lifecycles. Sie wird von dem Android System aufgerufen, wenn die Activity erstellt wird. Daher muss jede Activity in Android mindestens diese Callback-Methode implementieren.

In ihr muss die grundlegende Initialisierung der Activity erfolgen, wie bspw. Membervariablen instanziieren, Elemente der Benutzeroberfläche laden oder Hintergrund-Threads initialisieren. Zudem kann in ihr der vorherige Zustand der Activity mit Hilfe des Bundle-Objekts savedInstanceState wiederhergestellt werden.

Die onCreate() Methode

Wir werden nun die onCreate() Methode genauer betrachten. Sie wird in den Zeilen 19 bis 49 der DetailActivity-Klasse definiert. Ihre Aufgabe ist das Darstellen des angeklickten Zitats. Wie dies erfolgt, werden wir nun beschreiben. Die Methode ist daher zur Übersichtlichkeit an dieser Stelle nochmals aufgeführt:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_detail);

    // Initialisieren der App Bar und Aktivieren des Up-Buttons
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_detail_activity);
    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);

    // Füllen der View-Elemente mit den empfangenen Daten des Intent-Objekts
    Intent receivedIntent = getIntent();
    if (receivedIntent != null && receivedIntent.hasExtra(EXTRA_IMAGE_ID)) {

        String imageID = receivedIntent.getStringExtra(EXTRA_IMAGE_ID);
        String quoteAuthor = receivedIntent.getStringExtra(EXTRA_QUOTE_AUTHOR);
        String quoteText = receivedIntent.getStringExtra(EXTRA_QUOTE_TEXT);

        actionBar.setTitle(quoteAuthor);

        TextView textView   = (TextView) findViewById(R.id.textview_detail_activity);
        textView.setText("\"" + quoteText + "\"");
        textView.setMovementMethod(new ScrollingMovementMethod());

        ImageView imageView  = (ImageView) findViewById(R.id.imageview_detail_activity);
        int imageResourceId = getResources().getIdentifier(imageID, "drawable", getPackageName());
        if (imageResourceId > 0) {
            imageView.setImageResource(imageResourceId);
        }
    }
}

Die Methode besitzt den formalen Parameter savedInstanceState, der vom Typ Bundle ist. Bei Methodenaufruf wird über ihn der vorherige Zustand der Activity übergeben. In Zeile 2 wird die Implementation der onCreate() Methode der Super-Klasse aufgerufen. Sie führt die grundlegende Initialisierung der Activity durch. Würde der Aufruf nicht erfolgen, wäre unsere App nicht lauffähig und eine Exception, die SuperNotCalledException, würde geworfen werden.

In Zeile 3 wird das UI-Layout aus der vorher erstellten XML-Layout Datei geladen. Dazu übergeben wir der setContentView() Methode die Resource-ID der erstellten Layout-Ressource.

Auf die entsprechende Ressource wird folgendermaßen im Code referenziert:

[<package_name>.]R.<resource_type>.<resource_name>

  • <package_name> ist der Name des Packages, in welchem sich die Ressource befindet. Wird bei Ressourcen aus dem eigenen Package nicht benötigt.

  • R ist die Ressourcen-Klassendatei, in der alle Ressourcen-IDs verwaltet werden. Sie sollte niemals von Hand verändert werden, da sie von dem aapt-Programm bei jedem Kompilieren des Projekts neu generiert wird. Jede Änderung würde daher beim nächsten Kompilieren automatisch überschrieben werden.

  • <resource_type> ist eine Unterklasse von R, die für den jeweiligen Ressourcen-Typ steht. In unserem Fall ist dies layout, da wir auf eine XML-Layout Datei zugreifen möchten.

  • <resource_name> ist entweder der Dateiname der Ressource (ohne Dateinamenserweiterung) oder der Wert des android:name-Attributs des XML-Elements (bei einfachen Werten, z.B. Strings). In unserem Fall ist es der Dateiname der XML-Layout Datei activity_detail.xml ohne Dateiendung, also nur activty_detail. Insgesamt ergibt sich daraus: R.layout.activity_detail als Referenz zur Layout Datei.

In den Zeilen 6 bis 9 wird das Toolbar-Objekt als App Bar für die Activity aktiviert. Dabei wird zuerst die Referenz für die Toolbar-Instanz mit Hilfe der findViewById() Methode angefordert. Nach der Toolbar-Instanz wird mittels der Ressourcen-ID R.id.toolbar_detail_activity gesucht. Anschließend wird die setSupportActionBar() Methode aufgerufen und ihr die erhaltene Toolbar-Instanz übergeben. Auf diese Weise wird das Toolbar-Objekt als App Bar für die DetailActivity aktiviert. Für die App Bar wird anschließend der UP-Button aktiviert.

In den Zeile 12 bis 30 wird das empfange Intent-Objekt angefordert, dessen Inhalt ausgelesen und damit die View-Elemente der DetailActivity gefüllt. Dabei wird zuerst mit Hilfe der getIntent() Methode das Intent-Objekt angefordert, durch welches die Activity gestartet wurde. In diesem Intent-Objekt sind zusätzliche Daten übertragen worden.

In den Zeilen 15 bis 17 wird der Inhalt des Extra-Felds des Intent-Objekts mit Hilfe der drei oben angelegten Konstanten ausgelesen. Die Daten sind in Form von Schlüssel-Wert Paaren im Intent enthalten. Mit den drei Schlüsseln und der getStringExtra() Methode kann auf die im Intent-Objekt hinterlegten Werte zugegriffen werden. Wie die Werte in das Intent-Objekt abgelegt werden, werden wir weiter unten beschreiben, wenn wir den expliziten Intent in der MainActivity-Klasse erzeugen.

In Zeile 19 wird der Name des Autoren als neuer Titel für die App Bar festgelegt. Der Autorenname wurde vorher aus dem empfangenen Intent-Objekt ausgelesen.

In den Zeilen 21 bis 23 wird der empfangene Zitattext als neuer TextView-Inhalt festgelegt. Dabei wird zuerst nach dem TextView-Objekt mit der findViewById() Methode und der Ressourcen-ID R.id.textview_detail_activity gesucht. Anschließend wird als neuer Inhalt mit Hilfe der setText() Methode der empfangene Zitattext festgelegt und die Scrollfunktion des TextViews aktiviert, falls der Text zu lang für das Textfeld sein sollte.

In den Zeilen 25 bis 29 wird das anzuzeigende Bild des ImageViews vorgegeben. Dazu wird zuerst über die getIdentifier() Methode die Ressourcen-ID des auszugebenden Autorenbilds bei den System Resources angefragt. Dabei übergeben wir der Methode den Namen der Bild-Ressource und den Ordner (drawable), in welchem sich diese befindet. Über die zurückerhaltene Ressourcen-ID wird schließlich dem ImageView das darzustellende Autorenbild zugewiesen. Falls für die angefragte Bild-Ressource keine ID gefunden werden kann (entspricht dem Rückgabewert 0), wird kein Autorenbild zugewiesen und stattdessen das in der XML-Layout Datei vorgegebene Bild verwendet.

In Android Studio sollte die DetailActivity.java Klassendatei wie folgt aussehen:

detail_activity_created_code

Die Klassendatei DetailActivity.java mit dem eingefügten Quellcode

In der oberen Abbildung ist die DetailActivity.java Klassendatei dargestellt. Es muss unbedingt darauf geachtet werden, dass sich die neue Klasse in dem Package-Ordner de.codeyourapp.zitate befindet. Zur Kontrolle kann auf den oberen Projektstruktur-Reiter geklickt werden, um die aktuelle Struktur unseres Android Projekts anzuzeigen.

Jetzt haben wir die DetailActivity-Klasse zusammen mit ihrer XML-Layout Datei erstellt. Unser Android Projekt verfügt damit über eine weitere Activity. Bevor wir die DetailActivity jedoch starten können, ist noch eine weiterer wichtiger Schritt notwendig. Und zwar muss die neue Activity in der Schaltzentrale unserer Anwendung, dem App Manifest, bekannt gegeben werden. Dies werden wir im nächsten Abschnitt vornehmen.

3. Bekanntgeben der DetailActivity im App Manifest

Bevor wir die DetailActivity mittels expliziten Intents starten können, müssen wir sie dem Android System bekanntgeben. Die Bekanntgabe muss in der AndroidManifest.xml Datei, der Schaltzentrale unserer Android Anwendung, erfolgen. Diesen Schritt werden wir jetzt ausführen und die neue Activity bekanntgeben.

Dazu öffnen wir nun die App Manifest-Datei im Editorfenster von Android Studio durch einen Doppelklick auf die entsprechende Datei in der Project-Ansicht. Sie befindet sich in dem app/src/main/ Ordner unseres Android Studio Projekts.

Anschließend fügen wird die markierten Zeilen in den XML-Code der AndroidManifest.xml Datei ein:

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.codeyourapp.zitate">

    <!-- Diese Genehmigung wird für das Öffnen von Network Sockets benötigt. -->
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".DetailActivity"
            android:parentActivityName=".MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".MainActivity" />
        </activity>

    </application>

</manifest>

In dem oberen XML-Code der AndroidManifest.xml Datei ist die DetailActivity bereits bekanntgegeben worden. Das <application> Element des App Manifests enthält nun zwei innere <activity> Elemente, mit deren Hilfe die jeweilige Activity dem Android System bekanntgegeben wird.

Hinweis: Alle Activities der App müssen durch ein solches <activity> Element repräsentiert sein. Wird eine Activity nicht auf diese Art bekannt gegeben, wird sie vom Android System nicht gesehen und kann daher von diesem niemals gestartet werden.

Der Haupt-Einstiegspunkt unserer Anwendung, die MainActivity, ist in den Zeilen 15 bis 22 bekanntgegeben worden. Sie ist die Activity, die geöffnet werden soll, wenn der Benutzer unsere App über das Launcher-Symbol startet. Dies erfolgt über das erste <activity> Element, welches wir bereits in einer sehr frühen Lektion dem App Manifest hinzugefügt hatten.

  • Das erste <activity> Element – Das erste <activity> Element besitzt das Attribut android:name. Diesem Attribut muss der Name der Klasse zugewiesen werden, welche die Activity implementiert. Dabei sollte der vollqualifizierende Klassenname (de.codeyourapp.zitate.MainActivity) verwendet werden. Ist in dem <manifest> Element das package Attribut gesetzt, kann auch die Kurzschreibweise (.MainActivity) genutzt werden. Dabei wird der Klassenname an den Package-Namen angehängt.

  • Das <intent-filter> Element – In dem ersten <activity> Element befindet sich ein <intent-filter> Element. Über Intents werden Activities gestartet. Mit <intent-filter> Elementen wird vorgegeben auf welche Arten von Intents die Activity antworten kann. Das Android System weiß dadurch genau, wann die jeweilige Activity gestartet werden kann bzw. soll. Die <intent-filter> werden über <action>, <category> und <data> Elemente definiert.

    • Das <action> Element – Dem <action> Element weisen wir mit android.intent.action.MAIN die Konstante ACTION_MAIN zu. Somit signalisieren wir dem Android System, dass die MainActivity der Haupt-Einstiegspunkt unserer App ist.

    • Das <category> Element – Dem <category> Element weisen wir mit android.intent.category.LAUNCHER die Konstante CATEGORY_LAUNCHER zu und geben damit an, dass der Activity-Icon in den App Launcher des Android Systems platziert werden soll. Wurde für das <activity> Element kein Icon vorgegeben, wird er Icon des <application> Elements verwenden. Dies ist bei uns der Fall.

Das Bekanntgeben der neuen Activity, der DetailActivity, erfolgt in den Zeilen 24 bis 30 über das zweite <activity> Element. Mit dessen Hilfe festgelegt wird, welche Klasse die DetailActivity implementiert und welche Activity ihre Eltern-Activity ist, zu der mittels Up-Button zurück navigiert werden kann.

  • Das zweite <activity> Element – Das zweite <activity> Element besitzt die beiden Attribute android:name und android:parentActivityName. Dem android:name Attribut ist der Name der Klasse zugewiesen worden, welche die DetailActivity implementiert. Da in dem <manifest> Element das package Attribut gesetzt ist, wurde dafür wieder die Kurzschreibweise (.DetailActivity) gewählt. Dabei wird der Klassenname automatisch von Android Studio an den Package-Namen angehängt.

    Dem android:parentActivityName Attribut ist der Klassenname ihrer Eltern-Activity (.MainActivity) zugewiesen worden. Dadurch wird die MainActivity zur Eltern-Activity der DetailActivity oder umgekehrt ausgesprochen die DetailActivity zur Kind-Activity der MainActivity. Dies ist für die Navigation per Up-Button von großer Bedeutung.

  • Das <meta-data> Element – In dem zweiten <activity> Element befindet sich ein <meta-data> Element, welches über die beiden Attribute <android:name> und <android:value> verfügt. Das Element wird benötigt, um die Kompatibilität unserer App auf älteren Android Geräten sicherzustellen, da das android:parentActivityName Attribut erst in Android 4.1 (API Level 16) eingeführt wurde.

    Durch Definieren eines Name-Wert Paares (name-value pairs) kann auch für ältere Android Geräte die Eltern-Activity unserer DetailActivity vorgegeben werden. Dazu weisen wir dem <android:name> Attribut mit android.support.PARENT_ACTIVITY die Konstante PARENT_ACTIVITY zu und dem <android:value> Attribut mit .MainActivity den Namen der MainActivity-Klasse zu.

Die AndroidManifest.xml Datei sollte in Android Studio nun wie folgt aussehen:

android_manifest_detailactivity

Die AndroidManifest.xml Datei mit den vorgenommenen Änderungen

In der oberen Abbildung ist die AndroidManifest.xml Datei zu sehen. Das zweite <activity> Element wurde bereits eingefügt und ist von einem blauen Rahmen umschlossen (Markierung A). Die erstellte DetailActivity wurde auf diese Weise dem Android System mittels App Manifest bekannt gegeben. Sie kann jetzt von uns per expliziten Intent gestartet werden.

Im nächsten Abschnitt werden wir genau dies tun und die DetailActivity von der MainActivity aus starten lassen. Ihr Aufruf wird dabei durch einen Klick auf einen ListView-Eintrag erfolgen.

4. Aufrufen der DetailActivity in der MainActivity-Klasse mit Hilfe eines Intents

Wir werden nun die neue DetailActivity von der MainActivity aus per expliziten Intent starten. Die neue Activity soll immer dann vom Android System aufgerufen werden, wenn der Benutzer kurz auf einen Eintrag des ListViews klickt. Für das Erfassen von Klicks auf ListView-Einträge ist der OnItemClickListener zuständig, den in der registerListViewClickListener() Methode implementiert und für den ListView registriert wird. Wir müssen daher diese Methode überarbeiten und in sie den Quellcode für das Starten der DetailActivity einfügen.

Wir öffnen nun die Klassendatei MainActivity.java im Editor von Android Studio mit einem Doppelklick auf ihren Dateinamen im Project Tool Window. Die Klassendatei befindet sich im Package-Ordner de.codeyourapp.zitate unseres Projekts.

Alle in die MainActivity.java Datei eingefügten bzw. überarbeiteten Codezeilen sind markiert worden:

An dieser Stelle endet der freie Inhalt dieser Lektion. Wir hoffen, sie hat dir bis hierher gefallen! Du kannst sie im geschützten Bereich von ProgrammierenLernenHQ fortsetzen, in welchem sich alle Lektionen unserer Android Online-Kurse befinden.

Unsere Android Kurse bestehen aus insgesamt 43 großen Lektionen und sind unterteilt in 13 frei zugängliche und 30 Premium-Lektionen. Die Premium-Lektionen befinden sich in dem geschützten Bereich und sind nur für Käufer unseres Android Online-Kurs Gesamtpaket zugänglich.

plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813 An dieser Stelle endet der freie Inhalt dieser Lektion. Wir hoffen, sie hat dir bis hierher gefallen! Du kannst sie durch Kauf unseres Android Online-Kurs Gesamtpakets freischalten.

In unserem Android Online-Kurs Gesamtpaket befinden sich 43 große Lektionen, in denen wir dir schrittweise zeigen, wie voll funktionstüchtige Android Apps programmiert werden.

Diese Lektion ist Teil unseres Android Gesamtpakets. Insgesamt sind unsere Online-Kurse unterteilt in 13 frei zugängliche und 30 Premium-Lektionen.

Die Premium-Lektionen befinden sich in dem geschützten Bereich und sind nur für Käufer des Android Online-Kurs Gesamtpakets zugänglich.



Welche Inhalte befinden sich im Android Online-Kurs Gesamtpaket?

  • Das Gesamtpaket enthält alle Android Online-Kurse von ProgrammierenLernenHQ.
  • Im Paket enthalten ist unser großer Android Apps Programmieren Online-Kurs. Er ist unser Hauptkurs und besteht aus 35 großen Lektionen. Die Grundlagen der Android App Entwicklung praxisnah und verständlich zu lehren, ist das Hauptziel des Android Apps Programmieren Kurses.
  • Im Paket enthalten ist auch unser SQLite Datenbank App Programmieren Online-Kurs. Dieser Spezialkurs besteht aus 8 großen Lektionen und ist als weiterführender Kurs konzipiert worden. Der Kurs schließt an unseren Android Apps Programmieren Hauptkurs an und widmet sich dem speziellen Thema der SQLite Datenbanken.
  • Durch den Kauf erhältst du unbegrenzten Zugang zu allen Inhalten unseres Android Online-Kurs Gesamtpakets. Wir werden in Zukunft weitere Lektionen hinzufügen. Auch auf alle zukünftigen Lektionen erhältst du vollen Zugriff.

Wir hoffen, Dich bald als neuen Kursteilnehmer unserer Android Online-Kurse begrüßen zu dürfen!

Einmal kaufen und dadurch zeitlich unbegrenzten Zugriff auf alle Inhalte unseres Android Online-Kurs Gesamtpakets erhalten.



Hinweis: Der untere Quellcode ist Teil des geschützten Bereichs von ProgrammierenLernenHQ. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte.
Erfahre mehr über unsere Android Online-Kurse.

android_programmieren_lernen_blurry_sourcecode

Der obere Quellcode ist Teil des geschützten Bereichs. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte. Klicke auf die Info-Box, um mehr zu erfahren.

In dem oben aufgeführten Quellcode der MainActivity.java Datei wurde die Methode registerListViewClickListener() bereits überarbeitet. Zudem wurde die Klasse Intent per Import-Anweisung sichtbar gemacht. Weitere Änderungen sind nicht an der MainActivity-Klasse vorgenommen worden.

In Zeile 3 werden die Intent-Klassen mittels Import-Anweisungen innerhalb der MainActivity-Klasse sichtbar gemacht, so dass wir sie ohne den Namen ihres Packages verwenden können.

Die überarbeitete Methode registerListViewClickListener() in den Zeilen 215 bis 237 wurde ebenfalls markiert. In ihr wurde der Quellcode für das Erzeugen des Intent-Objekts und Starten der DetailActivity eingefügt. Dabei wurde der bisherige Quellcode der Methode überschrieben. Um Programmierfehler zu vermeiden, ist es sicherer, die Methode daher vollständig durch den oben markierten Quellcode zu ersetzten. Auch wenn sich nur einige Codezeilen verändert haben.

Die registerListViewClickListener() Methode

Wie bereits weiter oben erwähnt, wird in den Zeilen 215 bis 237 der MainActivity-Klasse die registerListViewClickListener() Methode definiert. Durch die Methode wird ein OnItemClickListener implementiert und für den ListView registriert. Der Listener erfasst Klicks auf ListView-Einträge und starten daraufhin die DetailActivity per expliziten Intent.

Wie der OnItemClickListener dies ausführt, werden wir nun genauer betrachten. Die gesamte Methode ist daher zur Übersichtlichkeit an dieser Stelle nochmals aufgeführt:

android_programmieren_lernen_blurry_sourcecode

Der obere Quellcode ist Teil des geschützten Bereichs. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte. Klicke auf die Info-Box, um mehr zu erfahren.

An der registerListViewClickListener() Methode wurden nur die Zeilen 8 bis 18 verändert. Und zwar wurde in der anonymen Klasse der Methodenrumpf der onItemClick() Methode mit neuem Quellcode befüllt.

In der ursprünglichen Version wurde durch die onItemClick() Methode eine kurze Toast-Meldung auf dem Bildschirm des Android Geräts ausgegeben. Diesen alten Quellcode haben wir nun entfernt und mit dem oben aufgeführten ersetzt. Der neu eingefügte Quellcode ist in zwei Teile unterteilt.

Der erste Teil, die Zeilen 8 bis 11, ist für das Auslesen und Speichern der Zitatdaten zuständig. Dazu wird das angeklickte Quote-Objekt von der Datenquelle angefordert und in der Variable clickedQuote gespeichert. Welches Quote-Objekt, also welcher ListView-Eintrag, angeklickt wurde, ist in dem Methodenparameter position gespeichert. Der Inhalt des angeforderten Quote-Objekts wird anschließend in den Variablen imageID, quoteAuthor und quoteText gespeichert.

Der zweite Teil, die Zeilen 14 bis 18, ist für das Erzeugen des Intent-Objekts und Starten der DetailActivity verantwortlich. Zuerst wird ein expliziter Intent erzeugt. Dazu wird dem Konstruktor der Intent-Klasse als Context die MainActivity-Instanz und als aufzurufende Klasse die DetailActivity übergeben. Danach werden in das Extra-Feld des Intent-Objekts die zu übertragenden Daten abgelegt.

Die Daten werden mit Hilfe der drei Konstanten, welche in der DetailActivity-Klasse definiert worden sind, dem Intent-Objekt hinzugefügt. Dabei wird der putExtra() Methode jeweils ein Schlüssel und der zugehörige Wert übergeben. Auf diese Weise werden die Zitatdaten als Schlüssel-Wert Paare im Extra-Feld des Intents gespeichert.

Die DetailActivity wird schließlich in Zeile 18 von der startActivity() Methode gestartet. Dazu wird der Methode das erzeugte Intent-Objekt, das in sich die Zitatdaten des angeklickten ListView-Eintrags trägt, übergeben. Das Android System startet daraufhin automatisch die DetailActivity. Alle dafür notwendigen Informationen sind in dem expliziten Intent enthalten.

In Android Studio sollte der Inhalt der MainActivity.java Klassendatei nun wie folgt aussehen:

android_programmieren_lernen_blurry_sourcecode

Der obere Quellcode ist Teil des geschützten Bereichs. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte. Klicke auf die Info-Box, um mehr zu erfahren.

In der oberen Abbildung ist die MainActivity.java Klassendatei dargestellt. Es wurde eine Methode überarbeitet und eine Import-Anweisung hinzugefügt. Es ist nur die überarbeitete Methode aufgeklappt. Alle anderen Methoden sind unverändert geblieben und daher zugeklappt. Die hinzugefügten bzw. überarbeiteten Codezeilen sind mit Markierungen versehen worden.

Welche Bedeutung die jeweilige Zeile bzw. der jeweilige Code-Block besitzt, ist in der unteren Liste angegeben:

  1. B – Die benötigten Import-Anweisung zum Sichtbarmachen der Klasse Intent.
  2. C – Die registerListViewClickListener() Methode startet nun die DetailActivity per expliziten Intent, sobald ein ListView-Eintrag vom Benutzer angeklickt wird.

Wir haben nun die Methode registerListViewClickListener() so überarbeitet, dass durch sie die neu erstellte DetailActivity mit Hilfe eines expliziten Intent gestartet wird. Die neue Activity wird gestartet, sobald von der registerListViewClickListener() Methode ein Klick auf einen ListView-Eintrag erfasst wird. An die gestartete Activity werden dabei die Zitatdaten des angeklickten Eintrags über das Intent-Objekt übertragen.

Somit haben wir alle Änderungen an unserem Android Projekt vorgenommen und können nun die neue Funktion unserer App testen.

5. Ausführen und Testen unserer Android App

Wir werden nun unserer Android App auf einem Android Virtual Device im Emulator ausführen lassen. Unsere Anwendung besteht nun aus den beiden Activities MainActivity und DetailActivity. Wir werden nun die DetailActivity per expliziten Intent von der MainActivity aus starten lassen. Dabei werden wir prüfen, ob die gestartete DetailActivity die empfangenen Zitatdaten korrekt darstellt.

Unsere App starten wir dazu wie gewohnt über den Run > Run 'app' Menüeintrag, den wir über die obere Menüleiste erreichen.

Sobald unsere App auf dem AVD gestartet wurde, führen wir einen kurzen Klick auf einen Eintrag des ListViews in der MainActivity aus, daraufhin wird die DetailActivity vom Intent Mechanismus des Android Systems gestartet.

Das Ergebnis ist in der unteren Abbildung dargestellt:

screenshot_expliziter_intent

Von der per expliziten Intent gestarteten DetailActivity werden die empfangenen Zitatdaten dargestellt

Der erfolgte Klick wurde vom OnItemClickListener erkannt und von diesem umgehend die DetailActivity per expliziten Intent gestartet. Dabei wurden die Zitatdaten des angeklickten ListView-Elements dem Intent-Objekt hinzugefügt und an die aufgerufene Activity übermittelt. In der DetailActivity wurde die übertragenen Zitatdaten aus dem Extra-Feld des empfangenen Intent-Objekts ausgelesen und als Inhalt für die View-Elemente der Activity wiederverwendet.

Zusammenfassung

In dieser Lektion haben wir unsere Android App um eine zusätzliche Activity erweitert. Die neue Activity, DetailActivity, zeigt Details zu einem angeklickten Eintrag des ListViews an. Sie wird von der MainActivity aus gestartet, sobald der Benutzer kurz auf einen ListView-Eintrag klickt.

Zum Starten der neuen Activity haben wir den Intent Mechanismus von Android verwendet. Dabei haben wir im theoretischen Teil dieser Lektion erfahren aus welchen Komponenten ein Intent besteht, wie durch ihn eine Activity gestartet wird und welche Daten an die gestartete Activity durch das Intent-Objekt übertragen werden können.

Anschließend haben wir im praktischen Teil dieser Lektion die DetailActivity erstellt. Dazu haben wir zuerst die XML-Layout Datei und danach die Java Klasse der DetailActivity angelegt und mit Quellcode gefüllt. Damit die neu Activity auch gestartet werden kann, haben wir sie dem Android System im App Manifest bekanntgeben.

Die DetailActivity haben wir schließlich von der MainActivity-Klasse aus per expliziten Intent gestartet. Das Starten haben wir vom OnItemClickListener des ListViews durchführen lassen, welcher kurze Klicks auf die ListView-Elemente erfasst und darauf nach unseren Vorgaben reagiert.

Abschließend haben wir unsere Android App im Emulator auf einem Android Virtual Device ausgeführt und überprüft, ob die neue Activity per Intent gestartet wird und die übertragenen Daten korrekt von ihr ausgegeben werden.

In der nächsten Lektion werden wir uns weiter mit dem Intent System von Android beschäftigen. Wir werden in der DetailActivity einen impliziten Intent erzeugen und mit diesem eine App-fremde Activity starten lassen. Dabei werden wir erfahren, wie das Android System die zur angeforderten Aufgabe passende Activity herausfiltert und für uns startet.

Weiterführende Literatur




Comments 23

  1. Hallo Chris,
    hätte da zwei Fragen bezüglich des Tutorials.

    1. kann man das auch so machen, dass man einzelne Elemente bearbeitet?
    Beispielsweise ich wähle das zweite Element aus und dann kommt nicht nur als anzeige der Eintrag der Liste sondern etwas Detaillierter, das ein weiterer Text noch darunter erscheint?
    Und wie würde man das dann implementieren?

    2. Wie stellt man das dar, das nicht Aktiendetail bei der zweiten Activity oben in der Actionbar steht sondern die Aktie die man grade angewählt hat?

    Hoffe auf eine Schnelle Antwort

    Vielen Dank für das Tutorial!
    Liebe Grüße

    1. Post
      Author

      Hallo Jonas,

      Frage 1: Im Tutorial wird als Datenquelle des ListViews nur ein Array mit Strings genutzt. Mehr Daten in der DetailActivity darzustellen ist recht einfach, wenn man als Datenquelle ein eigenes Datenmodell als Klasse implementiert. In dem Datenmodell können dann viele Informationen gehalten werden, auf die je nach Bedarf zugegriffen wird. Ein Datenmodell könnte hier eine Klasse Aktie.java sein, die als Membervariablen den Aktienkurs, Unternehmensnamen, Branche und Unternehmensbeschreibung besitzt. Im ListView zeigt man nur den Aktienkurs und den Unternehmensname an. In der DetailActivity dann zusätzlich die Branche und die Beschreibung. Wie so etwas gemacht wird, zeige ich in meinem Android Apps Programmieren Online-Kurs in Modul 5. Der Kurs ist viel ausführlicher als dieses freie Tutorial und beschäftigt sich u.a. mit der Frage wie in Android Daten mit der Benutzeroberfläche verbunden werden.

      Frage 2: Wie man den Titel der ActionBar, auch App Bar, ändert ist nicht ganz einfach. Die App Bar muss dazu als Toolbar implementiert werden. Anschließend kann man mit Hilfe der getSupportActionBar() Methode den Titel der App Bar ändern. Wie man das macht, zeige ich auch in meinem Android Apps Programmieren Online-Kurs in Modul 6 Lektion 3 (App Bar als Toolbar implementieren) und Modul 9 Lektion 1 (DetailActivity -> App Bar Titel ändern).

      Viele Grüße,

      Chris

  2. Habe bisher in Pascal programmiert und beschäftige mich gerade mit Android Studio. Also Java-Anfänger 🙂 Deine Anleitung ist sehr gut und vor allem verständlich geschrieben, hat mich ein großes Stück weiter gebracht, funktioniert super bis auf ein paar korrigierte Kleinigkeiten, die aber versionsbedingt waren.

    Großes Lob und vielen, vielen Dank für dieses Tutorial!

    1. Post
      Author

      Hallo Ronny,

      danke für dein Lob! Es freut mich wenn die Lektionen auch als Java „Anfänger“ nachvollziehbar sind. An manchen Stellen wird der Quellcode doch etwas komplexer, da ist es schwierig für Beginner in einer neuen Programmiersprache den Überblick zu behalten.

      Viele Grüße, Chris

  3. Hallo Chris,

    das Tutorial ist echt klasse! Leider hänge ich gerade am Punkt 9.1. Sobald ich die Daten aktualisiert und auf eine der 3 Aktien geklickt habe, springt er zur Hauptansicht zurück und im Log bekomme ich:
    „D/AbsListView: Get MotionRecognitionManager“
    Kannst du mir bitte weiterhelfen? Ich nutze ein Samsung-Tablet mit Android 4.4.2

    Gruß Christian

    1. Post
      Author

      Hallo Christian,

      hmm, schwierig ohne Quellcode zu beurteilen.

      Wenn du möchtest, kannst Du mir deine Projektdateien (den ganzen Android Studio Projektordner, aber OHNE die build-Unterordner) als ZIP per E-Mail zusenden. Die E-Mail Adresse kannst Du im Impressum finden. Ich schaue dann mal, ob ich etwas herausfinden kann.

      Viele Grüße, Chris

  4. Hallo Chris,

    danke für die tolle Tutorialreihe.

    Ich stehe jetzt am Ende von Teil 10, habe bisher viele Dinge gelernt und auch noch viele Dinge nicht verstanden. Abgesehen davon bin ich auf ein Problem gestoßen.

    Die App verhält sich im Emulator wie gewollt, auf einem Smartphone nicht. Bis zur Implementierung der Activities/Intents war alles gut, jetzt passiert beim Klick auf die einzelnen Kurse auf dem Smartphone nichts (im Gegensatz zur Emu).

    Hast du einen Tipp für mich?

    Gruß Tino
    P.S.: Emu: Nexus5 mit Android 6 / Smartphone: Xperia Z3 mit Android 6

    1. Post
      Author

      Hallo Tino,

      danke für’s Lob.

      Leider habe ich kein übereinstimmendes Testgerät. Zur Fehlersuche würde ich im Debugger von Android Studio die Zeile als Breakpoint markieren, in der die andere Activity aufgerufen wird. Dann würde ich die vom Debugger angezeigten Werte (der relevanten Variablen) miteinander vergleichen. Also die Werte beim Ausführen im Emulators mit den Werten beim Ausführen auf dem Smartphone. Eventuell lässt sich dann erkennen, was auf dem Smartphone zu dem Problem führt.

      Viele Grüße, Chris

  5. Chris, du bist echt toll. Danke, danke, danke, danke, danke für dieses tolle Tutorium, du glaubst nicht, wie viel du mir damit hilfst! Vielen, vielen Dank!!

    1. Post
      Author

      Hallo Susi,

      danke für dein Lob! Ich erkläre es hiermit zum Lob des Monats 🙂

      Es freut mich immer sehr, wenn das Tutorial hilfreich ist und mir davon berichtet wird. Das schafft Motivation es beim nächsten Mal noch besser zu machen.

      Viele Grüße, Chris

  6. Hallo Chris,

    nun am Ende des Wochenendes bin ich – erfolgreich – am Ende von Lektion 10, wie von Dir bei meiner Frage zu L. 6 empfohlen. Mein Kopf „raucht“, doch so soll es wohl sein …
    Warum wird man beim Installieren der App im AS nicht gefragt (wg. der Internet permission), ob man installieren möchte? Ist das normal so?
    Bitte um Nachsicht!
    Viele Grüße
    Fido

    1. Post
      Author

      Hallo Fido,

      die Frage habe ich mir auch kürzlich gestellt.

      Wird die App durch Android Studio aufgespielt, werden die angefragten Genehmigungen (Permissions) automatisch vergeben. Würde die App über den Google Play Store installiert werden, wäre das Verhalten anders.

      Viele Grüße, Chris

  7. Hallo Chris

    Ich hab‘ auf gut Schweizerdeutsch immer noch ein Gnusch (eine Verwirrung) was die Verbindungen zwischen den XMLs und den Java Klassen anbelangt. Liegt wohl an mir. Doch eine Frage: Wäre es nicht möglich, das aktiendetail_fragment in der main activity zu zeigen, anstelle der Aktienliste?

    Gruss,

    André

    1. Post
      Author
  8. Hi Chris,

    bin weiterhin begeistert dabei 😉 1a – dieses Tutorial!!!

    Eine Frage: nach Erzeugen des Intents wird eine „Activity“ gestartet, die Daten werden aber letztlich von einem „Fragment“ angezeigt. Verstehe ich es richtig, dass beim Start der Activity alle untergeordneten/zugehörigen Fragments (hier: AktiendetailFragment) die onCreate-Methode durchlaufen und jedes Fragment für sich „entscheidet“, ob es den Intent und die im Intent übergebenen Extra-Daten verarbeitet und anzeigt?

    Gruß, Reinhard

    1. Post
      Author

      Hallo Reinhard,

      in Android gibt es den Activity Lifecycle und den Fragment Lifecycle. Wir haben Teil 15 diesem spannenden Thema gewidmet: Der Activity und Fragment Lifecycle in Android.

      Ja es ist so, wie Du sagst. In den verschiedenen Lifecycle-Callbacks der Fragmente kann mittels Intent empfangenerIntent = getActivity().getIntent(); auf den Intent und dessen Inhalte zugegriffen werden. Jedes Fragment kann damit machen was es will.

      Viele Grüße, Chris

  9. Hallo Chris,

    vorweg ein super Tutorial, bisher funktioniert alles bestens. Danke dafür!

    Nun mal ne Anmerkung, obwohl ich nicht weiß, ob der Fehler bei mir oder bei Dir liegt.

    Unter Punkt 2.1 in diesem Tutorial hast Du folgenden Quellcode in der AktienlisteFragment.java:

    ListView vorhersageListView = (ListView) rootView.findViewById(R.id.listview_vorhersage);
    vorhersageListView.setAdapter(mVorhersageAdapter);
    

    und ich habe folgenden Quellcode in meiner Datei:

    ListView aktienlisteListView = (ListView) rootView.findViewById(R.id.listview_aktienliste);
            aktienlisteListView.setAdapter(mAktienlisteAdapter);
    

    Der Unterschied ist, dass Du „mVorhersageAdapter“ und ich „mAktienlisteAdapter“ habe, obwohl ich das gesamte Tutorial bis hier komplett durch habe.

    Hab ich im Tutorial irgendwas übersehen? Geht es noch Jemandem so wie mir?

    Ich möchte nur nicht, dass am Ende des Tutorials irgendwas nicht funktioniert, weil es unterschiedliche Bezeichnungen gibt.

    Danke im voraus für deine Antwort!

    Gruß Matze

    1. Post
      Author

      Hallo Matze,

      vielen Dank für die lobenden Worte und den Quellcode-Hinweis.

      Ja, in der Tat hat sich da bei mir ein Fehler eingeschlichen. Ich habe den Quellcode korrigiert, so dass er jetzt Deinem Quellcode entspricht.

      Die unterschiedliche Bezeichnung im Quellcode lag daran, dass ich in diesem Tutorial vorher eine Wetter-App programmiert hatte und diese dann auf eine Aktien-App umgestellt habe. Der mVorhersageAdapter war noch ein Überbleibsel aus der Wetter-App (die Wettervorhersage).

      Viele Grüße und nochmals danke für Deine Hilfe, Chris

  10. hey das tutorial ist super, ich habe aber ein kleines Problem, Erstens hast du eigentlich diese Mockdaten rausgenommen, denn beim Appstart würde ja sonst immer erst diese Liste mit den Mockdaten ( Aktienkurse ) angezeigt werden ? Und dann habe ich noch das Problem dass die App oft abstürzt wenn ich die Daten von Yahoo hole ( also den Asynctask starte )und ich nicht weiss warum.

    1. Post
      Author

      Hallo Dennis,

      die Mockdaten werden auch am Ende des Android-Tutorials nicht rausgenommen, da es nur eine Beispiel-App ist. Bei einer realen App würden die Mockdaten natürlich so durch echte Daten ersetzt werden, dass schon beim Starten der App echte Daten angezeigt werden.

      Manchmal endet die HTTP-Anfrage nicht korrekt. Dann werden keine Aktiendaten von Yahoo! zurückgeliefert. In einem solchen Fall stürzt die App bspw. ab. Das ist auch bei mir schon ab und zu passiert. Da es nur eine Beispiel-App ist, wurde auf das Abfangen viele möglicher Fehler verzichtet, damit die Lerninhalte nicht zu komplex und unübersichtlich werden. Eine reale App müsste deutlich stärker debugged werden, da Programmabstürze die User sehr verärgern…

      Viele Grüße, Chris

  11. Pingback: Android Tutorial: Der ShareActionProvider in Android

  12. Pingback: Android Tutorial: Mit impliziten Intent eine andere App aufrufen

  13. Pingback: Android Tutorial: XML-Daten auslesen und anzeigen in Android

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.