2016-06-29 2 views
1

Intro: Je tente de charger du code en cours d'exécution à partir d'un classes.dex qui se trouve dans un fichier classes.jar. J'ai fait beaucoup de recherches et j'ai passé beaucoup de temps là-dessus, alors j'ai vraiment besoin d'aide.Android: le chargement de la classe DexClassLoader échoue lors du chargement de l'interface

Problème: Lorsque mon fichier jar contient une classe simple, il est chargé avec succès. Cependant, dans la même situation que mon pot contient la même classe, seulement maintenant que la classe implémente une interface, le chargement de cette classe échoue avec l'erreur:

"Didn't find class "com.x.y.z.w.Patch" on path: DexPathList[[zip file "/data/user/0/x.y.z/app_dex/classes_dexed.jar"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]"

Je reçois aussi:

I/dalvikvm: Failed resolving Lcom/x/y/TestClassImpl; interface 4 'Lcom/x/y/TestClassInterface;'

Environnement: - Fonctions utilisées pour essayer de charger une classe:

(par exemple DexClassLoader) .loadClass & (instance DexFile) .loadClass.

Plus précisément:

Méthode 1:

DexFile dx = DexFile.loadDex(jarInternalPath, File.createTempFile("opt", "dex", 
    context.getCacheDir()).getPath(), 0); 
Class<?> targetClass = dx.loadClass(className, 
    ClassLoader.getSystemClassLoader()); // Error 

Méthode 2:

DexClassLoader dexClassLoader = new DexClassLoader(jarInternalPath, 
    dexOutPath.getAbsolutePath(), null, ClassLoader.getSystemClassLoader()); 
Class<?> targetClass = dexClassLoader.loadClass(className); // Error 
  • IDE: les applications studio 2.1.2
  • Dispositifs de test: Émulateur Nexus 4 (avec API 16, 19 & 23), également physique Nexus 5 Dispositif avec Android 6.0.1
  • Plus étonnant: Lorsque j'imprime les classes du fichier dex je vois la bonne classe chemin. J'utilise DexFile pour charger le contenu dex et imprimer ses chemins de classes. Cette méthode reconnaît le contenu correct! Cela me fait penser qu'il y a quelque chose à faire avec les permissions Android ou Linux. Je ne sais pas ..

C'est ma méthode d'impression:

try { 
    DexFile dx = DexFile.loadDex(jarInternalPath, File.createTempFile("opt", "dex", 
     context.getCacheDir()).getPath(), 0); 

    // Print all classes in the DexFile 
    for (Enumeration<String> classNames = dx.entries(); classNames.hasMoreElements();) { 
     String className = classNames.nextElement(); 
     Log.d(TAG, "Analyzing dex content, fonud class: " + className); 
    } 
} catch (IOException e) { 
    Log.d(TAG, "Error opening " + jarInternalPath, e); 
} 
  • post-scriptum Cela ne semble pas pertinent, mais peut-être pas: Mon application hôte, l'interface commune et la mise en œuvre du nouveau contenu se trouvent tous dans 3 modules différents du même projet. L'application a le nom de paquet de x.y.z, l'interface a pkgName de x.y.z.interface et l'implémentation a pkgName de x.y.z.impl.

Un deuxième projet j'ai essayé avec tous les 3 modules dans le même, 1 module n'a pas fonctionné de la même manière.

S'il vous plaît, aidez!

+0

essayer quelque chose comme ça ... https://gist.github.com/SelvinPL/eefa88add4fa33f41ca8 ... vous voyez, je suis redéfinissant la 'getClassLoader' de l'activité. .. Pourquoi? parce que je charge plusieurs bocaux et si vous ne le faites pas, vous créez la nouvelle instance de chargeur pour chaque bocal de chargement .... au lieu de le remplacer dans Activité vous pouvez: le remplacer dans la classe Application ou faire un chargeur global statique – Selvin

+0

utilisez-vous Gradle? comment vous ajoutez des dépendances (compiler/fourni) ... pourquoi avez-vous 3 paquets (apk et 2 jar)? toutes les interfaces (utilisées par apk lui-même) devraient être compilées dans apk (comme vous ne pouviez pas les utiliser dans un chargement dynamique) ... avez-vous des dépendances cilculaires? – Selvin

+0

Hey Selvin, répondant à votre 1er commentaire, je ne suis pas inquiet à propos de plusieurs instances de chargeur, pour le moment. Comme pour le 2ème commentaire, j'utilise Gradle, 3 modules: l'application, l'interface et l'implémentation. L'interface est vérifiée pour être compilée dans l'apk. Le module 'app' dépend du module d'interface, l'interface n'a aucune dépendance, l'implémentation dépend aussi de l'interface mais n'est pas compilée quand le module 'app' est compilé dans un apk (puisque je le compile manuellement, le dex it et le place dans le dossier assets du module 'app' pour test local). – esWoobi

Répondre

0

ce n'est pas suffisant pour charger votre classe. vous devez changer le chargeur de classe système pour utiliser votre propre classe depuis dex dynamiquement et par programmation. sinon, vous ne pouvez pas utiliser votre interface ou classe ou autre.

Si vous voulez charger une classe dynamiquement, chargez d'abord la classe dexfile ou dexclassloader et utilisez-la.

exemple,

Class<?> myOwnClass = MyDexClassLoader.loadClass("com.example.my");