Kürzlich hatte ich das Vergnügen mich 1 Tag mit Google Android beschäftigen zu können. Dazu passend gibt es ein kleines Howto um auch anderen da draußen den Einstieg zu erleichtern. Voraussetzung für das Tutorial sind eine fertig installierte Eclipse IDE und Java Kenntnisse. Eine kleine Einführung was Android eigentlich kann und ist hab ich hier geschrieben.
Getting Started
Um starten zu können muss man sich erstmal das SKD Android von der Homepage laden. Dann wird das Eclipse Plugin hinzu gefügt. Das ist nicht unbedingt erforderlich, erleichter aber das arbeiten mit Android enorm. Plugins für andere IDEs gibt es leider derzeit noch nicht. Installiert wird das Android Plugin wie jedes andere Eclipse Plugin über die Update Funktionen:
- Help > Software Updates > Find and Install….
- Optioen “Search for new features to install” auswählen
- Klick “New Remote Site“
- url eingeben:
https://dl-ssl.google.com/android/eclipse/
- Alle Packete auswählen, dann den Nutzngsbediengungen zustimmen und “Install All” klicken
Danach muss noch der Pfade zum Android SDK in den Preferences angegeben werden:
- Window > Preferences..
- In der Treeview links Android Suchen
- dann unter SDK Location den Pfad wo es liegt angeben
Hello World Applikation
Neues Android Projekt anlegen
- New Project → Android → Android Project
- Name, Package etc. wie bei normalen Java Applikation
Es wird automatisch folgende Hello World App erstellt (Klasse ist wie gewohnt im src Ordner)
public class HelloAndroid extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
}
}
Dieses einfache Beispiel besteht grob gesagt aus der HelloWorld Klasse und der R Klasse. Die R Klasse ist dabei die Repräsendation des XML Layouts, das in res/layouts/main.xml. Diese Klasse aktualisiert sich selbst sobald sich in den Layouts etwas ändert. Händisches editieren ist nicht empfohlen.
Ordnerstruktur
- src (Source Klassen analog zu tradtionellen Java App)
- assets
- bin (kompiliertes Dalvik Executable (.dex) File
- res
- drawable (Grafiken, etc)
- layout (xml Dateien mit View Informationen)
- values (String Properties)
- AndroidManifest.xml
Komponenten einer Applikation
- Activities Repräsentieren Screen auf dem Handsets. Eine Activity kann auf User Inputs reagieren und besteht aus Views (UI). Eine abgeleitete Klasse extends Activity und man muss mit import android.app.Activity; importieren. Activities müssen im manifest definiert werden:
Soll eine Activity beim Starten des Programms ausgeführt werden kann man sie als Main mit einem Intent-Filter definieren:
- Intent definiert Ablauf einer Applikation. Stelle Action zur Verfügung/ URI. Beispiele: VIEW; EDIT. Request + Data Handling
- Intent Filter Filtert die Weiterleitung eines Intent an eine spezielle Activity.
- Intent Reciever Lauschen auf Ereignisse des Endgerätes. zb. Starten einer Applikation wenn Anruf eingeht. Ist unabhängig von der Applikation und wir im androidmanifest.xml definiert.
- Service Stellt Funktionalität bereit die nicht umittelbar mit User-Interaktionen zu tun haben. zb. MP3 abspielen im Hintergrund. In diesem Fall ist die Activity das UI und das Service der MP3 Decoder und Player
- Content Provider Interface für Standard Datenmanagements-Operationen
Tutorial
Auf der Android Homepage gibt es weiters ein schönes Tutorial, das die Basiskonzept von Android in einem netten kleinen Praxisbeispiel verpackt. Ich hab auch anfangs dieses Tut durchgearbeitet und kann es nur jedem empfehlen.
Google Maps Applikation
Für die Google Maps App ein neues Android Projekt anlegen:
Als ersten Schritt wollen wir uns nur mal eine Karte mit einem fix definierten Startpunkt ausgeben lassen. Für die Karten-Ausgabe gibt es in Android einen eigene MapView. Wir ändern die onCreate Methode der Hauptactivityklasse (bei mir mapapp.java) wie folgt:
private MapView map;
(...)
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
map = new MapView(this);
// einen startpunkt der Karte als Point defnieren. Achtung: die Koordinatenpaare werden nicht als double sondern als int gespeichert und müssen daher 10e6 multipliziert werden
Point p = new Point((int) (48.416402 * 1000000), (int) (16.025078 * 1000000));
// Der MapController Steuert die Aktionen mit der Karte
MapController mc = map.getController();
// zum defnierten Point p scrollen
mc.animateTo(p);
// Die Zoomstufe setzen
mc.zoomTo(9);
// Karte ausgeben
setContentView(map);
}
Um eine Android Applikation zu starten müsst ihr beim ersten Mal eine Launch-Konfig erstellen. Dafür auf Run->Open Run Dialog.. klicken und die Einstellungen ähnlich meinen hier vornehmen
Wenn ihr auf den Tab Emulator geht könnt ihr euch noch die visuelle Form des Android Emulators aussuchen. Abschließend auf Run klicken um den Build Prozess zu starten.
Nachdem der Android Emulator geladen ist, solltet ihr in etwa sowas sehen:
Als nächstes geben wir dem User einiges mehr an Kontrolle über die Karte. Wir implementieren Hotkeys für die wichtigsten Funktionen wie Zoomen und die Map-Modi wechseln:
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_I) {
int level = map.getZoomLevel();
map.getController().zoomTo(level + 1);
return true;
} else if (keyCode == KeyEvent.KEYCODE_O) {
int level = map.getZoomLevel();
map.getController().zoomTo(level - 1);
return true;
} else if (keyCode == KeyEvent.KEYCODE_S) {
map.toggleSatellite();
return true;
} else if (keyCode == KeyEvent.KEYCODE_T) {
map.toggleTraffic();
return true;
}
return false;
}
Als nächstes Feature wollen wir eine Suche in der Karte implementieren. Dazu machen wir im ersten Schritt ein Options-Menü, das uns zur Suchmaske leitet:
private static final int SEARCH_ID = Menu.FIRST;
private static final int ACTIVITY_SEARCH=0;
(...)
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, SEARCH_ID, R.string.map_search);
return true;
}
@Override
public boolean onMenuItemSelected(int featureId, Item item) {
super.onMenuItemSelected(featureId, item);
switch(item.getId()) {
case SEARCH_ID:
Intent i = new Intent(this, MapSearch.class);
startSubActivity(i, ACTIVITY_SEARCH);
break;
}
return true;
}
in den strings.xml muss noch der String für den Wert “map_search” gesetzt werdeb:
Suche in der Karte
Wie ihr sehen könnt starte ich nach dem Klick auf den SEARCH_ID Eintrag im Options-Menü eine Sub-Activity auf Basis der neuen MapSearch Klasse. Also mal eine neue Klasse anlegen mit New->Class. Die Klasse extended Activity und muss natürlich auch import android.app.Activity;. Ihr könnt jetzt händisch die onCreate() Methode schreiben oder im Optionen Menü mit Rechtsklick in den Editor-> Source -> Override/Implement Methods die gewünschten Methoden auswählen die überschrieben werden soll – in userem Fall nur die onCreate() Methode.
Für die Suche machen wir uns dann ein eigenes XML Layout:
Dazu dann noch die Klasse mapSearch ausimplementieren. Sie besteht aus einem einfachen Aufbauen des Layouts und Verarbeiten des OK Klicks, der die Suche abschließt:
private EditText search;
private static final int ACTIVITY_DISPLAY=0;
public static final String KEY_ROW_ID = "search";
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.map_search);
search = (EditText) findViewById(R.id.search);
Button confirmButton = (Button) findViewById(R.id.confirm);
confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
setResult(RESULT_OK, search.getText().toString());
finish();
}
});
}
Für die Rückgabe der Such String zur Karten Activity benutzen wir die setResult Methode, die einen String an Daten zur Hauptactivity transportieren kann. Diesen String data werden wir dann in einem weiteren Schritt auslesen und die Suche auf der Karte visualisieren. Die strings.xml muss wieder um folgende Werte ergänzt werden:
OK <
string name="map_search">Suche in der Karte
Suche <
auch im AndroidManifest muss die neue Activity definiert werden:
Als nächsten Schritt wechseln wir wieder zurück in die Hauptklasse des Projektes und fügen folgende Methode hinzu, welche die Such-Funktionalität zur Verfügung stellt:
private String search = "";
(...)
private MapPoint search(String q) {
MapPoint mapPoint = new MapPoint(map.getMapCenter().getLatitudeE6(), map.getMapCenter().getLongitudeE6());
Map myMap = new Map(getDispatcher(), null, 0, 0, 0, mapPoint, Zoom.getZoom(map.getZoomLevel()), 0);
Search search = new Search(q, myMap, 0);
getDispatcher().addDataRequest(search);
while (!search.isComplete()) {
}
MapPoint point = null;
for (int i = 0; i < search.numPlacemarks(); i++) {
Placemark placemark = search.getPlacemark(i);
point = placemark.getLocation();
}
return point;
}
Die Methode nutze für die Suche das Search Objekt. Beim Instanzieren wird der Suchbegriff und ein MapView Objekt übergeben. Dieses kann aus ??? Gründen nicht die gerade aktive Karte sein, sondern muss ein extra dafür instanziertes Objekt sein. Darum der etwas seltsame Code. Wie schon vorher angesprochen muss jetzt nur noch der Such String aus der Such Activity übernommen werden. Das passiert in der Methode onActitivityResult welche den data String aus der Such Activity empfängt und die Suche ausführt:
@Override
protected void onActivityResult(int requestCode, int resultCode, String data, Bundle extras) {
super.onActivityResult(requestCode, resultCode, data, extras);
search = (String) data.toString();
if (search != null) {
MapPoint point = this.search(search);
if (point != null) {
MapController mc = map.getController();
Point point1 = new Point(point.getLatitude(), point.getLongitude());
mc.animateTo(point1);
mc.zoomTo(12);
}
}
}
Damit wäre einmal das Map Beispiel soweit fertig. Was noch im Code fehlt ist eine Fehlerbehandlung der Suche oder das Handling bei mehreren Suchergebnissen.
Das fertige Projekt könnt ihr auch noch downloaden: mapapp.rar
Ressourcen
Offizielle Homepage
Blog
Download Seite
API Dokumentation
Tutorial
User Gruppe
Leave a Reply