Comment puis-je Charger un fichier jar de façon dynamique dans une application android (version 4.0.3)
J'ai une application android qui a pour charger dynamiquement classe ,un nombre indéterminé d'un pot de classe qui a mis en place une interface.
En fait, j'ai regarder un annuaire et la liste de tous les fichiers jar qui sont dans ce répertoire
J'ai ouvert le manifeste du fichier jar et de trouver les associés de classe et de les énumérer.
Et après, je instanciés un dexClassLoader pour charger tous les fichiers jar et à trouver si les classes que j'ai trouvé dans le manisfest mettre en œuvre mon interface.
Comme ça je peux avoir toute la classe qui a mis en place mon interface sans le savoir à la base
Pour la reprendre, j'ai une liste de classe pot de mettre en œuvre mon interface, mais la liste est inconnu par mon application android, et par moi. La liste des classes jar peut être modifiée à chaque fois que je lance mon application.
Mais quand j'ai essayé de créer le DexClassLoader il est échoué. J'ai toujours un pointeur null
DexClassLoader classLoader = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
Pour faire mon test, j'ai utilisé l'émulateur. Je l'ai copié avec mon DDMS les fichiers jar dans le répertoire
/data/data/com.exemple.Myappli/JarFilesDirectory/*.jar
Avis que mon fichier jar contenu du fichier dex
J'ai lu beaucoup de chose sur ce sujet. Certains problèmes avec les permissions
J'ai essayé de chaque chose, mais pas trouvé la solution
Quelqu'un peut m'aider s'il vous plaît !!!
ici le contenu manifeste d'un fichier jar
Manifest-Version: 1.0
Module de Classe: com.exemple.asktester.AskPeripheral
Voici mon code :
public class ModuleLoader {
private static List<URL> urls = new ArrayList<URL>();
private static List<String> getModuleClasses(String folder)
{
List<String> classes = new ArrayList<String>();
//we are listing the jar files
File[] files = new File(folder).listFiles(new ModuleFilter());
for(File f : files)
{
JarFile jarFile = null;
try
{
//we open the jar file
jarFile = new JarFile(f);
//we recover the manifest
Manifest manifest = jarFile.getManifest();
//we recover the class
String moduleClassName = manifest.getMainAttributes().getValue("Module-Class");
classes.add(moduleClassName);
urls.add(f.toURI().toURL());
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(jarFile != null)
{
try
{
jarFile.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
return classes;
}
private static class ModuleFilter implements FileFilter {
@Override
public boolean accept(File file) {
return file.isFile() && file.getName().toLowerCase().endsWith(".jar");
}
}
private static ClassLoader classLoader;
public static List<IPeripheral> loadModules(String folder, Context CurrentContext) throws IOException, ClassNotFoundException
{
List<IPeripheral> modules = new ArrayList<IPeripheral>();
List<String> classes = getModuleClasses(folder);
final File dexInternalStoragePath = new File(CurrentContext.getDir("dex", Context.MODE_PRIVATE),"ask.dex");
File dexOutputDir = CurrentContext.getDir("dex", Context.MODE_PRIVATE);
final File dexClasses = new File(CurrentContext.getDir("dex", Context.MODE_PRIVATE),"ASK.jar");
DexFile dexFile = DexFile.loadDex(dexClasses.getAbsolutePath(), dexOutputDir.getAbsolutePath(), 0);
DexClassLoader classLoader = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
//Class<?> myClass = classLoader.loadClass("com.example.asktester.AskPeripheral");
if(IPeripheral.class.isAssignableFrom(myClass )){
Class<IPeripheral> castedClass = (Class<IPeripheral>)myClass ;
IPeripheral module = castedClass.newInstance();
modules.add(module);
}
}
catch (ClassNotFoundException e1)
{
e1.printStackTrace();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
return modules;
}
OriginalL'auteur Virginie Voirin | 2012-07-12
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé la solution à mon problème.
Pour charger dynamiquement pot, les classes qui implémentent une interface dans une application android, certaines tâches doivent être faites dans le bocal :
Créer votre propre manisfest pour le pot et mettre cette information
Exporter votre pot à l'aide d'eclipse et de mettre en paramètre il utilise son propre manisfest
Créer les classes.dex associés pour le pot
(ce fichier est nécessaire par le Dalvik VM, il suffit de pot peut pas être lu par le dalvik VM)
Attention, le nom de l'indice dex fichier DOIT ÊTRE classes.dex
Ajouter le fichier classes.dex dans le fichier jar
Vous devez également avoir le droit d'écrire dans le cache dalvik répertoire
Le faire à chaque fois, votre relancer votre émulateur
mettre ce fichier jar dans l'émulateur par exemple sur la SDcard
Utiliser un PathClassLoader pour charger le fichier jar
NB : le LogCat dans Eclipse vous donne de précieuses informations. N'oubliez pas de regarder ses messages
Ci-dessous, le code :
Mon interface :
MyPeripheral qui implémente l'interface
Comment charger dynamiquement les fichiers jar
OriginalL'auteur Virginie Voirin
Il serait également une bonne idée d'utiliser le chargeur de classe plutôt que le Dalvik chemin de la classe loader:
Où url est l'emplacement du fichier en cours de chargement "à partir de".
ApplicationConstants.ref_currentActivity est tout simplement une activité de classe - mon application est assez compliquée en raison de la dynamique modulaire de chargement - j'ai donc besoin de garder une trace de cette façon, mais d'autres peuvent probablement utiliser simplement "présent" si cette classe est déjà une activité.
La raison PRINCIPALE de l'utilisation de la classe loader sur le dalvik - est qu'il ne nécessite pas l'écriture des fichiers de cache, et donc la permission chmod 777 /data/dalvik-cache est unrequired - et bien sûr vous n'avez pas besoin de passer cette commande à partir de la racine sur un téléphone enracinée pro-grammaticalement.
Il est toujours préférable de ne pas avoir les utilisateurs forcé à la racine de leurs téléphones portables, tout simplement parce que votre application l'exige. Surtout si votre application est un plus professionnel "signifie pour l'entreprise type d'utilisation" -.La politique du travail, contre l'utilisation des téléphones enracinées sont généralement en place.
Si quelqu'un a des questions sur des modules de chargement - s'il vous plaît n'hésitez pas à demander.
La base de mon code actuel est grâce à Virginie Voirin, avec mes propres modifications. Bonne chance à tous!
OriginalL'auteur ryvianstyron