Stand: 28.07.2020

Mobile Apps bestehen häufig aus verschiedenen Screens, zwischen denen man wechselt. Weiterhin ist es üblich, zwischen verschiedenen Apps zu wechseln, z.B. von einer Mail in der Mail-App zum Browser, um einen Link zu betrachten, und zurück, oder von einer Kamera-App zu einer Chat-App, um das Foto zu teilen.

7.1 Intents

API Intent →

Intents stellen Verbindungen zwischen den Activities her, sowohl zwischen Activities derselben App als auch zwischen Activities unterschiedlicher Apps. Wenn man von Activity A zu Activity B wechseln möchte, erzeugt man ein neues Intent-Objekt und teilt dieser mit, dass man Activity B (eine Klasse) aufrufen möchte. Anschließend übergibt man den Intent einer Android-Methode, die den Übergang regelt.

Wir haben es also bei einem einfachen Übergang zwischen zwei Activities mit diesen drei Objekten zu tun:

Intent

Warum soll so etwas vermeintlich Einfaches wie der Übergang von Activity A zu Activity B von einem Objekt geregelt werden? Reicht nicht ein einfacher Funktionsaufruf? Nein, denn Intent-Objekte können eine Reihe von Zusatzinformationen zum Übergang enthalten:

Man unterscheidet zwischen expliziten Intents und impliziten Intents. Explizite Intents benutzt man, um zu einer anderen Activity zu wechseln. Es handelt sich also um einen Übergang innerhalb der eigenen App.

explizite und implizite Intents

7.2 Explizite Intents

Wir beginnen mit expliziten Intents.

7.2.1 Neue Activity

Dazu müssen wir zunächst eine neue Activity erstellen. In der Projektsicht (links) gehen wir auf java und dort auf unser Package und wählen per Rechtsklick: New > Activity > Empty Activity.

Nennen Sie die neue Activity "SecondActivity". Android Studio legt eine Java-Datei SecondActivity.java und eine Layout-Datei activity_second.xml an.

Wir stellen uns eine App vor, die zwei Screens hat (also zwei Activities). In der ersten Activity (MainActivity) haben wir eine Texteingabe und einen Button. Man kann eine beliebige "Nachricht" für die zweite Screen schreiben. Auf der zweiten Screen (= SecondActivity) möchten wir den Text zeigen, den der User auf der ersten Screen eingegeben hat.

Beispiel für explizite Intents

7.2.2 Zweite Activity starten

Für den ersten Übergang erstellen wir ein Intent-Objekt, das sowohl die aktuelle Activity (this) als auch die Ziel-Klasse (SecondActivity.class) enthält:

Intent gotoSecond = new Intent(this, SecondActivity.class);

(Das this kann problematisch sein - das sehen wir gleich...)

Bei dem Buttonklick "starten" wir den Intent mit der Methode startActivity:

startActivity(gotoSecond);

Im Kontext sieht das so aus:

public class MainActivity extends AppCompatActivity {

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

        Button next = (Button)findViewById(R.id.buttonNext);
        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent gotoSecond = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(gotoSecond);
            }
        });
    }
}

Wie Sie sehen, mussten wir diese Zeile leicht ändern:

Intent gotoSecond = new Intent(MainActivity.this, SecondActivity.class);

Grund ist, dass wir mit new View.OnClickListener() eine Instanz einer neuen (anonymen) Klasse erstellen und ein this auf genau dieses Objekt verweisen würde. Mit folgendem Ausdruck können wir Java in unserem Fall mitteilen, dass wir das "übergeordnete" Objekt meinen:

MainActivity.this

Zurück zum eigentlichen Thema: Auch wenn wir jetzt in der zweiten Activity sind, so ist die erste Activity immer noch "am Leben". Auf dem Endgerät können Sie jederzeit mit dem Back-Button zur ersten Activity zurückkehren. Mehr zum Thema "Back-Stack" werden Sie im Modul Lifecycle lernen.

7.2.3 Daten über Extras mitgeben

Wie geben wir der SecondActivity den Text mit, den der User eingegeben hat? Wenn wir noch Daten an die zweite Screen mitgeben wollen, sind das sogenannte Extras.

Extras sind aufgebaut wie eine Tabelle: wir geben für jede Information (= String) einen Schlüssel an. Bei uns heißt der Schlüssel "secret". Wir verwenden die Methode putExtra, um einem Intent eine Information hinzuzufügen.

Beispiel für explizite Intents mit Extras

Wenn wir also einen String foo hätten, könnten wir ihn mit

gotoSecond.putExtra("secret", foo);

dem Intent hinzufügen.

Im Code kann das so aussehen. Wir holen hier den Text aus dem editierbaren Textfeld (editText). Wir brauchen das "final" bei dem Intent, damit wir innerhalb des Button-Handlers auf den Intent zugreifen können.

public class MainActivity extends AppCompatActivity {

    private EditText editText;

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

        editText = (EditText)findViewById(R.id.editText);

        Button next = (Button)findViewById(R.id.buttonNext);
        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent gotoSecond = new Intent(this, SecondActivity.class);
                gotoSecond.putExtra("secret", editText.getText().toString());
                startActivity(gotoSecond);
            }
        });
    }
}

Auf der zweiten Screen können wir uns die Extra-Infos holen mit

getIntent().getExtras().get("secret");

Alternativ können wir (kürzer) schreiben:

getIntent().getStringExtra("secret");

Im Code von SecondActivity sieht das wie folgt aus:

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

    String message = getIntent().getStringExtra("secret");
    ((TextView)findViewById(R.id.textMessage)).setText(message);
}

7.2.4 Rückkehr mit finish

In SecondActivity rufen wir einfach die Methode finish() auf, um wieder in die MainActivity zurückzukehren.

Beispiel für explizite Intents, Rückkehr mit finish

Im Code:

protected void onCreate(Bundle savedInstanceState) {
    ...

    Button back = (Button)findViewById(R.id.buttonBack);
    back.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });
}

Bei der Rückkehr wird die Activity, die wir verlassen, unwiederbringlich zerstört.

Natürlich gibt es auch Situationen, wo Ihre zweite Activity eine dritte aufruft (und diese evtl. eine vierte). Sie sollten aber niemals in eine alte Activity über startActivity zurückkehren. Warum das so ist, sehen Sie beim Thema "Back-Stack" im Modul Lifecycle.

7.3 Sub-Activity und Datenrückgabe [optional]

Es gibt Activities, die häufiger als "Dienst" verwendet werden, z.B. reine Eingabe-Screens für Namen, Adressen etc. Eine solche Activity kann also mit der Intention aufgerufen werden, dass ein Wert (z.B. Text) zurückgegeben wird. Dann spricht man auch von einer Sub-Activity.

7.3.1 Aufruf der Sub-Activity

Nehmen wir an, wir haben eine Activity A, die eine Sub-Activity B aufruft. Auch hier verwenden wir einen Intent, aber der Aufruf erfolgt mit startActivityForResult.

Damit Activity A weiß, zu welchem Zweck B aufgerufen wurde, kann ein RequestCode (eine ganze Zahl) mitgegeben werden. Das ist insbesondere dann wichtig, wenn A mehrere Sub-Activities aufrufen kann, denn die Ergebnisse werden alle in einer einzigen Methoden aufgefangen.

Außerdem kann man dem eigenen Intent Extras mitgeben (s.o.). Damit kann man einer Eingabemaske mitgeben, was man genau abfragen will ("Name" oder "Telefon").

Nehmen wir an, Sie haben eine (Sub-)Activity FrageActivity, die dem User eine Frage stellen kann und die Antwort zurückgibt.

Intent intent = (this, FrageActivity.class);
intent.putExtra("fragetext", "Warum ist die Banane krumm?");
startActivityForResult(intent, 0);

Den RequestCode setzen wir einfach auf 0.

7.3.2 In der Sub-Activity

In der Sub-Activity B wird z.B. eine Eingabemaske gezeigt und auf einen Input gewartet. Typischerweise hat man Buttons für "OK" und "Abbrechen". Sobald OK gedrückt wird, kann man in Activity A zurückspringen. Dazu

Hinweis: Nicht den Result-Code mit dem Request-Code verwechseln! Der Result-Code besagt, ob der User abgebrochen oder bestätigt hat. Der Request-Code sagt der aufrufenden Activity, von welcher Sub-Activity das Ergebnis kommt.

In unserem Beispiel mit der FrageActivity nehmen wir an, dass wir eine EditText-Komponente in der Variablen editText halten. Sofern der User die Eingabe bestätigt, rufen wir dies auf:

Intent intent = new Intent();
intent.putExtra("antwort", editText.getText().toString());
setResult(RESULT_OK, intent);
finish();

Bei "Abbrechen" setzt man setResult auf RESULT_CANCELED und ruft finish auf.

Beachten Sie, dass die Sub-Activity nach Aufruf von finish komplett zerstört wird (siehe Modul Lifecycle).

7.3.3 Ergebnis auffangen

In Activity A wird nach Beendigung von Sub-Activity B die Methode onActivityResult aufgerufen. Diese muss man also implementieren (d.h. überschreiben). Innerhalb der Methode kann man sich den ResultCode anschauen (ist entweder RESULT_OK oder RESULT_CANCELED) und den RequestCode (hat man selbst bestimmt). In dem mitgelieferten Intent-Objekt stehen die Extras, wo auch die Eingabe gespeichert wurde.

In unserem Beispiel wären wir z.B. wieder in MainActivity:

protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    if (requestCode == 0 && resultCode == RESULT_OK) {
        String antwort = intent.getStringExtra("anwort", "KEINE ANTWORT");
        ...
    }
}

Wie schon erwähnt, wird immer diese eine Methode aufgerufen, egal von welcher Sub-Activity wir zurückkehren (für den Fall, dass mehr als eine Sub-Activity von A aus aufgerufen werden kann). Der Request-Code dient in solchen Fällen dazu, die Ergebnisse korrekt zu behandeln. Hier haben wir der Sub-Activity lediglich eine 0 mitgegeben und bekommen diese auch zurück.

7.4 Zusammenfassung

Intents sind Objekte, die den Übergang von einer Activity A in eine andere Activity B erlauben. Ein einfacher Übergang besteht darin, dass man in Activity A einen neuen Intent für Activity B erzeugt und dann die Methode startActivity aufruft. Will man aus Activity B wieder in Activity A zurückkehren, ruft man einfach finish() auf.

Man kann in einem Intent Daten in Form einer Tabelle speichern, den sog. Extras. Diese Extras können in der Ziel-Activity B wieder abgerufen werden.

Man kann eine Activity B auch als reine "Datenbeschaffungs"-Activity mit Rückgabe sehen. Eine solche Activity könnte z.B. eine Usereingabe durchführen und das Resultat - ähnlich wie eine Funktion - zurückgeben. Dazu rufen wir B als Sub-Activity mit der Methode startActivityForResult auf. Die aufrufende Activity muss das Resultat mit der Methode onActivityResult auffangen.

7.5 Übung

Kontaktseite mit Edit-Activity

Schreiben Sie für eine Kontakte-App eine Sub-Activity, in der Sie eine Texteingabe machen können.

Ihre App besteht aus einer Seite mit Feldern für Name, Telefon und Mail:

Kontaktseite

Wird jetzt einer der drei Edit-Buttons betätigt, springt die App in eine Sub-Activity, in der die Texteingabe erfolgen kann. Beachten Sie, dass über dem Texteingabe-Feld (Klasse EditText, in der Design-Ansicht unter "Plain Text") noch steht, um welche Eingabe es sich handelt (Name, Telefon oder Mail):

Edit-Screen

Wenn auf OK geklickt wird, wird die Eingabe in das entsprechende Feld übernommen:

Kontaktseite mit Name

Hier nochmal schematisch der Ablauf:

Ablauf