2014-12-07 15 views
10

До Android 5.0 я смог динамически загружать DEX-файлы с помощью DexClassLoader и вызывать метод loadClass(), но с последней версией Android я получаю ClassNotFoundException.Динамически загружать DEX-файл на Android 5.0

Вот что я делаю:

  1. Генерация файла DEX.

    ../android-sdk/android-sdk-linux_86/build-tools/21.1.1/dx --dex --output=bin/output.dex bin/output.jar 
    
  2. Создайте DexClassLoader.

    DexClassLoader cl = new DexClassLoader(
    dexFile.getAbsolutePath(), 
    odexFile.getAbsolutePath(), 
    null, 
    mContext.getClassLoader()); 
    
  3. Вызов cl.loadClass("myMethod");

Я знаю, что ART использует dex2oat для генерации файла ELF, который является нагруженный ART, но на шаге 2 я генерируя ODEX файл, так что я не то, что необходимо сделать в ART для загрузки файла DEX во время выполнения, может ли кто-нибудь мне помочь?

+0

Зачем вам нужно загружать DEX-файл во время выполнения? 5.0 поддерживает несколько файлов dex изначально. – ianhanniballake

+1

Файл DEX имеет конфиденциальную информацию и шифруется в каталоге активов. Когда мне нужно его использовать, он расшифровывается, а затем загружается во время выполнения. – garibay

+1

@garibay вам удалось решить эту проблему? У меня такая же проблема, это работает только для Дальвика. – cdroid

ответ

3

Update

Это работает как на Dalvik и АРТ: new DexClassLoader(jarredDex.getAbsolutePath(), context.getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), null, context.getClassLoader()); где jarredDex является баночка-файл с classes.dex. Банку можно получить, запустив dx --dex --output=filename.jar your/classes/dir.


Оригинальный ответ

Я взял образец кода из this article. Но ART использует PathClassLoader вместо Далвика DexClassLoader. Этот код тестируется на эмуляторе с Android 6 и на Xiaomi с Android 5.1 и отлично работает:

// 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); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^