Я создаю приложение для домашней автоматизации. Я пытаюсь добавить систему плагинов. В качестве теста я экспортировал тестовый класс (который является подклассом Button) в виде файла APK и поместил его в каталог файлов моего приложения. Я смог создать новый экземпляр этого класса и поместить его в свой вид, используя DexClassLoader
и .loadClass
.
Следующим шагом будет сканирование всех APK в этом каталоге и получение имен классов в них.
Я нашел класс DexFile, который делает именно это, но выдает следующие исключения:
04-18 17:26:15.697: E/dalvikvm(726): Can't open dex cache '/data/dalvik-cache/data@[email protected]@[email protected]@classes.dex': No such file or directory
04-18 17:26:15.705: I/dalvikvm(726): Unable to open or create cache for /data/data/com.strutton.android.testplugin/files/testloadclass.apk (/data/dalvik-cache/data@[email protected]@[email protected]@classes.dex)
Казалось бы, он пытается найти оптимизированный DexFile в системном кеше, но у меня нет прав доступа к каталогу кеша. Из того, что я вижу, это, вероятно, дизайн, и у меня нет проблем с этим. Есть ли другой способ проанализировать файл DEX и получить из него имена классов?
Я просмотрел исходный код некоторых проектов декомпилятора dex. Должен ли я свернуть свое собственное решение?
Вот код моего тестового приложения (из моей Activity OnCreate) на случай, если я что-то пропустил:
try {
ArrayList<String> UIPlugins = new ArrayList<String>();
final File filesDir = this.getFilesDir();
final File tmpDir = getDir("dex", 0);
final DexClassLoader classloader = new DexClassLoader( filesDir.getAbsolutePath()+"/testloadclass.apk",
tmpDir.getAbsolutePath(),
null, this.getClass().getClassLoader());
final Class<Button> classToLoad =
(Class<Button>) classloader.loadClass("com.strutton.android.testloadclass.MyTestClass_IRDroidUIPlugIn");
Button mybutton = classToLoad.getDeclaredConstructor(Context.class).newInstance(this);
mybutton.setId(2);
mybutton.setOnClickListener(this);
main.addView(mybutton);
// Up to here everything works as expected
// This line throws the exceptions
DexFile mDexFile = new DexFile(filesDir.getAbsolutePath()+"/testloadclass.apk";);
Enumeration<String> classNames = mDexFile.entries();
while (classNames.hasMoreElements()){
String className = classNames.nextElement();
if (className.endsWith("IRDroidUIPlugIn")){
UIPlugins.add(className);
}
}
final Class<Button> classToLoad =
(Class<Button>) classloader.loadClass("com.strutton.android.testloadclass.MyTestClass_IRDroidUIPlugIn");
Button mybutton = classToLoad.getDeclaredConstructor(Context.class).newInstance(this);
mybutton.setId(2);
mybutton.setOnClickListener(this);
main.addView(mybutton);
btn.setText(tmpDir.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}