PlatinTato
PlatinTato

Reputation: 378

NoSuchMethodException, despite it beeing there

I am working on an Application, which can work with external apks. For this i used the DexClassLoader , to load classes, from external apks into an classes-Array, and work with the classes like this:

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");
            }
        }
    }
}

external 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();
}
}

and the proguard, to prevent unused methods to not be assembled:

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

i already know, that there isnt a problem with the loaded class, as the "newInstance" function can be called the EXACT same way, except tweaking the cArg-Array slightly, to match the sought after method, like follows:

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); 

into

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

When i start the Application, it still throws a NoSuchMethodException, when i call m.invoke();, which gets caught, and well... that isnt supposed to happen. The only difference, i can see is, that getInstance() isnt used, but the proguard-rule should have prevented that.

Help is appreciated

Cheers, Jacobus

Upvotes: 0

Views: 62

Answers (1)

PlatinTato
PlatinTato

Reputation: 378

I solved it myself, after trying literally everything. It turns out, that Integer.class != int it should have been

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

Upvotes: 1

Related Questions