问题描述
我建立一个家庭自动化应用。我想添加一个插件系统。我有一个测试导出的测试类(子类按钮)为APK文件并把它放在我的应用程序的文件目录。我能够创建这个类的一个新实例,并使用把它放在我查看 DexClassLoader
和 .loadClass
。
下一步是为扫描所有APK的这个目录中,并在其中获得的类的名称。
我发现DexFile类,做到了这一点但它抛出以下例外情况:
04-18 17:26:15.697:E / dalvikvm(726):无法打开DEX缓存/data/dalvik-cache/data@data@com.strutton。 android.testplugin @文件@ testloadclass.apk @ classes.dex':没有这样的文件或目录04-18 17:26:15.705:I / dalvikvm(726):无法打开或创建/data/data/com.strutton.android.testplugin/files/testloadclass.apk缓存(/数据/达尔维克缓存/数据@ @数据@ com.strutton.android.testplugin文件@ testloadclass.apk @ classes.dex)
这似乎是试图找到在系统缓存优化DexFile,但我没有权限到缓存目录。从我所看到的这可能是由于设计,我没有与一个问题。有另一种方式来解析一个DEX文件,并从它那里得到的类名称?
我已经看过源为一些DEX反编译器项目。我必须推出自己的解决方案?
下面是我的测试应用程序code(从我的活动OnCreate中),以防万一我错过了什么:
{尝试
ArrayList的<串GT; UIPlugins =新的ArrayList<串GT;();
最终文件FILESDIR = this.getFilesDir();
最后文件TMPDIR = GETDIR(DEX,0);
最后DexClassLoader类加载器=新DexClassLoader(filesDir.getAbsolutePath()+/ testloadclass.apk
tmpDir.getAbsolutePath(),
空,this.getClass()getClassLoader());
最后一类<按钮和GT; classToLoad =
(类<按钮和GT;)classloader.loadClass(com.strutton.android.testloadclass.MyTestClass_IRDroidUIPlugIn);
巴顿则myButton = classToLoad.getDeclaredConstructor(Context.class).newInstance(本);
mybutton.setId(2);
mybutton.setOnClickListener(本);
main.addView(myButton的);
//到这里一切正常
//此行抛出的异常
DexFile mDexFile =新DexFile(filesDir.getAbsolutePath()+/ testloadclass.apk);
枚举<串GT;类名= mDexFile.entries();
而(classNames.hasMoreElements()){
字符串的className = classNames.nextElement();
如果(className.endsWith(IRDroidUIPlugIn)){
UIPlugins.add(的className);
}
}
最后一类<按钮和GT; classToLoad =
(类<按钮和GT;)classloader.loadClass(com.strutton.android.testloadclass.MyTestClass_IRDroidUIPlugIn);
巴顿则myButton = classToLoad.getDeclaredConstructor(Context.class).newInstance(本);
mybutton.setId(2);
mybutton.setOnClickListener(本);
main.addView(myButton的);
btn.setText(tmpDir.getAbsolutePath());
}赶上(例外五){
e.printStackTrace();
}
而不是:
DexFile mDexFile =新DexFile(filesDir.getAbsolutePath()+/ testloadclass.apk);
尝试:
DexFile mDexFile = DexFile.loadDex(filesDir.getAbsolutePath()+/ testloadclass.apk,tmpDir.getAbsolutePath()+/ testloadclass.odex,0);
I am building a home automation app. I am trying to add a plugin system. I have as a test exported a test class (that subclasses Button) as an APK file and put it in my app's file directory. I was able to create a new instance of this class and put it in my View using DexClassLoader
and .loadClass
.
The next step is to scan all the APK's in this directory and get the names of the classes in them.
I found the DexFile class that does just that however it throws the following exceptions:
04-18 17:26:15.697: E/dalvikvm(726): Can't open dex cache '/data/dalvik-cache/data@data@com.strutton.android.testplugin@files@testloadclass.apk@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@data@com.strutton.android.testplugin@files@testloadclass.apk@classes.dex)
It would seem that it is trying to find the optimized DexFile in the system cache but I do not have permissions to the cache directory. From what I can see this is probably by design and I don't have a problem with that. Is there another way to parse a DEX file and get the class names from it?
I have looked at the source for some of the dex decompiler projects. Do I have to roll my own solution?
Here is my test app code (from my Activity OnCreate) just in case I missed something:
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();
}
Instead of:
DexFile mDexFile = new DexFile(filesDir.getAbsolutePath()+"/testloadclass.apk";);
try:
DexFile mDexFile = DexFile.loadDex(filesDir.getAbsolutePath()+"/testloadclass.apk", tmpDir.getAbsolutePath()+"/testloadclass.odex", 0);
这篇关于有没有办法让在给定classes.dex文件中的类名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!