Fragmentierung auf der Android-Plattform

Andreas Hölzl und Andrei Socaciu

Der Erfolg der Android-Plattform ist maßgeblich auf ihre Flexibilität zurückzuführen. Obwohl Android noch relativ jung ist, wird es mittlerweile von einem Heer an Geräten als Betriebssystem verwendet. Und nahezu wöchentlich werden es mehr. Allein bei den Smartphones zählt man schon mehr als 300 Modelle. Dazu kommen weitere Geräteklassen wie Tablets, E-Reader, Netbooks und seit Kurzem mit Google-TV auch Fernseher. Der Entwicker einer Android-App steht damit vor einer schier unlösbaren Aufgabe, will er auf all diesen Geräten eine professionelle Implementierung gewährleisten – denkt man zunächst. Vom Schreckgespenst der Plattformfragmentierung ist allerorts die Rede.

Android360

Der Artikel „Fragmentierung auf der Android-Plattform“ von Andreas Hölzl und Andrei Socaciu ist erstmalig erschienen im Android360-Magazin 4.2011.

http://android360.de/

Doch die Väter der Plattform haben auch daran gedacht und entsprechende Gegenmittel bereitgestellt. Beachtet man die wesentlichen Grundkonzepte und hält sich an die Empfehlungen der offiziellen Dokumentation, steht einer erfolgreichen Cross-Device-Entwicklung nichts im Wege. Dieser Artikel soll eine Einführung in diese Konzepte liefern.

Was ist Android konkret?

Betrachtet man die Hardware, so bietet sich einem folgendes Bild: Die Plattform definiert 11 Typen von Sensoren (Beschleunigungs-, Temperatur-, Orientierungs- und andere Sensoren), 4 Bildschirmgrößen-Klassen (S, M, L, XL) und 4 Typen von Touchscreens (single-, multi-, jazzhand- und stylustouch). Dazu kann jedes Device keine, eine oder zwei Kameras, eine physische Tastatur, ein DPad oder sogar spezielle Game Controls haben.

Softwareseitig hat man es mit einem Blumenstrauß an Plattformversionen zu tun. Seit der ersten Version 1.5 wurde die Plattform konsequent weiterentwickelt. In regelmäßigen Abständen erscheinen neue SDK-Versionen, die jeweils spannende neue Möglichkeiten bieten. Bis diese Versionen jedoch beim Endverbraucher ankommen, braucht es seine Zeit. Die Konsequenz davon ist, dass jederzeit eine Vielzahl von Versionen im Umlauf ist. Aktuell sind die Versionen 2.1, 2.2 und 2.3 am verbreitetsten. Diese SDKs sind auf mehr als 90 % der Geräte installiert (Stand: Ende 2011) (Abb. 1).

Ein wesentlicher Grund für die Verzögerungen bei der Auslieferung neuer Versionen ist, dass die meisten Hardwarehersteller eigene Weiterentwicklungen der Plattform verwenden. HTC benutzt das Sense-UI, Motorola hat sein Motoblur. Und diese müssen stets an die jeweils neuesten Versionen angepasst werden.

Abb. 1: Verteilung der Android-Versionen (Stand: Ende 2011)
Softwarefragmentierung

Da man sich bei der Applikationsentwicklung nicht gleichzeitig auf alle Versionen konzentrieren kann, wählt man zunächst eine Zielversion. Diese definiert man im App-Manifest mit dem Attribut android:targetSdkVersion. Um eine gewisse sinnvolle Rückwärtskompatibilität zu gewährleisten, definiert man mit android:minSdkVersion eine Mindestversion.

Die Zielversion ist diejenige, auf der die Applikation optimal läuft – diese sollte in der Regel immer die aktuellste sein. Die minimale Version ist die älteste Version, auf der die Anwendung noch ordentlich benutzt werden kann. Auf Geräten mit älteren Versionen als der Mindestversion kann die App gar nicht installiert werden. Die Zielversion wird auch in der Entwicklungsumgebung (z. B. Eclipse) als SDK-Bibliothek eingebunden. Beim Entwickeln muss man auf die verwendete API-Funktionalität achten, um bis zur minimalen Version kompatibel zu bleiben. Die notwendige Information liefert hier die API-Dokumentation. Für jede Klasse und jede Methode ist festgehalten, ab welchem API-Level diese verfügbar ist. Die Online-API-Referenz verfügt sinnvollerweise auch über einen Versionsfilter, mit der nicht unterstützte API-Bestandteile ausgeblendet und damit leicht identifiziert werden können.

Was also tun mit Funktionalität, die man in der Zielversion verwenden möchte, die aber in den älteren unterstützten Versionen nicht vorhanden ist? In der Entwicklungsumgebung wird man keine Fehler sehen, da sie auf der Zielversion arbeitet. Beim Ausführen auf einer älteren Plattform wird die Applikation jedoch abstürzen …

Nicht existente Methoden

Um Methoden aus einer neueren API-Version rückwärtskompatibel zu verwenden, stehen der Entwicklerin zwei Ansätze zur Verfügung. Der erste ist programmatisch die Plattformversion (Build.VERSION.SDK_INT) zu überprüfen. Damit kann der Entwickler Verzweigungen bereitstellen, falls die neueren Funktionen nicht vorhanden sind – beispielsweise alternative Methoden verwenden oder die Teilfunktion deaktivieren. Der zweite Ansatz geht über die klassische Java Reflection.

Ein Beispiel: In einer Kameraanwendung soll optional eine Zoomfunktionalität angeboten werden. Um das Vorhandensein der Zoomunterstützung zu überprüfen, steht uns folgender Methodenaufruf zur Verfügung:

camera.getParameters().isZoomSupported()

Allerdings ist die Methode erst ab Version 2.2 (API-Level 8) definiert. Der Aufruf wird uns deshalb auf älteren Versionen zur Laufzeit mit einem VerifyError um die Ohren fliegen. Mit Reflection sollte man den Aufruf somit wie folgt absichern:

fZoomSupported = false;
try {
  Method isZoomSupportedMethod = Camera.class.getMethod("isZoomSupported");       fZoomSupported = (Boolean) isZoomSupportedMethod.invoke(camera);
} catch (NoSuchMethodException e) {     }

Das heißt: Ist die Methode vorhanden, wird sie aufgerufen. Ist sie es nicht, wird auch keine Zoomfunktion unterstützt.

Geschrieben von
Andreas Hölzl und Andrei Socaciu
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.