Andreas Bruns

Softwareentwicklung für Oldenburg und Bremen

Starten von Android-Apps mit Intents

In diesem Jahr finden zum ersten Mal die Wettbewerbe Apps4Bremen und dessen großer Bruder Apps4Deutschland statt, die unter anderem Entwickler dazu aufrufen, auf Basis von öffentlichen Daten funktionsfähige Visualisierungen oder Web- und Handy-Anwendungen (Apps) zu entwickeln. Ich habe mir vorgenommen, mit einer Handy-App für Android-Systeme an dem Wettbewerb teilzunehmen.

Das Auswerten und Anzeigen von Daten innerhalb einer Handy-Anwendung kann ja alleine schon hilfreich sein. Echte Praxistauglichkeit beweist eine App jedoch damit, dass sie sich in das Handy-Benutzungskonzept integriert. So können beispielsweise aus einer Handy-App die Funktionen anderer Apps aufgerufen und genutzt werden. Das bietet sowohl für den Entwickler als auch für den Anwender Vorteile:

  • Entwickler müssen keine Zeit in die Entwicklung von Funkionen investieren, die andere Programme bereits bieten
  • Anwender werden für einen Einsatzzweck stets das gleiche bekannte Programm nutzen

In diesem Artikel stelle ich einige Code-Beispiele vor, mit welchen Aufrufen sich andere Android-Apps starten lassen. Die kleine Beispielanwendung ist bei Github verfügbar. Folgende Funktionen/Anwendungen werden vorgestellt (der Unterschied zwischen den Aufrufen besteht lediglich aus einer Zeile Programmcode): Telefonanruf starten, SMS verschicken, Webseite öffnen, Bild aufnehmen, Kontakte öffnen, Karte anzeigen und Navigation starten

Auf der Android-Plattfrom wird Kommunikation zwischen verschiedenen Komponenten über sogenannte Intents (Absichtserklärung) realisiert. Der Empfänger eines Intents kann in Form eines Klassennamens eindeutig benannt werden (explizite Intents) oder der Empfänger ermittelt sich aus den Komponenten der vorhandenen Apps (implizite Intents).

Unsere Aufgaben werden wir mit impliziten Intents erfüllen, sodass ich auf explizite Intents nicht großartig eingehen möchte. Die expliziten Intents sind auch recht einfach, wie man an dem folgenden Code erkennen kann. Man muss lediglich den Klassennamen mit dem Anwendungskontext (z.B. die aktuelle Aktivität) angeben, kann dem Intent noch zuätzliche Daten mitgeben und führt dann die Methode startActivity(intent) aus:

public class MyActivity extends Activity {
   ...
   Intent intent = new Intent(this, OtherActivity.class);
   intent.putExtra("my_key", "my_value");
   startActivity(intent);
   ...
}

Bei den impliziten Intents benenennen wir eine Aktion, optional eine URI (Uniform Resource Identifier) und optional weitere Daten. Wenn wir den Intent aufrufen, werden die vorhandenen Komponenten des Systems ausgewertet, ob eine Komponente mit dem Intent umgehen kann.

public class MyActivity extends Activity {
   ...
   String action = Intent.ACTION_CALL;
   Uri uri = Uri.parse("tel:(+49) 123 4567890");
   Intent intent = new Intent(action, uri);
   startActivity(intent);
   ...
}

Falls genau eine passende Komponente vorhanden ist, wird die zugehörige Anwendung gestartet. Wenn keine passende Komponente gefunden wird, erscheint eine Fehlermeldung und falls mehrere Komponenten passen, muss der Anwender die entsprechende Anwendung auswählen.

Die Beispielanwendung habe ich in folgenden Schritten umgesetzt:

  • Installation des Android-SDK und des Android-Plugins für Eclipse
  • Erstellen eines Android-Projekts (z.B.: Android – Hello World)
    – ich habe mich für API 2.1 entschieden
    – Google APIs der Version 2.1 wählen, weil wir installierte Programme von Google nutzen wollen (Maps, Navigator)
  • Device erstellen
    – API wie zuvor (Version 2.1 mit Google)
    – SD-Karte nutzen für Fotos (z.B.: 20 MB)
  • Datei ‚AndroidManifest.xml‘ um folgenden Permission-Eintrag erweitern, damit Telefonnummern gewählt werden dürfen
    
    <manifest ...>
        <uses-permission android:name="android.permission.CALL_PHONE"/>
        <application ...>
        </application>
    </manifest>
    
    
  • die verwendete Activity mit folgendem Code ausstatten
    public class IntentsActivity extends ListActivity {
    
       private static IntentData[] INTENT_DATA = {
             new IntentData("Telefonnummer wählen", Intent.ACTION_CALL, "tel:(+49) 123 4567890 "),
             new IntentData("Telefonnummer aufrufen", Intent.ACTION_DIAL, "tel:(+49) 123 4567890"),
             new IntentData("SMS verschicken", Intent.ACTION_VIEW, "sms:(+49) 123 4567890"),
             new IntentData("Webseite anzeigen", Intent.ACTION_VIEW, "http://me4bruno.wordpress.com"),
             new IntentData("Foto aufnehmen", "android.media.action.IMAGE_CAPTURE", null),
             new IntentData("Kontakte anzeigen", Intent.ACTION_VIEW, "content://contacts/people/"),
             new IntentData("Position auf Karte anzeigen", Intent.ACTION_VIEW, "geo:53.076397,8.803648?z=14"),
             new IntentData("Adresse auf Karte anzeigen", Intent.ACTION_VIEW, "geo:0,0?q=Bremen (Hansestadt Bremen)"),
             new IntentData("Google Street View anzeigen", Intent.ACTION_VIEW, "google.streetview:cbll=53.076397,8.803648"),
             new IntentData("Maps-Navigation anzeigen", Intent.ACTION_VIEW, "http://maps.google.com/maps?saddr=53.5536,9.9925&daddr=53.076397,8.803648"),
             new IntentData("Navigator-Navigation anzeigen", Intent.ACTION_VIEW, "google.navigation:q=53.076397,8.803648")
       };
    
       private static class IntentData {
    
          private final String label;
          private final String action;
          private final Uri uri;
    
          public IntentData(String label, String action, String uri) {
             this.label = label;
             this.action = action;
             this.uri = uri != null ? Uri.parse(uri) : null;
          }
    
          @Override
          public String toString() {
             return label;
          }
       }
    
       @Override
       public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
    
          setListAdapter(new ArrayAdapter<IntentData>(this, android.R.layout.simple_list_item_1, INTENT_DATA));
         
          getListView().setOnItemClickListener(new OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                IntentData selectedIntentData = INTENT_DATA[position];
                Intent intent = new Intent(selectedIntentData.action, selectedIntentData.uri);
                startActivity(intent);
             }
          });
       }
    }
    

Die Beispiele unterscheiden sich nur darin, mit welchen Daten der jeweilige Intent ausgeführt wird. Außerdem müssen eventuell Berechtigungen in der Datei AndroidManifest.xml festgelegt werden.

Telefonnummer wählen

Damit mit dem folgenden Intent auch wirklich eine Telefonnummer gewählt werden kann, muss die Berechtigung android.permission.CALL_PHONE eingetragen sein:

new Intent(Intent.ACTION_CALL, Uri.parse("tel:(+49) 123 4567890"))

Telefonnummer aufrufen

Im Gegensatz zum vorherigen Aufruf benötigen wir hier keine besondere Berechtigung, da in diesem Fall der Anwender selber per Tastendruck die Wahl der Telefonnummer startet.

new Intent(Intent.ACTION_DIAL, Uri.parse("tel:(+49) 123 4567890"))

SMS verschicken

Mit dem folgenden Code wird das Verschicken einer SMS vorbereitet. Um den Inhalt der SMS vorzubelegen, benötigen wir eine weitere Zeile Code.

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("sms:(+49) 123 4567890"))
intent.putExtra( "sms_body", "Der Inhald der SMS..." ); 

Webseite anzeigen

Sobald die Uri mit dem HTTP-Protokoll versehen ist, meldet sich der Browser zur Stelle.

new Intent(Intent.ACTION_VIEW, Uri.parse("http://me4bruno.wordpress.com"))

Foto aufnehmen

Wenn wir für das Gerät eine SD-Karte angegeben haben, kann man mit dem Emulator die Verwendung der Kamera simulieren.

new Intent("android.media.action.IMAGE_CAPTURE", null)

Kontakte anzeigen

Das folgende Beispiel zeigt, wie man zur App für die Verwaltung der Kontaktdaten gelangt. Beim ersten Start ist die Liste mit den Kontaktdaten leer, sodass man erstmal ein paar Kontakte anlegen sollte.

new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/"))

Position auf Karte anzeigen

Für Karten können wir die App Maps von Google nutzen. Wenn wir uns eine Karte auf Basis einer Position erstellen lassen, kann man zusätzlich den Zoomfaktor angeben.

new Intent(Intent.ACTION_VIEW, Uri.parse("geo:53.076397,8.803648?z=14"))

Adresse auf Karte anzeigen

Statt der Position kann man auch eine Adresse angeben. Das folgende Beispiel zeigt, dass wir zusätzlich optional einen Namen in Klammern übergeben können, so dass der Positionsmarker den angegebenen Namen erhält.

new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=Bremen (Hansestadt Bremen)"))

Google Street View anzeigen

Falls in unserem verwendeten Ort Daten von Google-Street-View vorhanden sind, ist der folgende Aufruf eventuell interessant.

new Intent(Intent.ACTION_VIEW, Uri.parse("google.streetview:cbll=53.076397,8.803648"))

Navigieren mit Google Maps

Wenn wir eine App nutzen wollen, die uns zu einem Ort navigiert, haben wir mehrere Möglichkeiten. Bei der 1. Variante geben wir eine HTTP-Adresse an, die den Startpunkt und den Zielpunkt enthält. Wenn wir den Intent starten, bekommen wie eine Auswahl zwischen zwei Apps angezeigt, die den Intent verarbeiten können. Ein Browser, der uns die Google-Maps-Seite anzeigt, oder die App von Google mit dem Namen Maps.

new Intent(Intent.ACTION_VIEW, Uri.parse("http://maps.google.com/maps?saddr=53.5536,9.9925&daddr=53.076397,8.803648"))

Navigieren mit Google Navigation

Bei der 2. Variante verwenden wir die App von Google mit dem Namen Navigation. Dabei müssen wir lediglich das Ziel angeben:

new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:q=53.076397,8.803648"))

Wenn Navigation gestartet wird, benötigt die App zur Berechnung der Route die aktuelle Position. Da im Emulator kein GPS-Sensor vorhanden ist, muss man die aktuelle Position manuell setzen. Das kann man einfach per telnet erledigen:

telnet localhost 5554
geo fix 9.9925 53.5536

Als App-Entwickler können wir also mit wenig Aufwand sehr gute, spannende Apps für uns arbeiten lassen… 🙂

Ein Kommentar

  1. Sehr einfach und inhaltlich abgerundet erklärt. Super Dank.