其他分享
首页 > 其他分享> > android-如何将动态加载的类强制转换为其接口?

android-如何将动态加载的类强制转换为其接口?

作者:互联网

我正在创建一个允许插件视图的家庭自动化应用程序.

我有以下代码作为概念证明:

我创建了一个带有插件界面的android库项目:

package com.strutton.android.UIPlugInLib;

import android.app.Dialog;

public interface IRDroidInterface  {
    public Dialog buildConfigDialog(int ID);
    // Other method signatures here
}

我已经能够在一个单独的项目中创建一个类作为示例插件(并将其导出到apk),并将其推送到应用程序的文件目录中:

package com.strutton.android.testloadclass;

import com.strutton.android.UIPlugInLib.IRDroidInterface;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.View;
import android.widget.Button;

public class MyTestClass_IRDroidUIPlugIn extends Button implements IRDroidInterface{
    public final Activity mActivity;
    public MyTestClass_IRDroidUIPlugIn(Activity activity) {
        super((Context)activity);
        mActivity = activity;
        setText("I was loaded dynamically! (1)");
        setOnClickListener(new View.OnClickListener() {  
            public void onClick(View v) {  
                setText("I was Clicked dynamically! (" + getId() +")");
            }}  
                );
    }

    public Dialog buildConfigDialog(int ID){
        AlertDialog.Builder builder = new AlertDialog.Builder((Context)mActivity);
        builder.setMessage("Click the Button...(1)")
           .setCancelable(false)
           .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    mActivity.dialogDismiss();
               }           
           });
        return builder.create();
    }
}

我可以在运行时加载此类,并使用以下代码在我的onCreate()中创建它的实例:

package com.strutton.android.testplugin;

        try {
        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<View> classToLoad = 
                (Class<View>) classloader.loadClass("com.strutton.android.testloadclass.MyTestClass_IRDroidUIPlugIn");
        mybutton = (View) classToLoad.getDeclaredConstructor(Context.class).newInstance(this);
        mybutton.setId(2);
        main.addView((View)mybutton);
      } catch (Exception e) {
        e.printStackTrace();
    }

    setContentView(main);
}
protected Dialog onCreateDialog(int id) {
    switch (id) {
        case 1:
                    // this is the offending line 57
            return ((IRDroidInterface) mybutton).buildConfigDialog(id);
    }
    return null;
}

我希望插件能够显示插件中定义的配置对话框.当我调用buildConfigDialog(id)时,得到以下ClassCastException:

04-20 20:49:45.865:W / System.err(354):java.lang.ClassCastException:com.strutton.android.testloadclass.MyTestClass_IRDroidUIPlugIn
04-20 20:49:45.894:W / System.err(354):在com.strutton.android.testplugin.TestpluginActivity.onCreate(TestpluginActivity.java:57)

我在这里想念什么?我已经搜索了一天半,无法找到解决方案.

提前致谢.

解决方法:

我怀疑问题在于您的应用程序和加载的dex文件中都存在IRDroidInterface接口.当动态加载MyTestClass_IRDroidUIPlugIn类时,由于它是来自dex文件的,因此它是从dex文件而不是应用程序中实现的接口类.

如果可以确保该接口类未包含在该插件的dex文件中,那么我相信您所拥有的应该可以正常工作.

不幸的是,如果要使用eclipse或ant构建插件apk,这可能会很棘手.一种(相当丑陋的)解决方案是在构建dex文件后从其删除接口类.即,使用baksmali对其进行反汇编,删除该接口的.smali文件,然后使用smali进行重组.

标签:classcastexception,dynamic-controls,dialog,android,classloader
来源: https://codeday.me/bug/20191201/2080791.html