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!
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
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
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