Allgemeines

Als Programmierer für J2ME von Sun war es mein Wunsch, auf Android umzusteigen. Bei J2ME musste man eine XML-Datei als Beschreibung erstellen, dann die Midlet-Klasse mit dem JDK übersetzen, dann ein preverify machen und den Aufruf emulator mit der XML- Datei und einigen Parametern machen. In kurzer Zeit (unter 10 sek) war der Emulator da, und man konnte das Midlet mehrfach starten und beenden. Wollte man eine andere Anwendung ausführen, musste man das emulator-Programm beenden.
Mit diesem Wissen wollte ich apps für Android programmieren, mein Rechner hatte zuerst etwa 100 MB RAM und 100MHz Takt. Leider gab es immer wieder Probleme (Error type 1: Could not access the package manager, Error type 2: Unable to connect to activity manager; is the system running ?). Zudem dauerte es etwa 6 Minuten, bis der emulator gestartet war (adb -e get-state ergab die Meldung 'device'). Hierbei habe ich das SDK 1.5 (letzte Version von Google) verwendet, meine Bemühungen sollen im folgenden untersucht werden.

Start des Emulators

Hat man den emulator einmalig gestartet, so reichte dies irgendwie nicht aus, um mit 'adb -e shell' darauf zugreifen zu können. Man musste mehrfach in einer Schleife adb -e start-server, adb -e get-state aufrufen, und im Negativfall wieder adb -e kill-server und neuer Versuch, bis get-state lieferte: 'device'.
Das Startskript für den Emulator ist hier.
Der emulator belegt 147 MB virtuellen Speicher, 49 MB Resource und wechselnd zwischen 30% und 90% CPU.
adb (Android debug bridge) arbeitet mit Dämonen. Hiermit kann man die Erreichbarkeit des Emulators testen:
adb -e start-server
* daemon not running. starting it now *
* daemon started successfully *
adb -e get-state
device
Ein Aufruf mit sinnvollen Parametern kann so aussehen:
emulator -avd testavd -netdelay 0 -cpu-delay 0 -netfast -noaudio -no-boot-anim
-sdcard sd_emu.bin
Im Emulator sah ich nur einen schwarzen Hintergrund mit der Schrift 'A n d r o i d', was bedeutet, dass dieser nicht komplett gestartet ist, weil Endzustand eigentlich ein Standardbildschirm sein sollte.
Die laufenden Prozesse kann man sich in der Shell mit dem Kommando ps oder top anschauen. Hier sehe ich die verschiedenen Benutzer root, radio, system, media, bluetooth und app_*. Eine selbstprogrammierte Anwendung wie der oben vorgestellte Dateimanger läuft hierbei auch unter der Benutzerkennung app_*.

"Error Type 1: Could not access the Package Manager"

Dies erhalte ich, wenn ich nach Start des Emulators versuche:
 adb -e shell pm list packages 
Ich habe zuerst geglaubt, dass es ein Rechteproblem ist (leider nicht). Bei der Anmeldung an die Shell ist man Benutzer 'root', dies müsste für pm passen. Dahinter verbirgt sich der Aufruf
export CLASSPATH=/system/bin/framework/pm.jar
exec app_process /system/bin com.android.commands.pm.Pm "$@"
Was nichts gebracht hat, war den Aufruf 'start qemud' in der shell zu machen, so dass dessen Status auf 'running' steht - der Fehler kam trotzdem.

Einmal beobachtet ich bei dem Fehler im logcat, dass der Package-Manager gar noch nicht gestartet war, oder erst nachdem der Fehler kam:
...
I/SystemServer(   99): Starting Power Manager
I/SystemServer(   99): Starting Activity Manager
Error Type 1: ...
I/SystemServer(   99): Starting telephony registry
I/SystemServer(   99): Starting Package Manager  // erst danach !
...
Wenn ich nach Erhalten des Fehlers nochmals probiere: adb -e shell pm list packages, erhalte ich eine Auflistung der Pakete ohne Fehler. Auf Android-Seiten schlug jemand vor, stattdessen vor adb ein 'strace -o irgendwas adb kommando' zu setzen, bei mir brachte dies aber keine Verbesserung.
Eine Abhilfe ist bei mir also gewesen:
adb -e kill-server
adb -e start-server
adb -e logcat &
adb -e shell pm list packages
Nach einiger Zeit meldete logcat dann:
I/ServiceManager(   18): service 'activity' died
I/ServiceManager(   18): service 'package' died
...
und der Fehler 'Error type 1' kam bei Wiederholung erneut !
Es ist also m.E. nach ein Problem mit dem SystemServer bzw. ServiceManager, dass der Package Manager gar nicht bzw. zu spät gestartet wird, wenn (z.B. bei der Installation von Anwendungen) auf das pm-Skript zugegriffen wird.

"Error type 2: Unable to connect to activity manager; is the system running ?'

Dies erhalte ich, wenn ich nach Start des Emulators versuche:
adb -e shell am start -D HelloActivity
Hinter am verbirgt sich der Aufruf:
export CLASSPATH=/system/framework/am.jar
exec app_process /system/bin com.android.commands.am.Am $*
Auch hier habe ich über logcat nur(!) dann Probleme festgestellt, wenn der ActivityManager nicht rechtzeitig vorher gestartet wurde, siehe auch 'service list', ob der Dienst gestartet ist, also in den eckigen Klammern etwas drin steht. Abhilfe: Die gleiche wie für pm.

Zugriff mit adb auf Echtgerät/apk-Installation

Auf die sd-Karte kann man unter Linux mit klassischen mount zugreifen, allerdings kann man vor Android 2.2 keine Anwendungen (apps) auf der sd-Karte speichern oder dorthin verlagern. Man konnte sich mit dem Trick weiterhelfen, d ass man die Anwendung (x.apk) und eine HTML-Datei mit einem Verweis (a href="x.apk") auf der sd-Karte ablegte, und die erste Datei in den Webbrowser lädt - beim Klick auf den Verweis wird man gefragt, ob man die Anwendung x installieren oder ausführen will, womit man das Ziel erreicht hat.

Filter für logcat

Bei logcat werden i.A. sehr viele Infos rausgeworfen. Eine sinnvolle Einschränkung ist z.B.:
Wichtig: D/AndroidRuntime, D/PackageManager, D/ActivityManager, I/SystemServer, E, W
Weniger: D/dalvikvm, D/jdwp
Sinnvoller Filter also z.B.
adb -e logcat *:I *:W *:E AndroidRuntime:D PackageManager:D ActivityManager:D

Emulator ansprechen mit telnet

Standardmaessig ist dieser an Port 5554 ansprechbar (siehe Ausgabe bei emulator -verbose ...).
 telnet localhost 5554
Hier ist die Kommandoübersicht
Kommando Info
eventsimulate hardware events
geoGeo-location commands
gsmGSM related commands
killkill the emulator instance
networkmanage network settings
powerpower related commands
quit|exitquit control session
redirmanage port redirections
smsSMS related commands
avdmanager virtual device state
windowmanager emulator window

Ausführen der Anwendung

Dies geschieht mit dem Programm adb. Liegt das Programm unter /data/app, hat den Paket-Pfad com.example.android.helloactivity und den Namen HelloActivity als Hauptaktivität, so kann man dies starten durch Angabe von Aktion, Kategorie und Komponente:
am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
- n com.example.android.helloactivity/com.example.android.helloactivity.HelloActivity
adb meldet dann: "Starting: Intent { ...} "

Auswirkungen einer Speicheraufrüstung

Ich habe mir ein neues Mainboard besorgt, mit knapp unter 1GB RAM und einer CPU mit etwa 750 Mhz Takt. Die Auswirkungen waren folgende:
- Der Emulator war in einer Minute da, zudem blieb er nicht beim Wort 'A n d r o i d' stehen, sondern lief bis zu einem Startbildschirm.
- Der virtuelle Speicher war 153 MB, die Resource etwa 129MB, die CPU-Auslastung in der Wartezeit unter 10%, d.h. die CPU-Auslastung des alten Mainboards war durch den Ein-/Auslagerungsspeicher (Swap) bedingt.
- Alle Dienste z.B. package, activity waren da, also waren error type x der Tatsache geschuldet, dass der Emulator aus Speichermangel diese Dienste nicht gestartet hatte.

Subjektives Fazit über den Emulator

Wer schon mal andere Emulatoren benutzt hat (J2ME-WTK), und einen älteren PC mit einer langsameren CPU und bescheidenem Arbeitsspeicher hat, kann enttäuscht sein. Nur mit Eclipse kann man gut arbeiten.
Zu dem oben beschriebenen Problemen mit Package/Activity Manager habe ich im Internet leider nichts richtiges gefunden, also selbst Beobachtungen anstellen müssen; der Vorschlag mit strace scheint damit zusammenzuhängen, dass der entsprechende Service (Package, Activity) zu dem Zeitpunkt gestartet war. Bevor man also versucht, ein Paket zu installieren und/oder auszuführen, muss man sicherstellen, dass die Dienste da sind:
adb -e shell service check package   # --> found
adb -e shell service check activity  # --> found
Eine Speicheraufrüstung konnte die Probleme mit error type x zuverlässig beseitigen.