Techtalk: Crosscompile Android Apps to iPhone
cs, den 7. Dezember 2009Am 03.12.2009 fand ein Techtalk im Developergarden der Deutschen Telekom in Darmstadt statt. Thema war „Cross-Compilation Android Applications to the iPhone„. Arno Puder, Professor an der San Francisco State University, erläuterte das Vorgehen des XMLVM getauften Projektes. Die Idee dahinter ist, dass man für iPhone und Android-Phones Apps gleichzeitig entwickeln kann.
Grundlage der App-Entwicklung mit XMLVM ist Java. Das wurde so gewählt, weil es nach Ansicht von Arno Puder mehr Java-Entwickler als Objective-C-Entwickler gibt. Man erreicht eine ungleich größere Benutzerbasis. Um eine iPhone-App mit Java entwickeln zu können, setzt das XMLVM-Team auf eine selbst entwickelte Java-API für Cocoa Touch. Diese ist lose an der Objective-C-API angelehnt.
Die berühmte „Hello World“-Applikation für das iPhone sieht in Java folgendermaßen aus:
import org.xmlvm.iphone.*; public class HelloWorld extends UIApplication { public void applicationDidFinishLaunching(UIApplication app) { UIScreen screen = UIScreen.mainScreen(); CGRect rect = screen.applicationFrame(); UIWindow window = new UIWindow(rect); rect.origin.x = rect.origin.y = 0; UIView mainView = new UIView(rect); window.addSubview(mainView); UILabel title = new UILabel(rect); title.setText("Hello World!"); title.setTextAlignment(UITextAlignment.UITextAlignmentCenter); mainView.addSubview(title); window.makeKeyAndVisible(); } public static void main(String[] args) { UIApplication.main(args, HelloWorld.class); } }
Um die Applikationen besser testen zu können hat das Team um Arno Puder einen auf Java basierenden iPhone-Simulator geschrieben. Ebenfalls wurden die UI-Komponenten im Aussehen an die iPhone nativen Komponenten angelehnt. Das Ergebnis ist der Look and Feel wie auf einem „echten“ iPhone. Somit kann die Anwendung kann bereits ohne Cross-Kompilierung getestet werden.
Was nun folgt, ist eine kurze Erläuterung der Cross-Kompilierung für das iPhone. Hierbei setzt XMLVM nicht auf den Sourcecode (Java), sondern auf den erzeugten Java-Bytecode (.class-Dateien). Der Bytecode wird in XML übersetzt. Das XML wird im Anschluss mittels XSLT-Stylesheets in die gewünschte Zielsprache transformiert. In diesem Fall Objective-C. Weitere Zielplattform ist derzeit der Palm Pre, also Javascript.
Um das Ganze anschaulicher zu machen, hier ein Beispiel, wie ein einfaches in Java implementiertes „Hello World“ in XML repräsentiert wird:
public class HelloWorld { static public void main(String[] args) { System.out.println("Hello World"); } }
wird zu
<vm:xmlvm xmlns:vm="http://xmlvm.org" xmlns:jvm="http://xmlvm.org/jvm"> <vm:class name="HelloWorld" extends="java.lang.Object"> <vm:method name="main" isPublic="true" isStatic="true" stack="2" locals="1"> <vm:signature> <vm:return type="void" /> <vm:parameter type="java.lang.String[]" /> </vm:signature> <vm:code> <jvm:var name="args" id="0" type="java.lang.String[]" /> <jvm:getstatic class-type="java.lang.System" type="java.io.PrintStream" field="out" /> <jvm:ldc type="java.lang.String" value="Hello World" /> <jvm:invokevirtual class-type="java.io.PrintStream" method="println"> <vm:signature> <vm:return type="void" /> <vm:parameter type="java.lang.String" /> </vm:signature> </jvm:invokevirtual> <jvm:return /> </vm:code> </vm:method> </vm:class> </vm:xmlvm>
Das erzeugte XML kann jetzt transformiert werden. Das XSLT-Template für die Addition zweier Integerwerte sieht zum Beispiel folgendermaßen aus:
<xsl:template match="jvm:irem"> <xsl:text> _op2.i = _stack[--_sp].i; // Pop operand 1 _op1.i = _stack[--_sp].i; // Pop operand 2 _stack[_sp++].i = _op1.i % _op2.i; // Push remainder </xsl:text> </xsl:template>
Da Java stackbasiert ist, Objective-C hingegen nicht, wird ein Stack von XMLVM in Objective-C simuliert. Der gesamte durch Transformation erzeugte Objective-C-Code der „Hello World“-Anwendung sieht folgendermaßen aus:
@interface org_xmlvm_test_HelloWorld : java_lang_Object + (void) main___java_lang_String_ARRAYTYPE :(NSMutableArray*)n1; @end @implementation org_xmlvm_test_HelloWorld; + (void) main___java_lang_String_ARRAYTYPE :(NSMutableArray*)n1 { XMLVMElem _stack[2]; XMLVMElem _locals[1]; int _sp = 0; XMLVMElem _op1, _op2, _op3; int _i; for (_i = 0; _i
Zusätzlich erzeugt der Cross-Compiler noch eine XCode-Projekt-Datei. Jetzt kann die iPhone-Anwendung mittels XCode kompiliert und gestartet werden. Laut Arno Puder ist es möglich die iPhone-App unter Windows oder Linux zu kompilieren. Es müssen jedoch per Hand einige Header-Dateien des iPhone-SDK kopiert und bereitgestellt werden. Als Compiler dient der frei verfügbare GNU Objective-C-Compiler. Ein Test auf dem Endgerät ist natürlich weiterhin nur mit einem Mac möglich, da nur auf diesem eine Signierung der App vollzogen werden kann.
Bis hier wurde nur gezeigt, wie eine in Java geschriebene iPhone-App cross-kompiliert werden kann. Titel der Veranstaltung war Cross Compile Android Applications for iPhone. Um die Cross-Kompilierung einer Android-App zu ermöglichen, setzt das XMLVM-Team die Benutzung ihrer Android Compatibility Library voraus. Diese Bibliothek bietet im Prinzip die gleiche API wie die Android-API, benutzt jedoch zusätzlich die erwähnte Java-basierte API für Cocoa Touch. Das XMLVM-Team hat diese ebenfalls entwickelt und bereitgestellt. Sie ist lose an der Objective-C-API angelehnt. Hierzu ein Auszug aus der Library:
package android.widget; public class Button extends View { protected UIButton button; // ... public void setOnClickListener(OnClickListener listener) { final OnClickListener theListener = listener; button.addTarget(new UIControlDelegate() { @Override public void raiseEvent() { theListener.onClick(Button.this); } }, UIControl.UIControlEventTouchUpInside); } }
Wird diese Library für die Android-Applikation verwendet, so steht dem Kompilieren für das iPhone nicht mehr viel im Wege.
Doch wo viel Licht ist, ist auch Schatten. So auch bei XMLVM. Zwar ist es bereits möglich einfache Spiele zu Entwickeln und für verschiedene Plattformen zu kompilieren, jedoch stößt man sehr schnell an die Grenzen, wenn es um die Unterstützung der nativen UI-Elemente des iPhone geht. Das ist darin begründet, dass noch nicht alle UI-Elemente ihre Repräsentation in der Java-API von XMLVM haben. Bisher sind einfache tabellenbasierte Anwendungen bereits möglich, komplexere Unserinterfaces jedoch noch nicht. Daran arbeitet das Team um Arno Puder derzeit. Da dieses Projekt jedoch Open Source ist, kann jeder interessierte Entwickler seinen Teil dazu beitragen.
Ein weiterer noch nicht geklärter Punkt ist die Akzeptanz seitens Apple im Reviewprozess für den App Store. Rein formal spricht derzeit nichts für eine Ablehnung einer mittels XMLVM erstellten App, jedoch ist der Reviewprozess nicht transparent genug um sicher zu gehen.
Nicht zu vergessen ist das Debugging. Dies kann derzeit nur auf Java-Seite erfolgen, denn der erzeugte Objective-C-Code ist alles andere als wartbar. Wird ein Fehler gefunden, der nur im Objective-C-Code auftritt, so muss davon ausgegangen werden, dass XMLVM einen Fehler macht. Die Behebung ist damit nicht trivial möglich und man ist abhängig von einem Bugfixing seitens XMLVM.
Das Projekt ist jedenfalls einen Blick wert und sollte beobachtet werden. Hier steckt viel Potential. Gerade für Firmen, die Anwendungen plattformübergreifend entwickeln möchten, ist XMLVM sehr interessant, denn es muss nicht zwischen den beiden Plattformen aufwendig portiert werden. Einige weitere Beispiele sind auf der Webseite von XMLVM zu finden. XMLVM muss noch einiges mehr an UI-Elementen unterstützen, um damit sinnvolle Anwendungen zu schreiben. doch der Weg ist bereits der Richtige.