Bei Android dreht sich alles um Intents. Wenn man eine einfache Applikation in Eclipse entwickelt muss man sich damit nicht unbedingt auseinandersetzen, weil die korrekten Daten für einen eingetragen werden, aber spätestens wenn man einen Service implementiert oder auf externe Ereignisse reagieren will muss man sich mit Intents beschäftigen.

Da ich Probleme damit hatte das System zu verstehen, will ich hier einmal das was ich gelernt habe zusammenfassen, schon alleine weil ein Aufschreiben immer dabei hilft das eigene Wissen in geordnete Bahnen zu lenken und Lücken zu finden.

Was sind Intents

Intents sind erst einmal nur eines: Nachrichten.

Google hat in seinem Android-Betriebssystem quasi eine Architektur gebaut, in der alle möglichen Komponenten getrennt voneinander erstellt werden können und über diese Nachrichten miteinander kommunizieren, sich aufrufen und aufeinander reagieren können. Intents sind quasi IPC, Hooks, Systemintegration und Prozess-Aufrufe in einem.

Intents können für folgende Aufgaben genutzt werden:

  1. Eine Aktivity oder einen Service starten
  2. Das Programm im System verankern
  3. Auf ein Ereignis reagieren
Dafür gibt es zwei Arten von Intents (die im Quelltext beide ein "Intent" sind), die sich durch die enthaltene Information unterscheiden: Explizite Intents enthalten einen absoluten Komponentennamen, z.B. den genauen Namen des Service der gestartet werden soll. Android kümmert sich darum, dass diese Intents genau bei dieser Komponente ankommen.

Implizite Intents enthalten quasi "nur" Informationen darüber was passiert - wer/was darauf reagiert hängt davon ab welche Applikationen sich im System mit einem passenden Intent-Filter registriert haben. Passt der Implizite Intent auf den registrierten Filter einer Applikation wird die Komponente zu der der Filter definiert wurde aufgerufen.

Eine Aktivity oder einen Service starten

Der einfachste und offensichtlichste Fall. Genau dafür gibt es folgende Methoden der Klasse Context: startActivity und startService - denen übergibt man einen Intent der den genauen Namen der Activity bzw. des Service (also ein expliziter Intent) enthält (man kann darüber hinaus nahezu beliebige zusätzliche Informationen in den Intent packen und diese dann beim Starten des Service oder der Activity abfragen). Das macht man im Code einer Activity dann z.B. so:
    startService(new Intent(this, MyService.class));
Hier wird ein neuer Intent erstellt, mit der aufrufenden Activity als Context und dem zu startenden Service als Komponentenname  direkt an die Methode startService der Activity übergeben wird. Es handelt sich hier um einen expliziten Intent, da die zu startende Komponente eindeutig spezifiziert ist (nämlich durch den Wert von MyService.class).

Das Programm im System verankern

Dieser Fall ist deutlich weniger intuitiv als der vorherige. Ich will das ganze mal an einem in wohl 95% aller Applikationen vorhandenem Beispiel veranschaulichen:

Um meine Applikation in der Liste der vorhandenen Applikationen aufzulisten muss ich diese im System registrieren - soweit alles wie üblich. Allerdings muss ich bei Android nicht die Applikation, sondern z.B. eine meiner Activities registrieren, und zwar für den Intent der für die Applikationsliste "gesendet" wird. Genauer: Im Manifest meiner Applikation muss stehen, dass meine Activity auf den Intent mit der Action "android.intent.action.MAIN" in der (Intent-)Category "android.intent.category.LAUNCHER" registriert ist.

Im Manifest sieht das dann z.B. so aus:

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"></action>
                <category android:name="android.intent.category.LAUNCHER"></category>
            </intent-filter>
        </activity>
    </application>
Eclipse erstellt diesen Intent-Filter sogar automatisch.

Auf ein Ereignis reagieren

Wenn ich es richtig verstehe ist dies eigentlich nur eine andere Form des vorherigen.

Wenn ich z.B. möchte, dass mein Service automatisch gestartet wird, sobald das Telefon startet, dann muss ich ihn für die Action "android.intent.action.BOOT_COMPLETED" registrieren und dann natürlich noch eine Möglichkeit zur Verfügung stellen darauf zu reagieren. Die Action wird vom System erzeugt, dann guckt das System nach was sich dafür registriert hat (genauer, welche Intent-Filter passen) und schickt dann diesen Intent an genau diese registrierten Applikationen - das nennt Android dann "Broadcast".

Um einen Broadcast empfangen ("to receive") zu können benötigt man einen - Überraschung! - BroadcastReceiver, darauf gehe ich in diesem Posting näher ein. Ein ganz einfacher Receiver sieht ungefähr so aus:

    public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Do something based on the Intent received
        }
    }
Da wo jetzt der Kommentar steht würden wir natürlich überprüfen welche Action gesendet wurde und im Falle von "android.intent.action.BOOT_COMPLETED" eben den Service starten.

Jetzt muss ich diesen Receiver genau wie meine Activity im vorherigen Beispiel noch im Manifest eintragen und dort in Form eines Intent-Filters mitteilen wann das System denn nun den Receiver aufrufen soll. Das sieht dann in unserem Beispiel so aus:

    <receiver android:name="com.example.MyBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            <category android:name="android.intent.category.HOME"></category>
        </intent-filter>
    </receiver>
Dieser Abschnitt muss (genau wie das activity-Element oben) innerhalb des application-elements geschachtelt sein.

Hinweis

Hier endet mein "Wissen" über Intents, ich will schwer hoffen, dass sich das in nächster Zeit noch vertiefen wird, aber das kommt dann mit der weiteren Entwicklung.

Über Hinweise, Korrekturen und Kritik würde ich mich sehr freuen - ich hab schließlich noch einen langen Weg vor mir bis zum Android-Experten. ;-)