NoSuchMethodException,尽管它在那里

时间:2016-01-13 09:48:20

标签: android apk dexclassloader

我正在开发一个可以使用外部apks的应用程序。为此,我使用DexClassLoader将类从外部apks加载到classes - 数组中,并使用这样的类:

getFragment(){
    for (Class<?> cls : classes) {
        Log.v("loadDexClasses", "Class loaded " + cls.getName());
        if (cls.getName().contains("OpenQuestionFragment")) {
            Method m = null;
            Fragment xb = null;
            try
            {
                Class[] cArg = new Class[3];
                cArg[0] = Integer.class;
                cArg[1] = String.class;
                cArg[2] = String[].class;
                m = cls.getMethod("getInstance",cArg);
                xb = (Fragment) m.invoke(null,INTNULL,STRINGNULL,STRINGARRAYNULL);
                showFragment(xb);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
                if(xb==null){
                    return;
                }
                if (xb.equals(ClassLoader.getSystemClassLoader()))
                    Log.v("loadDexClasses", "Same ClassLoader");
                else
                    Log.v("loadDexClasses", "Different ClassLoader");
            }
        }
    }
}

外部apk:

public class OpenQuestionFragment extends Fragment{

//flags
final static int INTNULL = -1;
final static String STRINGNULL = null;
final static String[] STRINGARRAYNULL = null;

static View view;
static String setter;
static boolean run = true;
private static int edittextid;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    RelativeLayout rl = new RelativeLayout(getActivity());
    EditText et = new EditText(getActivity());
    edittextid = view.generateViewId();
    et.setId(edittextid);
    rl.addView(et);
    et.setTextSize(70);
    //blub
    et.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
    RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)et.getLayoutParams();
    layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT,RelativeLayout.TRUE);
    et.setLayoutParams(layoutParams);
    et.setHint("hier eingeben");
    view = rl; //inflater.inflate(R.layout.testlayout, container, false);
    if(setter!=STRINGNULL && setter != ""){
        ((EditText) view.findViewById(edittextid)).setText(setter);
    }
    //initializeListenerThread();
    return view;
}


public static OpenQuestionFragment newInstance(String seter){
    /*setter=seter;
    run = true;*/
    return new OpenQuestionFragment();
}

public static Fragment getInstance(int intloader, String stringloader, String[] arrayloader){
    setter = stringloader;
    return newInstance(null);
}

public String getResult(){
    EditText ET = (EditText) view.findViewById(edittextid);
    return ET.getText().toString();
}

public String getQuestionTag(){
    return "OpenQuestion";
}

public boolean isAnswered(){
    EditText ET = (EditText) view.findViewById(edittextid);
    if(ET.getText().toString()!=""){
        return false;
    }else{
        return true;
    }
}

@Override
public void onDestroy(){
    run = false;
    super.onDestroy();
}
}

和proguard,以防止未使用的方法被组装:

-keepclassmembers class dexloader.openquestion.OpenQuestionFragment {
   public *;
}

我已经知道,加载的类没有问题,因为“newInstance”函数可以被称为EXACT相同的方式,除了稍微调整cArg-Array,以匹配搜索后的方法,如下所示: / p>

Class[] cArg = new Class[3];
cArg[0] = Integer.class;
cArg[1] = String.class;
cArg[2] = String[].class;
m = cls.getMethod("getInstance",cArg);
xb = (Fragment) m.invoke(null,INTNULL,STRINGNULL,STRINGARRAYNULL); 

进入

Class[] cArg = new Class[1];
cArg[0] = String.class;
m = cls.getMethod("newInstance",cArg);
xb = (Fragment) m.invoke(null,STRINGNULL);

当我启动应用程序时,它仍会抛出一个NoSuchMethodException,当我调用m.invoke();时,它会被抓住,而且......这不应该发生。唯一的区别,我可以看到,getInstance()没有使用,但proguard-rule应该已经阻止了。

感谢帮助

干杯,雅各布斯

1 个答案:

答案 0 :(得分:0)

在尝试了所有的事情后,我自己解决了。事实证明,它应该是Integer.class != int

                Class[] cArg = new Class[3];
            cArg[0] = int.class;
            cArg[1] = String.class;
            cArg[2] = String[].class;