Jak mogę dynamicznie ładować plik jar w aplikacji dla systemu Android (4.0.3)
Mam aplikację dla systemu Android, która musi ładować dynamicznie klasę, niezdefiniowaną liczbę klasy jar, która zaimplementowała interfejs.
W rzeczywistości patrzę na katalog i pokazuję wszystkie pliki jar, które znajdują się w tym katalogu. Otwieram manifest pliku jar i znajduję powiązaną klasę i wypisuję je. I po tym, zainicjowałem dexClassLoader, aby załadować wszystkie pliki jar i sprawdzić, czy klasy, które znalazłem w manisfest implementują mój interfejs. W ten sposób mogę mieć całą klasę, która implementowała mój interfejs bez znajomości ich na początku
Aby wznowić, mam listę jar klasy, która implementuje mój interfejs, ale lista jest nieznana przez moją aplikację na Androida i przeze mnie. Lista klasy jar może się zmieniać przy każdym uruchomieniu aplikacji.
Ale kiedy próbowałem utworzyć DexClassLoader, nie powiodło się. Zawsze mam wskaźnik zerowy
DexClassLoader classLoader = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
Aby wykonać test, użyłem emulatora. Skopiowałem z moim DDMS pliki jar do katalogu /data/data/com.example.Myappli/JarFilesDirectory/*.jar
Zauważ, że mój plik jar zawiera plik dex
Dużo o tym czytam. Niektóre problemy z uprawnieniami wypróbowałem wszystko, ale nie znalazłem rozwiązania
Czy ktoś może mi pomóc?
tutaj treść manifestu pliku jar
Wersja manifestu: 1.0
Klasa modułu: com.example.asktester.AskPeripheral
Oto mój kod:
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;
}