2014-12-07 17 views
10

Przed wprowadzeniem systemu Android 5.0 mogłem dynamicznie ładować pliki DEX, używając metody DexClassLoader i wywołując metodę loadClass(), ale z najnowszą wersją systemu Android otrzymałem numer ClassNotFoundException.Załaduj dynamicznie plik DEX w systemie Android 5.0

Oto co robię:

  1. Generowanie pliku DEX.

    ../android-sdk/android-sdk-linux_86/build-tools/21.1.1/dx --dex --output=bin/output.dex bin/output.jar 
    
  2. Utwórz DexClassLoader.

    DexClassLoader cl = new DexClassLoader(
    dexFile.getAbsolutePath(), 
    odexFile.getAbsolutePath(), 
    null, 
    mContext.getClassLoader()); 
    
  3. połączeń cl.loadClass("myMethod");

Zdaję sobie sprawę, że sztuka wykorzystuje dex2oat aby wygenerować plik ELF, który jest ładowany przez sztukę, ale w kroku 2 Jestem generowania ODEX złożyć więc nie jestem co należy wykonać w ART, aby załadować plik DEX w czasie wykonywania, czy ktoś może mi pomóc?

+0

Dlaczego musisz załadować plik DEX w czasie wykonywania? 5.0 obsługuje natywnie wiele plików dex. – ianhanniballake

+1

Plik DEX zawiera poufne informacje i jest zaszyfrowany w katalogu zasobów. Kiedy potrzebuję go użyć, jest odszyfrowywany, a następnie ładowany w czasie wykonywania. – garibay

+1

@garibay czy udało Ci się rozwiązać ten problem? Mam ten sam problem, to działa tylko dla mnie w Dalvik. – cdroid

Odpowiedz

3

Aktualizacja

To działa zarówno na Dalvik i sztuce: new DexClassLoader(jarredDex.getAbsolutePath(), context.getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), null, context.getClassLoader()); gdzie jarredDex jest plik jar z classes.dex. Słoik można uzyskać, uruchamiając dx --dex --output=filename.jar your/classes/dir.


odpowiedź Original

ja wziąłem przykładowy kod z this article. Ale ART używa PathClassLoader zamiast Dalikiego DexClassLoader. Ten kod jest testowany na emulatorze z systemem Android 6 i na Xiaomi z systemem Android 5.1 i działa poprawnie:

// Before the secondary dex file can be processed by the DexClassLoader, 
// it has to be first copied from asset resource to a storage location. 
File dexInternalStoragePath = new File(getDir("dex", Context.MODE_PRIVATE), SECONDARY_DEX_NAME); 
try (BufferedInputStream bis = new BufferedInputStream(getAssets().open(SECONDARY_DEX_NAME)); 
    OutputStream dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath))) { 

    byte[] buf = new byte[BUF_SIZE]; 
    int len; 
    while((len = bis.read(buf, 0, BUF_SIZE)) > 0) { 
     dexWriter.write(buf, 0, len); 
    } 
} catch (IOException e) { 
    throw new RuntimeException(e); 
} 

try { 
    PathClassLoader loader = new PathClassLoader(dexInternalStoragePath.getAbsolutePath(), getClassLoader()); 
    Class<?> toasterClass = loader.loadClass("my.package.ToasterImpl"); 
    Toaster toaster = (Toaster) toasterClass.newInstance(); 
    toaster.show(this, "Success!"); 
} catch (ReflectiveOperationException e) { 
    throw new RuntimeException(e); 
}