zurück zum Artikel

Die Architektur von Android

| Arno Becker

Android geht in vielerlei Hinsicht ganz andere Wege als andere Linux-Versionen – das beginnt bei Anpassungen am Kernel und hört bei der virtuellen Maschine Dalvik noch lange nicht auf.

Die Architektur von Android

Android geht in vielerlei Hinsicht ganz andere Wege als andere Linux-Versionen – das beginnt bei Anpassungen am Kernel und hört bei der virtuellen Maschine Dalvik noch lange nicht auf. Die Besonderheiten der Android-Architektur zu kennen hilft dabei, die Eigenarten der populärsten Linux-Variante zu verstehen.

Es ist schon erstaunlich, wie viele Funktionen ein modernes Smartphone in sich birgt: telefonieren, Internet-Zugang, Spiele, Videos drehen … Selbstverständlich ist das nicht, eher ein kleines Wunder: Jede Funktion verbraucht Strom und Speicher, und das sind auf mobilen Geräten sehr endliche Ressourcen. Android ist ein Betriebssystem mit Linux-Kernel für Smartphones, aber auch andere Embedded Systems, das den Beschränkungen solcher Geräte Rechnung trägt. Es lohnt sich, einen genaueren Blick auf Android zu werfen: Vieles, was an der Android-Systemarchitektur besonders ist, hat direkte Auswirkungen auf das Verhalten von Android-Geräten und -Anwendungen.

Android ist eine Open-Source-Plattform, die von der Open Handset Alliance entwickelt wird, einem von Google initiierten breiten Zusammenschluss von Netzbetreibern, Smartphone-, Prozessor- und Chip-Herstellern sowie Softwarefirmen. Kern des Betriebssystems ist ein angepasster Linux-Kernel 2.6. Zudem sind zahlreiche Treiber und Bibliotheken verändert oder vollständig ersetzt – ein normales Linux würde die mobile CPU zu stark belasten, wodurch Anwendungen im Multitasking-Betrieb nicht schnell genug laufen würden und der Akku eines mobilen Geräts im Handumdrehen geleert wäre.

Daher erweitert Android das klassische Power Management des Linux-Kernels, um es an die Gegebenheiten mobiler Hardware anzupassen. So muss das System beispielsweise die Hintergrundbeleuchtung von Tastatur und Bildschirm ein- und ausschalten können. Ebenso muss das System den Status des Akkus überwachen und zuverlässig das Gerät herunterfahren, bevor die Stromversorgung zusammenbricht.

Unter Android läuft jede Anwendung als eigener Prozess, jedoch können die Programme Teile anderer Anwendungen nutzen. Folglich kommunizieren Prozesse intensiv miteinander. Diese Interprozesskommunikation (IPC) bringt normalerweise ein aufwendiges Marshalling und Unmarshalling mit sich – die auszutauschenden Daten müssen zwischen ihrer internen Repräsentation und einem zur Übermittlung geeigneten Format hin- und hergewandelt werden. Das verbraucht nicht nur Speicher, da dazu exzessiv Objekte erzeugt werden müssen, sondern belastet auch die CPU.

Um das zu vermeiden, implementiert Android über einen speziellen Treiber namens Binder eine besonders ressourcenschonende Form der Interprozesskommunikation, die den Datenaustausch zwischen Prozessen mittels Shared Memory realisiert: Programme tauschen per IPC lediglich Referenzen auf Objekte aus, die im Shared Memory abgelegt sind.

Der Systemaufbau von Android oberhalb des Kernels unterscheidet sich deutlich von Linux-Versionen für Desktop-Systeme oder Server.

Der Systemaufbau von Android oberhalb des Kernels unterscheidet sich deutlich von Linux-Versionen für Desktop-Systeme oder Server.

Auch für dessen Verwaltung unter Berücksichtigung von Zugriffsberechtigungen enthält Android mit Ashmem einen eigenen Treiber, der Schlüssel zum Zugriff auf geteilte Speicherbereiche vergibt. Alle Prozesse, die den Schlüssel kennen, können Daten über diesen Speicherbereich austauschen und den Schlüssel anschließend verwerfen. Gibt es auf einen Speicherbereich keine Referenz mehr, sind also alle Schlüssel verworfen, gibt ihn der Kernel frei. Wird der Gerätespeicher knapp, kann der Low Memory Killer, ein Bestandteil von Ashmem, auch Speicherbereiche freigeben, auf die es noch Referenzen gibt.

Wie bei modernen Betriebssystemen üblich, arbeitet Android mit einer virtuellen Speicherverwaltung: Der physikalische Speicher wird nicht direkt alloziert, sondern über Tabellen auf virtuelle Speicheradressen abgebildet. Allerdings verwendet Android keinen Swap Space, der normalerweise mit in den virtuellen Speicherbereich eingeht und ihn vergrößert – das System muss mit dem zur Verfügung stehenden Gerätespeicher auskommen. Android-Geräte können daher komplett auf externe Speichermedien wie SD-Karte oder Festplatte verzichten.

Zu den Vorteilen eines virtuellen Speichermanagements gehört, dass über die virtuellen Adressen ein zusammenhängender Speicherbereich zur Verfügung steht, der sich physikalisch über viele verstreute Speicherseiten verteilen kann. Ein weiterer Vorteil ist, dass sich virtuelle Speicherbereiche effizient von mehreren Prozessen nutzen lassen, da jeder Prozess nur die Startadresse und die Größe des Speichers kennen muss, nicht jede einzelne Speicherseite.

Zwei weitere Android-spezifische Kernelmodule, der Kernel-Debugger und der Logger, ermöglichen das Debuggen von Android-Anwendungen sowie die Ausgabe von Logging-Information aus Programmen und deren Auslesen mit dem Kommando logcat.

Auch bei den Änderungen an den Bibliotheken steht die Optimierung des Strom- und Speicherverbrauchs im Vordergrund; allerdings gibt es auch rechtliche Probleme. Anstelle der Glibc verwendet Android die C-Bibliothek Bionic. Sie ist (unter Aufgabe vollständiger Glibc-Kompatibilität) mit gut 200 KByte deutlich kleiner als die Standard-C-Bibliothek von Linux, auf Geschwindigkeit optimiert und um einige Android-spezifische Features erweitert.

Für jede Anwendung existiert ein eigenes Verzeichnis im Gerätespeicher.

Für jede Anwendung existiert ein eigenes Verzeichnis im Gerätespeicher.

So enthält Bionic eine spezielle Pthread-Implementierung, die die Besonderheiten mobiler Geräte berücksichtigt: Hier müssen nicht Tausende Threads parallel laufen, sondern jeder Thread muss vor allem wenig Speicher verbrauchen und schnell starten. Zudem steht die Android-C-Bibliothek nicht wie die Glibc unter der GNU General Public License, sondern unter der liberalen BSD-Lizenz – Google will (mit Ausnahme des Linux-Kernels) bewusst keine GPL-Software in Android, um Probleme wegen deren Copyleft-Klausel zu vermeiden.

Unter den weiteren Bibliotheken findet man viele alte Bekannte, die sich in der Embedded-Linux-Welt bewährt haben: WebKit als Rendering-Engine für den Browser, die für Embedded Systems optimierte 3D-Grafikbibliothek OpenGL ES, SQLite für Datenbankfunktionen und so weiter. Ebenfalls nicht untypisch für Embedded Systems ist das das Fehlen eines Fenstersystems wie X11.

Bis hierhin handelt es sich bei Android also um ein „normales“ Embedded Linux, das durchaus in die Liste der in [1 [1]] beschriebenen Systeme passen würde. Was Android in den Status einer eigenen Plattform hebt, ist die konsequente Verwendung der Programmiersprache Java. Das gilt sowohl für den Anwendungsrahmen, der die Hardware und die Betriebssystemfunktionen abstrahiert, als auch für die Anwendungen selbst.

Jede Android-Anwendung läuft in einem eigenen Prozess und in einer eigenen virtuellen Maschine. Dies stellt besondere Anforderungen an die VM, die in Bezug auf Speicherverbrauch und CPU-Last hochgradig optimiert sein muss. Durch die Entwicklung einer eigenen VM für Android hat Google zudem ein weiteres Lizenzproblem umgangen: Die Dalvik Virtual Machine (DVM) beruht im Kern auf der quelloffenen Java-VM Apache Harmony. Google-Mitarbeiter Dan Bornstein ist der verantwortliche Entwickler und die DVM nach dem Ort Dalvik in Island benannt, aus dem einige seiner Verwandten kommen.

Die Dalvik Virtual Machine arbeitet mit einem eigenen Bytecode. Android-Programme werden zwar in Java geschrieben und mit dem Compiler des Java-SDK zunächst in Java-Bytecode kompiliert, dann aber von einem Tool namens dx in dex-Bytecode (Dalvik Executable Bytecode) für die DVM übersetzt. Dabei landen sämtliche Klassen in einer einzigen dex-Datei. Durch zahlreiche Optimierungen ist diese Datei recht kompakt und kleiner als die gezippten Class-Dateien.

Zum Erzeugen einer Android-Anwendung kommt während des Build-Prozesses ein weiteres Tool zum Einsatz: Das Android Asset Packaging Tool (aapt) fügt alle Programmbestandteile zu einer Datei mit der Endung .apk zusammen. Neben der dex-Datei mit dem Bytecode gehören Ressourcen wie Bilder, Texte und Sound-Dateien sowie das sogenannte „Android Manifest“ zu einer Android-Anwendung. Eine solche apk-Datei kann man mit dem Tool adb (Android Debug Bridge) direkt auf einem Android-Gerät installieren.

Ist eine Anwendung erst einmal installiert und gestartet, läuft sie in einer Sandbox in einem geschützten Speicherbereich. Daten kann sie im Verzeichnis /data/data des internen Gerätespeichers ablegen. Für jede Anwendung existiert hier ein Verzeichnis mit dem Namen des Package, wie es im Android Manifest angegeben wurde. Dateien landen dort im Ordner files, Datenbanken im Ordner databases – eine explizite Pfadangabe ist nicht nötig. Anwendungseinstellungen werden als XML-Datei im Ordner shared_prefs gespeichert.

Außerdem können Anwendungen Daten in einem anwendungseigenen Bereich auf der SD-Karte ablegen, den andere Anwendungen nicht lesen können, oder in öffentlichen Ordnern für andere Anwendungen zugänglich machen. Allerdings sind auch die in einem anwendungseigenen Bereich auf der SD-Karte gespeicherten Daten nicht besonders sicher: Sie lassen sich leicht auslesen, wenn man direkt auf die SD-Karte zugreift. Daher sollten sicherheitsrelevante Daten auf der SD-Karte immer verschlüsselt werden.

Daten, die auf dem Gerät in /data/data gespeichert werden, sind relativ sicher – solange das Gerät nicht gerootet wird. Daher empfiehlt es sich auch hier, sicherheitsrelevante Daten zu verschlüsseln. Das ist jedoch nicht ganz trivial, da Android einen zentralen Schlüsselspeicher (Keystore) für Zertifikate besitzt, den sich alle Anwendungen teilen. Aus Sicherheitsgründen lässt Android keinen Import von Zertifikaten zu, die nicht von einer Certification Authority wie Verisign verifiziert sind. Da verifizierte Zertifikate Geld kosten, müssen Entwickler einen Trick nutzen, der die Verwendung selbst erstellter Zertifikate ermöglicht [2 [2]].

Android verwendet das Dateisystem YAFFS (Yet Another Flash File System); Android 2.3 wechselt auf das Linux-Standard-Dateisystem Ext4, das bei Schreib- und Leseoperationen deutlich schneller sein soll. Leider werden wohl nicht alle Hardwarehersteller beim Update auf Android 2.3 diese Änderung mitmachen und noch das alte YAFFS-Dateisystem ausliefern. Einige Hardwarehersteller verwenden zudem ein eigenes Dateisystem, Samsung beispielsweise seine FAT-Erweiterung Robust Fat Filesystem (RFS).

Als Datenbank verwendet Android SQLite, ein quelloffenes, kompaktes, für den Einsatz auf mobilen Systemen optimiertes relationales Datenbanksystem. SQLite bietet die meisten Funktionen, die man von größeren Datenbanksystemen gewohnt ist: SQL-Syntax, Transaktionen, Prepared Statements und so weiter. Die Datenbank verbraucht dabei jedoch zur Laufzeit nur sehr wenig Speicher in der Größenordnung 175 bis 250 KByte.

SQLite wird als Bibliothek direkt zu den Anwendungen hinzugelinkt und benötigt daher keinen Datenbankserver: Anwendungen definieren eine Datenbank und können sie sofort verwenden, ohne dass zuvor ein Datenbankserver starten muss. Genau wie bei Dateien können sich mehrere Anwendungen eine Datenbank teilen. Die Datenbank selbst wird in Form einer einzelnen Datei mit der Endung .db im Ordner databases des Anwendungsverzeichnisses abgelegt.

Android legt für jede installierte Anwendung einen eigenen Linux-User an, unter dessen User-ID alle Daten im Gerätespeicher abgelegt werden. Auch kann jede Anwendung eine eigene Datenbankinstanz verwenden. Dadurch und durch die Nutzung einer eigenen Dalvik Virtual Machine in einem eigenen Prozess pro Anwendung läuft jede Android-Anwendung in einer Art Sandbox. Sollen Anwendungen Daten gemeinsam nutzen, stehen drei verschiedene Methoden zur Verfügung. Zunächst können Anwendungen Dateien, Datenbankeinträge und Anwendungseinstellungen so speichern, dass alle anderen Anwendungen auf die Daten lesend oder lesend und schreibend zugreifen dürfen. Sollen nur bestimmte Anwendungen gemeinsam auf bestimmte Daten zugreifen, lässt sich das über eine sharedUserID realisieren: Anwendungen mit gleicher sharedUserID laufen im selben Prozess und mit derselben User-ID und können daher auf alle Daten anderer Anwendungen mit gleicher sharedUserID zugreifen. Anwendungen mit gleicher sharedUserId müssen mit demselben Zertifikat signiert sein. Die sharedUserId wird im Manifest-Tag des Android-Manifests deklariert:

<manifest xmlns:android="http://—
schemas.android.com/apk/res/android"
package="de.visionera"
android:sharedUserId="mySharedUserId">
...
</manifest>

Die dritte Möglichkeit ist die Implementierung eines Content Providers, einer speziellen Android-Klasse, die über einen Uniform Ressource Identifier (URI) bestimmte Daten auf Anfrage zur Verfügung stellt. Dazu gehören nicht nur die im Dateisystem oder der Datenbank gespeicherten Daten, sondern alle der Anwendung zur Verfügung stehenden Daten: Ressourcen, Anwendungseinstellungen, Laufzeitdaten und so weiter. Da der Anwendungsentwickler die Schnittstelle selbst implementiert, kann er sehr detailliert festlegen, welche Daten er zur Verfügung stellt.

Will man Anwendungsdaten aus einem Android-Gerät auslesen, schließt man es einfach per USB an den Computer an. Unter Windows muss man zuvor einen USB-Treiber installieren, unter einigen Linux-Versionen wie Ubuntu eine Udev-Regel anpassen [3 [3]]. Das Android SDK Starter Package [4 [4]] bringt bereits einige Tools zum Zugriff auf Android-Geräte mit. Über den enthaltenen Android SDK and AVD Manager (zu starten über das Skript android im tools-Verzeichnis des SDK) lassen sich noch die Plattform-Tools mit der Android Debug Bridge hinzufügen.

Der Android SDK and AVD Manager installiert die Plattform-Tools.

Der Android SDK and AVD Manager installiert die Plattform-Tools.

Der Dalvik Debug Monitor Server (DDMS) im tools-Verzeichnis ist in erster Linie ein Werkzeug zum Debuggen selbstentwickelter Anwendungen, enthält im Device-Menü jedoch auch einen File Explorer zum Zugriff auf das Dateisystem des Geräts. Über zwei Buttons ist es möglich, Dateien zwischen Android-Gerät und PC auszutauschen.

Über die Android Debug Bridge, nach Installation der Plattform-Tools zu finden im Verzeichnis platform-tools des Android-SDK, kann man eine Shell auf dem Gerät öffnen: Nach Eingabe von

adb shell

arbeitet man mit einer Konsole direkt auf dem Gerät, wo die wichtigsten Linux-Kommandozeilen-Tools zur Verfügung stehen. adb devices zeigt die angeschlossenen Android-Geräte an.

Die Dateien und Datenbanken unterhalb von /data/data/ kann man lediglich bei gerooteten Geräten auslesen, ansonsten greifen die Schutzmechanismen von Android, die verhindern, dass Anwendungen auf Daten anderer Apps zugreifen. Das Lesen und Schreiben von Daten auf der SD-Karte ist immer möglich. Dateien auf dem Gerät kann man mit adb pull auf den PC kopieren; der Befehl adb push überträgt eine Datei vom PC.

Installierte Anwendungen liegen im Ordner /data/app; kostenpflichtige Apps und geschützte Gratis-Apps, bei denen der Entwickler beim Einstellen in den Market die Option „Copy Protection“ ausgewählt hat, sind im Ordner /data/app-private abgelegt. Lediglich Besitzer eines gerooteten Android-Geräts haben vollen Zugriff auf diese Verzeichnisse. Apps sind Dateien mit der Endung .apk, die man einfach per adb pull herunterladen kann. Bis Juli 2010 gab es kein digitales Rechtemanagement, sodass man mit root-Rechten die geschützten Apps einfach aus dem Verzeichnis app-private auslesen, per adb push auf die SD-Karte eines beliebigen Geräts kopieren und von dort installieren konnte. Eine Installation von auf einer Website abgelegten Apps über HTTP war ebenfalls möglich. Nach der Installation, egal ob bezahlte App oder nicht, befand sich die Anwendung im Ordner /data/app.

Mittlerweile stellt Google eine License Verification Library (LVL) zur Verfügung, die Entwickler in ihre Anwendung einbinden können [5 [5]]. Apps, die diese Bibliothek nutzen, fragen bei der Installation im Android Market nach, ob der Besitzer des Android-Geräts die App zuvor auch gekauft hat.

Schaltet man ein Android-Gerät ein, startet nach der Initialisierung der Hardware der Prozess init im Root-Verzeichnis des Geräts. Er initialisiert zunächst das Log-System und liest dann die Dateien /init.rc und /init.Gerätename.rc ein – „Gerätename“ steht für ein herstellerspezifisches Kürzel. Es handelt sich um Shell-Skripte, die eine Vielzahl von Systemeinstellungen vornehmen und einige Prozesse starten. Auf dem Android-Emulator des Android-SDK startet die Datei init.goldfish.rc den Emulator Qemu, der nötig ist, um den für die ARM-Architektur kompilierten Linux-Kernel und seine Bibliotheken auf einem x86-Prozessor laufen zu lassen.

Der System Server startet die wichtigen Android-Manager-Klassen in eigenen Threads.

Der System Server startet die wichtigen Android-Manager-Klassen in eigenen Threads.

Einer der von init.rc gestarteten Prozesse ist das in C++ geschriebene Zygote-Programm (/system/bin/app_process). Zygote startet alle Android-spezifischen Prozesse und Threads, darunter AndroidRuntime, eine C++-Klasse zum Starten der Dalvik-Laufzeitumgebung. Danach findet ein grundlegender Wechsel statt: Den Rest des Initialisierungsprozesses übernehmen in Java geschriebene Android-Programme. Den Anfang macht der „System Server“-Prozess, dessen Prozessname in DDMS system_process lautet.

Ein Blick in den DDMS bei laufendem Android-Emulator (oder per USB angeschlossenem gerooteten Android-Smartphone) zeigt, dass dieser Prozess alle wichtigen Android-Manager-Klassen als seine Threads startet. Dazu wählt man in DDMS den Prozess system_process aus und klickt auf den Button „Update Threads“. Intern verwaltet werden alle diese Threads über den ServiceManager, der die darüber implementierten Services den anderen Komponenten des Anwendungsrahmens zur Verfügung stellt.

Ist ein Android-Gerät erst einmal hochgefahren, beginnt der Kampf um die Systemressourcen. Da Android ohne Swap Space auskommt, muss das System reagieren, wenn der Speicher knapp wird. Um einen Absturz des Geräts wegen Speichermangel zu verhindern, nutzt Android zwei Verfahren: Komponenten- und Prozess-Management.

Der Lebenszyklus einer Activity gibt dem Programmierer Gelegenheit, auf Ereignisse wie das Beenden und Neustarten der App zu reagieren.

Der Lebenszyklus einer Activity gibt dem Programmierer Gelegenheit, auf Ereignisse wie das Beenden und Neustarten der App zu reagieren.

Android kennt vier Komponenten als Grundbausteine, aus denen sich eine Anwendung zusammensetzt und die als eigene Java-Klassen implementiert sind: Activity, Service, Content Provider und Broadcast Receiver. Eine Activity entspricht normalerweise einer Bildschirmseite mit Oberfläche, Menü, Navigation und Programmlogik. Ein Service hingegen ist eine Klasse, die komplexe Hintergrundoperationen erledigt.

Content Provider sind Schnittstellen für Daten und Ressourcen, die ausschließlich von anderen Anwendungen aufgerufen werden und nicht nach innen wirken. Broadcast Receiver schließlich registrieren sich bei der Installation der App im System und lauschen auf bestimmte Systemnachrichten wie „Akku fast leer“ oder „SMS empfangen“. Wenn solch ein Ereignis eintritt, startet der Broadcast Receiver unabhängig davon, ob die Anwendung läuft oder nicht – der Rest der App bleibt unberührt.

Komponenten kann man als in sich abgeschlossene Programmbestandteile sehen, die durch Einflüsse innerhalb oder außerhalb des Programms gestartet und oft auch beendet werden. Eine App kann ihre Activities selbst verwenden, aber auch anderen Anwendungen zur Verfügung stellen: Eine App, die die Auswahl eines Kontakts ermöglichen oder eine Webseite anzeigen möchte, kann dazu einfach Activities der Kontakte- und Browser-Anwendung nutzen und muss die Funktionen nicht selbst implementieren. Nach der Installation einer Anwendung ist es oft gar nicht mehr so entscheidend, zu welcher Anwendung eine Komponente gehört: Wenn eine App in AndroidManifest.xml über entsprechende Intent-Filter Schnittstellen freigibt, können andere Anwendungen die Activities und Services der App verwenden.

Da Teile einer Anwendung immer wieder gestartet und beendet werden können, ist es nicht zweckmäßig, dabei jedes Mal den ganzen zugehörigen Prozess und die Dalvik Virtual Machine zu starten und zu beenden. Die Kontakte-Anwendung etwa wird wahrscheinlich mehrmals am Tag vom Anwender aufgerufen, zudem nutzen andere Apps immer wieder einige ihrer Activities. Um zu verhindern, dass bei jedem Zugriff auf eine Komponente einer Anwendung deren Prozess und eine Dalvik Virtual Machine starten muss, beendet Android den Prozess und die DVM nicht, wenn die Activity nicht mehr benötigt wird. Er steht daher beim nächsten Zugriff zur Weiterverwendung bereit.

Android besitzt ein komplexes Regelwerk, um festzustellen, in welchen Prozessen nichts Wichtiges oder gar nichts mehr läuft. Bei knappen Systemressourcen beendet das System leere Prozesse, in denen keine Komponenten mehr laufen, oder lange nicht mehr benötigte Prozesse, wodurch Speicher frei wird. Da sich der Heap einer DVM niemals verkleinert, belegen auch leere Prozesse mitunter viel Speicher. Aktuell kann der Heap eines Android-Smartphones 16 oder 24 MByte groß werden; diese Grenze legt der Hardware-Hersteller beim Kompilieren des Android-Systems für alle Anwendungen einheitlich fest. Für Geräte mit großen Bildschirmen kann der Hersteller bis zu 48 MByte maximalen Speicher pro App vorgeben, für Android 3.0 sind 96 MByte als Obergrenze für Tablets im Gespräch.

Multimediadaten (Sounds, Bilder, Videos) legt Android nicht im Speicher der Dalvik Virtual Machine ab, sondern im Shared Memory – nur ein Objekt als Referenz auf die Rohdaten liegt im Heap der DVM. Der Platz, den die Daten im Shared Memory belegen, wird aber trotzdem der DVM zugerechnet und unterliegt damit dem Limit von derzeit 16 oder 24 MByte [6 [6]]. Allerdings steht beim Beenden einer Komponente das von ihr belegte Shared Memory sofort für andere Apps zur Verfügung, während sich der Heap einer DVM nicht verkleinert. Bei Speichermangel ist es daher effektiver, Komponenten zu beenden, die viel Shared Memory belegen.

Wurde eine Activity längere Zeit nicht mehr angezeigt, kann das System sie automatisch beenden. Nimmt man also einen Anruf an, während man gerade eine E-Mail schreibt, beendet das System zwischenzeitlich womöglich die E-Mail-Activity, um Speicher freizugeben. Bei Activities gibt es dabei einen Automatismus, der die Eingabedaten aus Formularfeldern ausliest und persistent zwischenspeichert, wenn eine andere Activity aufgerufen wird. Kehrt der Anwender später zu dieser Activity zurück, werden die Daten wieder hergestellt: Der Anwender merkt gar nicht, ob die Activity zwischenzeitlich beendet wurde.

Leider gilt dies nur für Eingabefelder und nicht für Auswahlelemente wie Drop-down-Boxen (in Android: Spinner) oder Selektoren für Datum oder Uhrzeit: Deren Zustände gehen verloren, wenn der Programmierer nicht selbst für die Speicherung sorgt. Sofern es eine App nicht explizit verhindert, beendet Android auch beim Drehen des Bildschirms von Hoch- auf Querformat und zurück alle Activities. Gehen dabei Zustände von Auswahlelementen wie das eingestellte Datums verloren, ist das für den Anwender sehr ärgerlich, da er dann möglicherweise einen Termin mit dem falschen Datum speichert.

Solche unschönen Effekte soll der Lebenszyklus der Activity verhindern. Realisiert ist das über spezielle Methoden einer Komponente, die Android aufruft, wenn eine Activity den Zustand ändert, sodass die App reagieren und beispielsweise Formulardaten und Zustände auslesen oder die Komponente (neu) initialisieren kann. Die Methode onCreate ist der Programmeintrittspunkt, onDestroy wird aufgerufen, wenn die Activity beendet wird. Die Methoden dazwischen werden bei bestimmten Zuständen während des Aufbaus und Abbaus einer Activity aufgerufen.

Bei Android füllt eine Activity normalerweise den gesamten Bildschirm. Eine Ausnahme bilden Dialoge, die allerdings fest mit der Activity verbunden sind, die sie gestartet hat. Fenster wie bei Desktop-Betriebssystemen gibt es nicht. Der Wechsel zwischen Anwendungen erfolgt über drei Mechanismen, die durch zwei Knöpfe am Gerät realisiert werden. Der Zurück-Knopf hat die Funktion einer Abbrechen-Taste und ersetzt die aktuelle Bildschirmseite durch die zuvor angezeigte. Das Standardverhalten einer App ist, dass dabei die eingegebenen Daten verloren gehen; Entwickler können dieses Standardverhalten aber überschreiben und beispielsweise dafür sorgen, dass der bisher eingegebene Text einer E-Mail in einem Entwurfsordner landet.

Langes Drücken der Home-Taste erlaubt den schnellen Wechsel zwischen laufenden Apps.

Langes Drücken der Home-Taste erlaubt den schnellen Wechsel zwischen laufenden Apps.

Kurzes Drücken des Home-Knopfs bringt den Anwender zum Home-Screen, wo er eine neue App starten kann; langes Drücken öffnet einen Dialog, der alle kürzlich aktiven Anwendungen anzeigt und es so erlaubt, direkt auf die Bildschirmseite einer zuvor geöffneten App zu wechseln. Wobei es natürlich sein kann, dass Android die für diese Bildschirmseite verantwortliche Activity oder sogar die gesamte Anwendung samt DVM zwischenzeitlich beendet hat – was der Anwender aber gar nicht merkt, wenn der Entwickler der App die nötigen Vorkehrungen getroffen hat, um den ursprünglichen Zustand der Activity exakt wieder herzustellen.

Android verlässt sich voll auf sein Ressourcen-Management. Entwicklern stehen alle Möglichkeiten der Programmierung offen, egal wie viele Systemressourcen – Speicher, Akku, CPU – die App verbraucht. Das unterscheidet Android zum Beispiel wesentlich von Apples iOS, erfordert aber mehr Verantwortungsbewusstsein bei den Programmierern.

Leider gehen viele Entwickler nicht ausreichend sorgsam mit den Ressourcen um. Ein deutlicher Beleg dafür sind die Task Manager, die viele Anwender installiert haben und die sie gelegentlich benötigen, um einen ressourcenfressenden Prozess zu beenden. Auf einem Android-Gerät einen solchen Task Manager zu installieren ist ungefähr so, als würde man ein Auto mit einem Anker zum Bremsen ausstatten. Klemmt aber das Gaspedal und ist womöglich noch die Bremse kaputt, greift man notgedrungen auf kuriose Lösungen zurück. Würde jeder Entwickler gute, sprich ressourcenschonende Apps schreiben, bräuchte man keinen Task Manager – zumal Android auch selbst ganze Prozesse beendet, wenn die Ressourcen knapp werden.

Android nutzt geschickt die Vorteile des etablierten und sicheren Betriebssystems Linux. Dies gilt insbesondere für die Rechteverwaltung im Dateisystem: Daten lassen sich recht sicher auf einem Android-Gerät speichern. Einige tiefgreifende Veränderungen am Linux-Kernel sorgen dafür, dass Android auch auf Geräten mit wenig Speicher und einer langsamen CPU läuft. Die Verwendung der Programmiersprache Java über eine eigene virtuelle Maschine öffnet vielen Programmierern einen schnellen Zugang zur Entwicklung von Android-Apps. Dennoch darf man sich nicht täuschen lassen: Mobile Programmierung ist sehr kompliziert, will man guten Code schreiben. Sie erfordert ein tiefes Verständnis des Systemverhaltens.

  1. Gernot Hillier, Christoph Stückjürgen, Linux inside, Wie Linux auf Embedded Devices kommt, c’t 19/10, S. 164
  2. Arno Becker, Marcus Pant, Android 2 – Grundlagen und Programmierung, Mai 2010, dpunkt-Verlag
  3. USB-Treiber installieren (Windows) und Udev anpassen (Linux): developer.android.com/guide/developing/device.html [8]
  4. Android-SDK: developer.android.com/sdk/ [9]
  5. License Verification Library: developer.android.com/guide/publishing/licensing.html [10]
  6. Markus Junginger, Speichern will gelernt sein, Mobile Developer Android 4/10, Neue Mediengesellschaft Ulm mbH

(odi [11])


URL dieses Artikels:
https://www.heise.de/-1901647

Links in diesem Artikel:
[1] ?anchor=literatur
[2] ?anchor=literatur
[3] ?anchor=literatur
[4] ?anchor=literatur
[5] ?anchor=literatur
[6] ?anchor=literatur
[7] 
[8] http://developer.android.com/guide/developing/device.html
[9] http://developer.android.com/sdk/
[10] http://developer.android.com/guide/publishing/licensing.html
[11] mailto:odi@ix.de