android - 有没有办法在给定的 classes.dex 文件中获取类名?

标签 android dex

我正在构建一个家庭自动化应用程序。我正在尝试添加一个插件系统。作为测试,我将测试类(Button 的子类)作为 APK 文件导出,并将其放在我的应用程序的文件目录中。我能够使用 DexClassLoader.loadClass 创建此类的新实例并将其放入我的 View 中。

下一步是扫描此目录中的所有 APK,并获取其中类的名称。

我发现 DexFile 类就是这样做的,但是它会抛出以下异常:

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)

它似乎试图在系统缓存中找到优化的 DexFile,但我没有缓存目录的权限。据我所知,这可能是设计使然,我对此没有意见。是否有另一种方法来解析 DEX 文件并从中获取类名?

我查看了一些 dex 反编译器项目的源代码。我必须推出自己的解决方案吗?

这是我的测试应用程序代码(来 self 的 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();
    }

最佳答案

代替:

DexFile mDexFile = new DexFile(filesDir.getAbsolutePath()+"/testloadclass.apk";);

尝试:

DexFile mDexFile = DexFile.loadDex(filesDir.getAbsolutePath()+"/testloadclass.apk", tmpDir.getAbsolutePath()+"/testloadclass.odex", 0);

关于android - 有没有办法在给定的 classes.dex 文件中获取类名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10214880/

相关文章:

android - 使用 Canvas 时背景只是黑色

php - 将编辑文本值从 android 插入到 mysql

java - 构建 Android 启动器

java - Android应用程序错误: "unfotunatley Application has stopped"

android - 带有 multidex 的 Xamarin Android - Debug模式下的错误

android - 多索引文件格式

android-gradle-plugin - 安卓 : Didn't find class "Picasso" on path: DexPathList (Failed resolution of: Picasso)

android - 如何在 Retrofit-2.0+ android 中设置超时

Android动态加载资源

android - 无法验证 dex : Bad method handle type 7