如何将加载的 class 从外部 apk 转换为接口 class
How to cast loaded class from external apk into interface class
//接口[=52=] -> 打包到myinterface.jar
package com.example.my_interface;
import com.example.my_interface.point;
pubic abstract class MyInterface{
publib Object obj;
public abstract Point newPoint(Point p);
}
//--- and other class ----
package com.example.my_interface.point;
public abstract class Point{
public int x;
public int y;
}
//项目 1 - 包含 myinterface.jar 并打包到 classA.apk
package com.testing.classa;
import com.example.my_interface.point;
public class ClsA extends MyInterface{
@Override
public Point newPoint(Point p){
Point newP;
newP.x = p.x + 1;
newP.y = p.y + 1;
return newP;
}
}
//主项目
// 包含 myinterface.jar
// 从这个 class (ClassB),我想从 classA.apk 文件中的 "ClsA" 调用 "newPoint" 方法。
package com.testing;
import com.example.my_interface.point;
public class ClsB{
Point p1;
p1.x = 2;
p1.y = 3;
Point newP;
String apkfilePath = '/data/data/com.testing/files/apps/classA.apk';
final File optimizedDexOutputPath = cnt.getDir("outdex", Context.MODE_PRIVATE);
DexClassLoader dLoader = new DexClassLoader(apkfilePath,
optimizedDexOutputPath.getAbsolutePath(),
null, ClassLoader.getSystemClassLoader().getParent());
try{
Class<?> loadedClass = dLoader.loadClass("com.testing.classa.ClsA");
Object obj = (Object) loadedClass.newInstance(); // (*)
Method m = loadedClass.getDeclaredMethod("newPoint", Point.class);
m.setAccessible(true);
newP = (Point) m.invoke(obj, p1); //(**)
}catch(Exception ex){
ex.printStackTrace();
}
Log.d("NewPoint x",Integer.toString(newP.x));
Log.d("NewPoint y",Integer.toString(newP.xy));
}
问题一。
在 (*): 我无法将实例后返回的 "obj" 转换为 MyInterface class,例如:
Object obj = (Object) loadedClass.newInstance();
MyInterface mi = (MyInterface) obj;
-> 错误:
Can not cast com.testing.classa.ClsA to com.example.my_interface.MyInterface`
为什么不呢?而在 com.testing.classa.ClsA 中扩展了 MyInterface ?
问题二。
在 (**):错误,
java.lang.IllegalArgumentException: argument 1 should have type com.example.my_interface.point, got com.example.my_interface.point
我想在mainclass上有接口myinterface.jar,在classA.apk上也有myinterface.jar,他们不能一起通话。
这个问题的解决方案是什么?
p/s:我在 google 上搜索过,有人建议从 .apk 中删除公共库(此处 myinterface.jar),
但是,如果删除它,将无法构建,因为错误。
帮帮我,谢谢。
您无法像您尝试的那样进行转换,因为您定义了两个接口。它们被称为相同,但在不同的 apk 中。这同样适用于 Point
,这就是为什么会出现第二个错误。
由于您已经在使用反射,因此您可以进行完全反射,根本不要在包之间共享 jar。
另一种解决方案是使用 AIDL,它是 Android
的接口定义语言
//接口[=52=] -> 打包到myinterface.jar
package com.example.my_interface;
import com.example.my_interface.point;
pubic abstract class MyInterface{
publib Object obj;
public abstract Point newPoint(Point p);
}
//--- and other class ----
package com.example.my_interface.point;
public abstract class Point{
public int x;
public int y;
}
//项目 1 - 包含 myinterface.jar 并打包到 classA.apk
package com.testing.classa;
import com.example.my_interface.point;
public class ClsA extends MyInterface{
@Override
public Point newPoint(Point p){
Point newP;
newP.x = p.x + 1;
newP.y = p.y + 1;
return newP;
}
}
//主项目 // 包含 myinterface.jar // 从这个 class (ClassB),我想从 classA.apk 文件中的 "ClsA" 调用 "newPoint" 方法。
package com.testing;
import com.example.my_interface.point;
public class ClsB{
Point p1;
p1.x = 2;
p1.y = 3;
Point newP;
String apkfilePath = '/data/data/com.testing/files/apps/classA.apk';
final File optimizedDexOutputPath = cnt.getDir("outdex", Context.MODE_PRIVATE);
DexClassLoader dLoader = new DexClassLoader(apkfilePath,
optimizedDexOutputPath.getAbsolutePath(),
null, ClassLoader.getSystemClassLoader().getParent());
try{
Class<?> loadedClass = dLoader.loadClass("com.testing.classa.ClsA");
Object obj = (Object) loadedClass.newInstance(); // (*)
Method m = loadedClass.getDeclaredMethod("newPoint", Point.class);
m.setAccessible(true);
newP = (Point) m.invoke(obj, p1); //(**)
}catch(Exception ex){
ex.printStackTrace();
}
Log.d("NewPoint x",Integer.toString(newP.x));
Log.d("NewPoint y",Integer.toString(newP.xy));
}
问题一。 在 (*): 我无法将实例后返回的 "obj" 转换为 MyInterface class,例如:
Object obj = (Object) loadedClass.newInstance();
MyInterface mi = (MyInterface) obj;
-> 错误:
Can not cast com.testing.classa.ClsA to com.example.my_interface.MyInterface`
为什么不呢?而在 com.testing.classa.ClsA 中扩展了 MyInterface ?
问题二。 在 (**):错误,
java.lang.IllegalArgumentException: argument 1 should have type com.example.my_interface.point, got com.example.my_interface.point
我想在mainclass上有接口myinterface.jar,在classA.apk上也有myinterface.jar,他们不能一起通话。 这个问题的解决方案是什么?
p/s:我在 google 上搜索过,有人建议从 .apk 中删除公共库(此处 myinterface.jar), 但是,如果删除它,将无法构建,因为错误。
帮帮我,谢谢。
您无法像您尝试的那样进行转换,因为您定义了两个接口。它们被称为相同,但在不同的 apk 中。这同样适用于 Point
,这就是为什么会出现第二个错误。
由于您已经在使用反射,因此您可以进行完全反射,根本不要在包之间共享 jar。
另一种解决方案是使用 AIDL,它是 Android
的接口定义语言