Android Anfänger Workshop
Einleitung
Hier findet ihr die deutsche Übersetzung meiner Präsentation "Android Beginners Workshop", die ich auf dem Mobile Monday m2d2 Developer Day in Düsseldorf am 23.02.2010 gehalten hab. Dieser Workshop richtet sich an Anfänger, die hier ihre erste "Hello World"-App erstellen werden.
Die wichtigsten Grundlagen
Basics
- Android Apps werden in Java programmiert
- Fast alle Java-Klassen stehen zur Verfügung plus Verschlüsselung, HTTP, JSON, XML Bibliotheken
- Keine main()-Funktion - stattdessen: lose gekoppelte Komponenten, eine oder mehr davon als Einstiegspunkt definierbar
- Wichtigste Komponente: "Activity" - entspricht einem sichtbaren Fenster auf dem Screen
Im folgenden Bild seht ihr drei Activities der Contacts/Dialer App. Gut zu sehen sind die zwei Einstiegspunkte: Die App kann über das Icon "Contacts" sowie über das Icon "Dialer" gestartet werden. Die App startet dann mit der entsprechenden Activity.
Activity, View, Event, Intent
Activity
- definiert eine "View", zur Anzeige auf dem Screen
- behandelt "Events" (z. B. Klick auf einen Button)
- benutzt "Intents", um andere Activities zu starten
View
- eine "View" ist der sichtbare Teil der Activity
- definiert in einer XML-Layout-Datei (oder im Code)
Event
- wird ausgelöst, wenn etwas geschieht (z. B ein Button geklickt wird)
- ruft eine Listener-Methode auf, sofern ein Listener definiert ist
Intent
- startet eine andere Activity ("öffnet ein neues Fenster")
- kann Daten an die zu startende Activity übergeben
- kann Activities aus anderen Apps starten!
Activity Lifecycle
Resourcen auf dem Mobiltelefon sind limitiert. Daher muss das Android-Betriebssystem in der Lage sein, nicht aktive Activities (d. h. nicht im Vordergrund sichtbar), jederzeit zu beenden.
Jede Activity hat einen sogenannten Lifecycle ("Lebenszyklus"), der vom Betriebssystem gesteuert wird.
Um Datenverlust oder den Verlust des Zustands einer Activity zu vermeiden, müssen die Daten/der Zustand der Activity gesichert werden, wenn diese pausiert (nicht mehr im Vordergrund, aber noch sichtbar) oder gestoppt (nicht mehr sichtbar) wird.
Einrichtung der Entwicklungsumgebung
Eclipse
Zunächst wird Eclipse benötigt. Die Installation von Eclipse wird hier jedoch nicht behandelt.
Android SDK Starter Package
Lade das SDK Starter Package für Dein Betriebssystem unter http://developer.android.com/sdk/index.html herunter und installiere es.
SDK Packages
Starte des SDK Starter Package (als Administrator unter Windows Vista / Windows 7). Beim ersten Start siehst Du eine Auswahl verfügbarer Pakete, die Du alle installieren solltest (alle SDK Plattformen und Dokumentation).
Zusätzlich solltest Du noch "Usb Driver Package" auswählen - damit kannst Du nachher Deine App aus Eclipse heraus direkt auf Deinem Android-Handy starten und debuggen:
ADT (Android Development Tools) Eclipse Plugin
Die folgende Beschreibung ist für Eclipse 3.5 (Galileo) und Eclipse 3.6 (Helios). Instruktionen für Eclipse 3.4 (Ganymede) gibt es unter http://developer.android.com/sdk/eclipse-adt.html.
- Wähle "Help" → "Install New Software".
- Im "Available Software"-Dialog, klicke den "Add"-Button...
- Im "Add Site"-Dialog, gib einen Namen ein (z. B. "Android Plugin") und die folgende URL als Location: https://dl-ssl.google.com/android/eclipse/ (probier "http", wenn "https" nicht funktioniert). Klick den "OK"-Button.
- Zurück im "Available Software"-Dialog, wähle die Checkbox neben "Developer Tools" und klicke "Next".
- Im "Install Details"-Dialog, klicke "Next", um die Lizenzvereinbarung zu akzeptieren und klick auf "Finish".
- Eclipse neustarten.
- Wähle "Window" → "Preferences".
- Im "Preferences"-Dialog, wähle "Android".
- Gib den SDK-Ordner ein (z. B. "C:\Programme\android-sdk-windows") und klicke auf "OK".
Entwicklung und Test einer "Hello World" App
Neues Projekt erstellen
Mit dem ADT-Assistenten wird ein neues Projekt erstellt:
Wähle "File" → "New" → "Project..."; im "New Project"-Dialog wähle "Android Project" aus dem "Android" Order.
Füll den "New Android Project"-Dialog wie folgt aus:
- Project name: "Hello Workshop"
- Verwende die "default location" oder lege eine andere Location fest
- Build target: Android 1.6 (wir sorgen später für 1.5-Kompatibilität)
- Application name: "Hello Workshop"
- Package name: "de.test.hello"
- Create Activity: "HelloWorkshopActivity"
- Min SDK Version: "4"
Klicke auf den "Finish"-Button.
Der "New Project"-Assistent hat folgende Dateien und Ordner erstellt:
| HelloWorkshopActivity.java: | Klasse der Haupt-Activity |
| R.java: | Resourcen-ID-Definitionen (automatisch erstellt, nicht editieren!) |
| /assets: | Ordner für Binär-Dateien (alles, was Android nicht selbst verwaltet) |
| /res: | Ordner für Resource-Dateien (Bilder, Layouts, Strings, ...) |
| /res/drawable-hdpi/icon.png: | Logo in hoher Auflösung (72 x 72 Pixel – 240 dpi) |
| /res/drawable-ldpi/icon.png: | Logo in niedriger Auflösung (36 x 36 Pixel – 120 dpi) |
| /res/drawable-mdpi/icon.png: | Logo in mittlerer Auflösung (48 x 48 Pixel – 160 dpi) |
| /res/layout/main.xml: | Layout-Definition für View der Haupt-Activity |
| /res/values/strings.xml: | String-Definitionen |
| AndroidManifest.xml: | "Manifest"-Datei, definiert Infos wie Name, Logo und Haupt-Activity |
| default.properties: | Projekt-Eigenschaften |
AndroidManifest.xml
Damit Handys mit hohen Auflösungen (z. B. Motorola Milestone) auch die hdpi-Resourcen verwenden, muss folgender Eintrag in die AndroidManifest.xml-Datei eingefügt werden:
<supports-screens android:anyDensity="true" />
Anonsten würden bei hohen Auflösungen die mdpi-Resourcen verwendet und hoch-skaliert werden.
Damit die App auf Handys mit großem Screen (Archos 5) oder kleinem Screen (HTC Tattoo) den kompletten Bildschirm ausfüllt bzw. überhaupt läuft müssen folgende Attribute dem zuvor eingefügten Element hinzugefügt werden:
<supports-screens android:anyDensity="true"
android:largeScreens="true"
android:smallScreens="true" />
Ansonsten werden Handys mit großem Screen die App nur in einem kleinen Bereich anzeigen und Handys mit kleinem Screen werden die App nicht starten.
res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, HelloWorkshopActivity!</string>
<string name="app_name">Hello Workshop</string>
</resources>
Definiert Strings, die in den Manifest- und Layout-Dateien referenziert wurden (könnten auch im Code referenziert werden):
android:label="@string/app_name"
ist äquivalent zu
android:label="Hello Workshop"
Natürlich nur solange wir keine strings.xml-Dateien in anderen Sprachen hinzufügen. Wenn Du Deine App lokalisieren willst, solltest Du Deine Strings immer in Resourcen-Dateien auslagern!
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
Definiert ein (einfaches) Layout namens "main" (bloß ein Name, hat keine Bedeutung), welcher später in der Activity referenziert wird.
Das Layout sieht wie folgt aus:
R.java
Automatisch erstellt – definiert Integer-Konstanten für jede Resource. Diese Datei niemals editieren – man braucht sie eignetlich nicht mal einzusehen.
package de.test.hello;
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int icon=0x7f020000;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f040001;
public static final int hello=0x7f040000;
}
}
HelloWorkshop2Activity.java
HelloWorkshop2Activity.java
package de.test.hello;
import android.app.Activity;
import android.os.Bundle;
public class HelloWorkshopActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Wichtig ist hier die letzte Zeile:
setContentView(R.layout.main);
Diese setzt das angegebene Layout als View dieser Activity. Die Konstante aus der R-Klasse referenziert das Layout, welches in der Datei main.xml definiert wurde.
Emulator ("Android Virtual Device") erstellen
- Klicke auf das "Android SDK and AVD manager"-Icon in der Icon-Leiste von Eclipse.
- Klicke auf "New"
- Im "Create new AVD"-Dialog, gib folgendes ein:
- Name: "G1"
- Target: "Android 1.6 - API Level 4"
- SD Card Size: "1024" MiB
- Skin: Built-in: "Default (HVGA)"
- Dann klicke auf "Create AVD" (kann eine Weile - bis zu einigen Minuten - dauern)
App zum ersten Mal starten
- Wähle "Run" → "Run" (oder drücke Strg + F11).
- Im "Run As"-Dialog, wähle "Android Application" und klicke auf "OK".
- Eclipse startet jetzt automatisch den "G1" Emulator, den wir gerade erstellt haben. Sollte es mehrere passende Emulatoren geben, erscheint zunächst ein entsprechender Auswahldialog.
- Nach rund einer Minute solltest Du die App im Emulator sehen:
Ziel für das Tutorial
Das wollen wir heute erreichen:
- Eine View erstellen, die so aussieht wie die Grafik rechts.
- Der User soll seinen Namen eingeben können.
- Wenn der User auf einen der Buttons klickt und kein Name eingetragen wurde, soll sich Dialog mit einer Fehlermeldung angezeigt werden.
- Wenn der User auf einen Button klickt und seinen Namen eingegeben hat,
→ soll der User mit einer Popup-Nachricht („Toast“) gegrüßt werden
→ soll sich die Begrüßung am oberen Bildschirmrand ändern.
Komponenten hinzufügen
Füge ein „Enter your name“-Textfeld unter die ersten TextView-Komponente ein:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/enter_your_name"
/>
Eclipse wird jetzt eine Fehlermeldung anzeigen: „No resource found that matches the given name (at 'text' with value '@string/enter_your_name').
Füge die fehlende Resource zu der Datei strings.xml hinzu:
<string name="enter_your_name">Enter your name:</string>
Die Fehlermeldung in main.xml wird jetzt verschwinden.
Füge ein Eingabefeld unter der „Enter your name“-Komponente ein:
<EditText
android:id="@+id/name_field"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
Die erste Zeile weist der Komponente die ID „name_field“ zu.
Unter dem Namens-Feld wollen wir die Buttons nebeneinander anordnen. Dazu benötigen wir ein LinearLayout mit horizontaler Orientierung und darin die zwei Buttons.
Inneres LinearLayout mit zwei Buttons:
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/hi_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/hi_button"
/>
<Button
android:id="@+id/hello_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/hello_button"
/>
</LinearLayout>
Füge die Button-Texte in die strings.xml-Datei ein:
<string name="hi_button">Say Hi!</string> <string name="hello_button">Say Hello!</string>
Schauen wir uns das Layout einmal an!
Auf der "main.xml"-Seite in Eclipse, klicke auf den "Layout"-Reiter am unteren Rand und Du wirst folgendes sehen:
Activity erweitern
Nun erweitern wir unsere Activity. Öffne "HelloWorkshopActivity.java" und füge folgende Felder am Beginn der Klasse ein:
private Button hiButton; private Button helloButton;
Am Ende der onCreate-Methode, füge folgenden Code ein:
hiButton = (Button)findViewById(R.id.hi_button); hiButton.setOnClickListener(this); helloButton = (Button)findViewById(R.id.hello_button); helloButton.setOnClickListener(this);
Eclipse meldet nun dass HelloWorkshopActivity das Interface OnClickListener nicht implementiert. Klick auf die Fehlermeldung und wähle "Let 'HelloWorkshopActivity' implement 'OnClickListener'."
Nun zeigt Eclipse an, dass HelloWorkshopActivity die OnClickListener-Methoden nicht definiert. Klick auf die Fehlermeldung und wähle "Add unimplemented methods".
Wenn der User auf einen der Buttons klickt, müssen wir zunächst prüfen, ob er seinen Namen eingegeben hat. Füge folgenden Code in die „onClick“-Methode ein:
EditText nameField = (EditText) findViewById(R.id.name_field);
String name = nameField.getText().toString();
if (name.length() == 0) {
new AlertDialog.Builder(this)
.setMessage(R.string.error_name_missing)
.setNeutralButton(R.string.error_ok, null)
.show();
return;
}
Füge die zwei oben referenzierten Strings sowie zwei weitere in die strings.xml-Datei ein:
<string name="error_name_missing">Please enter your name.</string> <string name="error_ok">OK</string> <string name="hi_greeting">Hi %s!</string> <string name="hello_greeting">Hello %s!</string>
Der User hat seinen Namen eingetragen. Nun zeigen wir die Begrüßung an:
if (v == hiButton || v == helloButton)
{
int resourceId = v == hiButton ? R.string.hi_greeting
: R.string.hello_greeting;
String greeting = getResources().getString(resourceId, name);
Toast.makeText(this, greeting, Toast.LENGTH_LONG).show();
}
Schließlich wollen wir die Begrüßung am oberen Bildschirmrand ändern. Um den Text der Komponente zu ändern, müssen wir ihr zunächst eine ID zuweisen. Bearbeite die main.xml-Datei und füge wie folgt eine ID in das erste TextView-Element ein:
<TextView
android:id="@+id/greeting_field"
… />
Die zuvor erstellte Methode wird nun erweitert:
if (v == hiButton || v == helloButton)
{
int resourceId = v == hiButton ? R.string.hi_greeting
: R.string.hello_greeting;
String greeting = getResources().getString(resourceId, name);
Toast.makeText(this, greeting, Toast.LENGTH_LONG).show();
TextView greetingField = (TextView) findViewById(R.id.greeting_field);
greetingField.setText(greeting);
}
Und nun? Wir sind fertig – starte das Projekt!
Projekt starten
Starte das Projekt wie zuvor (am einfachsten mit Strg + F11), hier sind ein paar Screenshots:
Projekt kompatibel zu Android 1.5 machen (z. B. HTC Hero)
In Android 1.6 wurden unterschiedliche Bildschirmauflösungen und Pixeldichten eingefügt. Für Android 1.5 und älter sind die Ordner „drawable-hdpi“, drawable-ldpi“, „drawable-mdpi“ unbekannt.
- Ordner "drawable-hdpi" in "drawable-hdpi-v4" umbenennen, so dass Android 1.5 und älter ihn ignorieren
- Ordner "drawable-ldpi" in "drawable-ldpi-v4" umbenennen, so dass Android 1.5 und älter ihn ignorieren
- Ordner "drawable-mdpi" in "drawable" umbenennen, so dass Android 1.5 und früher ihn sehen
In der AndroidManifest.xml-Datei, ändere die Zeile
<uses-sdk android:minSdkVersion="4" />
in
<uses-sdk android:minSdkVersion="3" targetSdkVersion="4" />
Wie geht es weiter?
- Erstelle verschiedene Layouts für verschiedene Bildschirm-Orientierungen (horizontal, vertikal)
- Füge eine zweite Activity hinzu und starte sie aus der bestehenden Activity heraus (z. B. durch Klicken eines neuen Buttons)
- Probiere andere Layouts aus (http://developer.android.com/resources/tutorials/views/index.html)
- Schau Dir die Tutorials unter http://developer.android.com an.
Anhang - Quellcodes
HelloWorkshopActivity.java:
package de.test.hello;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class HelloWorkshopActivity extends Activity
implements OnClickListener {
private Button hiButton;
private Button helloButton;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
hiButton = (Button) findViewById(R.id.hi_button);
hiButton.setOnClickListener(this);
helloButton = (Button) findViewById(R.id.hello_button);
helloButton.setOnClickListener(this);
}
public void onClick(View v) {
EditText nameField = (EditText) findViewById(R.id.name_field);
String name = nameField.getText().toString();
if (name.length() == 0) {
new AlertDialog.Builder(this).setMessage(
R.string.error_name_missing).setNeutralButton(
R.string.error_ok,
null).show();
return;
}
if (v == hiButton || v == helloButton) {
int resourceId = v == hiButton ? R.string.hi_greeting
: R.string.hello_greeting;
String greeting = getResources().getString(resourceId, name);
Toast.makeText(this, greeting, Toast.LENGTH_LONG).show();
TextView greetingField = (TextView) findViewById(R.id.greeting_field);
greetingField.setText(greeting);
}
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/greeting_field" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="@string/enter_your_name" /> <EditText android:id="@+id/name_field" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" > <Button android:id="@+id/hi_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hi_button" android:layout_weight="1" /> <Button android:id="@+id/hello_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_button" android:layout_weight="1" /> </LinearLayout> </LinearLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, HelloWorkshopActivity!</string>
<string name="app_name">Hello Workshop</string>
<string name="enter_your_name">Enter your name:</string>
<string name="hi_button">Say Hi!</string>
<string name="hello_button">Say Hello!</string>
<string name="error_name_missing">Please enter your name.</string>
<string name="error_ok">OK</string>
<string name="hi_greeting">Hi %s!</string>
<string name="hello_greeting">Hello %s!</string>
</resources>
Bookmark / E-Mail
Klicke auf ein Icon, um diese Wiki-Seite zu bookmarken. » Diesen Artikel per E-Mail versendenKategorien
- Acer (2)
- AndroidPIT-Wiki: Ergänzungswürdige Seiten (2)
- AndroidPIT-Wiki: Zu löschende Seiten (5)
- Anleitungen (29)
- APN (12)
- Archos (1)
- Asus (2)
- Begriffserklärungen (17)
- Custom-Rom (1)
- Einstellungen (14)
- Entwicklung (11)
- Geräte mit NFC (5)
- Google (6)
- Handys mit NFC (3)
- Hardware (26)
- Hero (3)
- Hersteller (3)
- HTC (8)
- LG (2)
- Milestone (2)
- Motorola (3)
- Nexus-Geräte (6)
- NotionInk (1)
- Root (27)
- Samsung (7)
- Samsung Galaxy S i9000 (1)
- Sony Ericsson Xperia X10 Mini (5)
- Sony Ericsson Xperia X10 Mini Pro (8)
- Sony Ericsson Xperia X8 (2)
- Spiele (1)
- Tablet (20)
- Tablets mit NFC (2)
- Tipps und Tricks (12)
- Tools (6)
- Toshiba (1)
- User's Guide (1)
- Wiki (6)
- ZTE (1)















