I have a little problem. I am developing an Android application. There you can dynamically load classes from other applications (packages). First of all, I don’t want to “hack” a third-party application, I want to try to create plugins for my own application. So what do I have?
2 test applications and 1 library included in both applications.
So the code for app1:
package com.ftpsynctest.app1; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import android.app.Activity; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import com.syncoorp.ftpsyncx.commons.SyncFile; import dalvik.system.PathClassLoader; public class App1Activity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); SyncFile f = new SyncFile("bla"); String classname = "com.ftpsynctest.app2.classcall"; String classpath = getApk("com.ftpsynctest.app1") + ":" + getApk("com.ftpsynctest.app2"); PathClassLoader myClassLoader = new dalvik.system.PathClassLoader(classpath, ClassLoader.getSystemClassLoader()); try { Class c = Class.forName(classname, true, myClassLoader); for (Method m : c.getDeclaredMethods()) { System.out.println("Method: " + m.getName()); for (Type t : m.getGenericParameterTypes()) { System.out.println(" - type: " + t.toString()); } m.invoke(c.newInstance(), new Object[] { new com.syncoorp.ftpsyncx.commons.SyncFile("bla") }); break; } } catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} } private String getApk(String packageName) { try { return this.getPackageManager().getApplicationInfo(packageName, 0).sourceDir;} catch (NameNotFoundException e) {e.printStackTrace();} return ""; } }
So, I want to create a class com.ftpsynctest.app2.classcall and call the method change with a parameter of type com.syncoorp.ftpsyncx. commons.SyncFile .
My application code 2:
package com.ftpsynctest.app2; import com.syncoorp.ftpsyncx.commons.SyncFile; public class classcall { public SyncFile modify(SyncFile file) { file.change_date = 123; return file; } }
First I set app2 to provide a class for app1. After that I started app1.
My conclusion:
01-10 22: 21: 48.804: INFO / System.out (4681): Method: change | 01-10 22: 21: 48.809: INFO / System.out (4681): - type: class com.syncoorp.ftpsyncx.commons.SyncFile
So for now, it looks good. the parameter type of the method found is com.syncoorp.ftpsyncx.commons.SyncFile and mine provided that one of them.
But I get the following error:
java.lang.IllegalArgumentException: argument type mismatch at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:507) at com.ftpsynctest.app1.App1Activity.onCreate(App1Activity.java:44) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667) at android.app.ActivityThread.access$1500(ActivityThread.java:117) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:130) at android.app.ActivityThread.main(ActivityThread.java:3691) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:507) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665) at dalvik.system.NativeStart.main(Native Method)
But why? my output tells me that it is a SyncFile, and I put SyncFile in the invoke command. What is the problem? Could it be that compiling app2 creates a class from SyncFile that is different from compiled application1? if so, why? The SyncFile class is the same physical class in my "commons" library, shared by both projects.
Does anyone have a solution or answer?