2010-06-11 17 views
30

Mi chiedo se e come si può caricare i file DEX o di classe dinamicamente in Dalvik, una certa funzione di test frettoloso e approssimativo che ho scritto è stato questo:Come caricare una classe Java in modo dinamico su 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(); 
      } 
    } 

mentre l'interfaccia Foo è questo

public interface Foo { 
      int get42(); 
    } 

e f.dex contiene alcune dx'ed implementazione di tale interfaccia:

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

Il collaudatore sopra getta defineCl ass() e che non si lavoro e ho studiato il codice Dalvik e abbiamo trovato questo:

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

Quindi mi chiedo se qualcuno mi può illuminare se questo è possibile in qualche altro modo o non dovrebbe essere possibile. Se non è possibile, qualcuno può fornire dei motivi per cui ciò non è possibile?

+1

Hai 'DexFile d', quindi non assegnarlo o non usarlo mai. AFAIK, 'DexClassLoader' è l'approccio corretto, anche se non l'ho usato personalmente. – CommonsWare

+0

Questo è vero, il DexFile è il resto di un altro trucco sporco che ho provato, ora cercherò DexClassLoader. – anselm

+0

Ho provato a usare DexClassLoader, ma anche questo non funziona. Ho creato una classe derivata e ho chiamato il supercostruttore con super ("/ sdcard/f.jar", "/ sdcard", null, getSystemClassLoader()); Ma nessun successo. Sia defineClass che findClass restituiscono qualsiasi classe che è allegata dinamicamente. Il mio sospetto è che Android non supporti affatto questo, altrimenti normale defineClass dovrebbe funzionare già. Probabilmente a causa di alcuni problemi di sicurezza. Ma mi piacerebbe sicuramente sentire le ragioni, ho anche iniziato una discussione su Google-sviluppatori di Android. – anselm

risposta

47

C'è un example di DexClassLoader nella suite di test Dalvik. Si accede al programma di caricamento classe riflessivo, ma se si sta costruendo contro l'SDK di Android si può semplicemente fare questo:

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

Per far funzionare tutto questo, il file jar deve contenere una voce denominata classes.dex. Puoi creare un vaso simile con lo strumento dx fornito con il tuo SDK.

+2

Sostituisci "/ tmp" con qualcos'altro sul dispositivo. – fadden

+0

Grazie posso confermare che funziona ora, fantastico! – anselm

+2

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

Problemi correlati