0

外部apkで動作するアプリケーションに取り組んでいます。このために、私は DexClassLoader を使用して、クラスを外部 apk から -Array にロードし、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();
}
}

未使用のメソッドがアセンブルされないようにするためのプロガード:

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

次のように、求められているメソッドに一致するように cArg-Array をわずかに微調整することを除いて、「newInstance」関数をまったく同じ方法で呼び出すことができるため、ロードされたクラスに問題がないことは既に知っています。

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を防ぐべきでした.

助けていただければ幸いです

乾杯、ヤコブス

4

1 に答える 1

1

文字通りすべてを試した後、私はそれを自分で解決しました。Integer.class != intそれはそうあるべきだったことが判明しました

                Class[] cArg = new Class[3];
            cArg[0] = int.class;
            cArg[1] = String.class;
            cArg[2] = String[].class;
于 2016-01-13T12:02:57.957 に答える