NoSuchMethodException,尽管它在那里
NoSuchMethodException, despite it beeing there
我正在开发一个可以与外部 apk 一起使用的应用程序。为此,我使用 DexClassLoader 将 classes 从外部 apks 加载到 classes
-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();
}
}
和proguard,以防止未使用的方法不被组装:
-keepclassmembers class dexloader.openquestion.OpenQuestionFragment {
public *;
}
我已经知道,加载的 class 没有问题,因为 "newInstance" 函数可以完全相同的方式调用,除了稍微调整 cArg-Array 以匹配追捧方法,如下:
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);
当我启动应用程序时,当我调用 m.invoke();
时,它仍然会抛出 NoSuchMethodException
,它会被捕获,嗯......这不应该发生。我能看到的唯一区别是 getInstance()
没有被使用,但是 proguard-rule
应该已经阻止了。
感谢帮助
干杯,雅各布斯
在尝试了一切之后,我自己解决了这个问题。结果 Integer.class != int
应该是
Class[] cArg = new Class[3];
cArg[0] = int.class;
cArg[1] = String.class;
cArg[2] = String[].class;
我正在开发一个可以与外部 apk 一起使用的应用程序。为此,我使用 DexClassLoader 将 classes 从外部 apks 加载到 classes
-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();
}
}
和proguard,以防止未使用的方法不被组装:
-keepclassmembers class dexloader.openquestion.OpenQuestionFragment {
public *;
}
我已经知道,加载的 class 没有问题,因为 "newInstance" 函数可以完全相同的方式调用,除了稍微调整 cArg-Array 以匹配追捧方法,如下:
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);
当我启动应用程序时,当我调用 m.invoke();
时,它仍然会抛出 NoSuchMethodException
,它会被捕获,嗯......这不应该发生。我能看到的唯一区别是 getInstance()
没有被使用,但是 proguard-rule
应该已经阻止了。
感谢帮助
干杯,雅各布斯
在尝试了一切之后,我自己解决了这个问题。结果 Integer.class != int
应该是
Class[] cArg = new Class[3];
cArg[0] = int.class;
cArg[1] = String.class;
cArg[2] = String[].class;