我正在开发一个可以使用外部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
应该已经阻止了。
感谢帮助
干杯,雅各布斯
答案 0 :(得分:0)
在尝试了所有的事情后,我自己解决了。事实证明,它应该是Integer.class != int
Class[] cArg = new Class[3];
cArg[0] = int.class;
cArg[1] = String.class;
cArg[2] = String[].class;