2010-06-11 6 views
30

Ich frage mich, ob und wie ein dex oder Klassendateien dynamisch in Dalvik laden kann ich einige quick'n'dirty Testfunktion geschrieben war:Wie lade ich eine Java-Klasse dynamisch auf Android/Dalvik?

public void testLoader() { 
      InputStream in; 
      int len; 
      byte[] data = new byte[2048]; 
      try { 
        in = context.getAssets().open("f.dex"); 
        len = in.read(data); 
        in.close(); 
        DexFile d; 
        Class c = defineClass("net.webvm.FooImpl", data, 0, len); 
        Foo foo = (Foo)c.newInstance(); 
      } catch (IOException e1) { 
        // TODO Auto-generated catch block 
        e1.printStackTrace(); 
      } catch (IllegalAccessException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
      } catch (InstantiationException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
      } 
    } 

während die Foo-Schnittstelle diese

ist
public interface Foo { 
      int get42(); 
    } 

und f.dex enthält einige dx'ed Implementierung dieser Schnittstelle:

public class FooImpl implements Foo { 
      public int get42() { 
        return 42; 
      } 
    } 

der obige Test Treiber führt bei defineCl ass() und es nicht Arbeit und ich den Dalvik-Code untersucht und fanden diese:

http://www.google.com/codesearch/p?hl=en#atE6BTe41-M/vm/Jni.c&q=Jni.c ...

Also ich frage mich, ob jemand kann mich aufklären, wenn dies in eine andere möglich ist Art und Weise oder nicht möglich sein sollte. Wenn es nicht möglich ist, kann jemand Gründe angeben, warum dies nicht möglich ist?

+1

Sie haben 'DexFile d', dann nie zuweisen oder verwenden. AFAIK, 'DexClassLoader' ist der richtige Ansatz, obwohl ich ihn nicht persönlich benutzt habe. – CommonsWare

+0

Das stimmt, die DexFile ist ein Rest eines anderen schmutzigen Hacks, den ich ausprobiert habe, ich werde jetzt in DexClassLoader schauen. – anselm

+0

Ich habe versucht mit DexClassLoader, aber das funktioniert auch nicht. Ich habe eine abgeleitete Klasse erstellt und den Superkonstruktor mit super aufgerufen ("/ sdcard/f.jar", "/ sdcard", null, getSystemClassLoader()); Aber kein Erfolg. Ob defineClass oder findClass eine dynamisch angehängte Klasse zurückgeben. Mein Verdächtiger ist, dass Android dies überhaupt nicht unterstützt, sonst sollte normale defineClass schon funktionieren. Wahrscheinlich wegen einiger Sicherheitsprobleme. Aber ich würde auf jeden Fall gerne Gründe hören, ich habe auch einen Thread auf Android-Entwickler Google-Gruppe gestartet. – anselm

Antwort

47

Es gibt eine example von DexClassLoader in der Dalvik Testsuite. Es greift auf die Classloader reflexiv, aber wenn Sie bauen gegen das Android SDK können Sie einfach tun:

String jarFile = "path/to/jarfile.jar"; 
DexClassLoader classLoader = new DexClassLoader(
    jarFile, "/tmp", null, getClass().getClassLoader()); 
Class<?> myClass = classLoader.loadClass("MyClass"); 

Damit dies funktioniert, sollte die JAR-Datei enthält einen Eintrag namens classes.dex. Mit dem dx Tool, das mit Ihrem SDK geliefert wird, können Sie ein solches Glas erstellen.

+2

Ersetzen Sie "/ tmp" durch etwas anderes auf dem Gerät. – fadden

+0

Danke Ich kann bestätigen, dass das jetzt funktioniert, großartig! – anselm

+2

dx.bat --dex --output = E: \ classes.dex E: \ test_app.jar – diyism