Mittwoch, 16. September 2009

Wo ist denn nur mein Android Launcher?

Nachdem ich mich heute mal wieder über die 3-Screens Limitierung des aktuellen Android Launchers (Startseite) geärgert habe, ist es mir nach einigen Experimenten mit diversen alternativen Launchern gelungen, dass mein originaler Launcher überhaupt nicht mehr gestartet ist.

Die Ursache war, dass ich aus reiner Neugierde ein Launcher Replacement (ersetzt den originalen Android Launcher) ausprobiert habe und bei dem stand ungefähr die folgende Anleitung:

Installation (im Recovery Mode):
1) Anlegen einer Kopie von /system/app/Launcher.apk
2) Installation des neuen Launcher.apk
3) Löschen von /system/app/Launcher.odex

Deinstallation:
1) Zuvor erstellte Kopie von Launcher.apk nach /system/app/Launcher.apk kopieren

OK, klang irgendwie logisch und ich dachte mir, die Launcher.odex wird dynamisch erzeugt, weil ja die anderen Anwendungen auch immer nur als apk-Paket ausgeliefert werden.

Leider blieb das Handy dann aber nach der Deinstallation beim Android Schriftzug hängen und mein erster Gedanke dazu war: Verdammt, jetzt kann ich das Handy nochmals komplett flashen und muss wieder alles neu konfigurieren.

Die Ursache des Problems war mit einem adb logcat jedoch rasch gefunden, das Android beschwerte sich wie folgt über die fehlende Datei Launcher.odex:

I/PackageManager( 1058): /system/app/Launcher.apk changed; unpacking
I/dalvikvm( 1058): Zip is good, but no classes.dex inside, and no .odex file in the same directory
W/PackageManager( 1058): Exception reading apk: /system/app/Launcher.apk
W/PackageManager( 1058): java.io.IOException: /system/app/Launcher.apk
W/PackageManager( 1058): at dalvik.system.DexFile.isDexOptNeeded(Native Method)
W/PackageManager( 1058): at com.android.server.PackageManagerService.scanPackageLI(PackageManagerService.java:2138)
W/PackageManager( 1058): at com.android.server.PackageManagerService.scanPackageLI(PackageManagerService.java:1793)
W/PackageManager( 1058): at com.android.server.PackageManagerService.scanDirLI(PackageManagerService.java:1705)
W/PackageManager( 1058): at com.android.server.PackageManagerService.(PackageManagerService.java:460)
W/PackageManager( 1058): at com.android.server.PackageManagerService.main(PackageManagerService.java:261)
W/PackageManager( 1058): at com.android.server.ServerThread.run(SystemServer.java:113)

Super, die Launcher.odex habe ich aber ein paar Minuten vorher gelöscht und hatte kein Backup.

Was ist nun diese odex-Datei überhaupt? Auf http://groups.google.com/group/android-framework/browse_thread/thread/70ee61a240edc84a steht die folgende Erklärung:
The production builds pre-generate the .odex files from the source apk/jar files, and then remove the "classes.dex" from the source. This uses a bit more space on /system (because the DEX data isn't compressed) but saves space on /data (because we don't need to hold the odex data in /data/dalvik-cache).
Auf Deutsch heisst dass nun, wenn eine .odex Datei existiert, dann ist in dem Zuge der Erstellung dieser Datei das "classes.dex" aus dem apk-Paket entfernt worden, dh. man braucht beide Dateien, damit die Applikation lauffähig ist. Wenn das classes.dex noch im apk-Paket enthalten ist, dann werden normalerweise die odex-Daten in /data/dalvik-cache abgelegt. Die heissen dann zB. /data/dalvik-cache/system@app@YouTube.apk@classes.dex für die Applikation in /system/app/YouTupe.apk.

Wie komme ich aber nun wieder zu dieser Launcher.odex, die zu meiner Launcher.apk passt?

Glücklicherweise habe ich ja erst vor ein paar Tagen mein Galaxy auf das neue H8 Image von Samsung geflasht und hatte daher noch das entsprechende Update-File am Rechner. Das File gibt's zum Beispiel auch auf http://www.android-hilfe.de/root-hacking-modding-fuer-samsung-galaxy/6010-fuer-profis-updates-und-customroms-fuer-galaxy-mit-odin-mulit-downloader-einspielen.html).
In dem ZIP-File für das Update ist ein Tar-File "I7500XXIH8-PDA-CL53973-REV5(VIA).tar" mit folgendem Inhalt enthalten:
  • amss
  • cache.img
  • kernel
  • recovery
  • system
Das gesuchte Launcher.odex ist ja in der system-Partition und daher vermutlich in der Datei "system". Mit dem Tool unyaffs von http://code.google.com/p/unyaffs/ lassen sich nun unter Linux ganz einfach alle Files aus dem system-Image extrahieren. Danach einfach die Launcher.odex wieder auf das Handy nach /system/app kopieren, rebooten und alles läuft wieder wie vorher.

Nachem ich jetzt weiss wo ich die originalen Files wieder herbekomme steht nun weiteren root-Experimenten nichts mehr im Wege ;-)

5 Kommentare:

  1. Hallo Heiko.

    Hast du schon Erfahrungen, wie man ein .odex selber erzeugt? Ich bin gerade dabei das Framework (framework.jar) umzuschreiben und benötige daher ein eigenes framework.odex File. Wäre klasse, wenn ich das Rad nicht neu erfinden müsste.

    Grüße,
    Patrick
    AntwortenLöschen
  2. Hallo Patrick,

    schau mal im Android GIT Repository nach, dort gibt's eine Seite wo dokumentiert ist, wie man die odex Files erzeugt:

    http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/dexopt.html;hb=HEAD
    AntwortenLöschen
  3. Und auf http://android.git.kernel.org/?p=platform/build.git;a=tree;f=tools/dexpreopt;hb=HEAD gibt's dann das passende Tool dazu (dexpreopt).
    AntwortenLöschen
  4. Danke.

    Hast du das selbst schon ausprobiert? Ich dachte (entsprechend dexopt.html) man solle das dexopt Tool verwenden. Scheinbar ist das aber veraltet bzw. wird von dexpreopt verwendet. Ich habe die Benutzung noch nicht ganz verstanden aber werde noch ein wenig damit herumprobieren.

    Patrick
    AntwortenLöschen
  5. Hatte exakt dasselbe Problem wie du ... finde es allerdings schon etwas "unverantwortlich", dass in der AdvancedLauncher-Anleitung nix von einem Backup steht .. da geht man halt davon aus, dass die Datei völlig nutzlos ist.
    AntwortenLöschen