Android uses DexClassLoader to run other apk Methods
The dex file in the apk file in Android is compiled for java. class files are repackaged. Of course, some data is processed using your own protocol before packaging, such as optimizing function tables and variable tables. In java programs, classloader is used to load these compilers. class files. However, in android programs, DexClassLoader is used to load these files. here we can use DexClassLoader to dynamically load classes in program B in program A and call methods in program B.
1. First, create a common Android project, define a class called plugin in this project, and implement a simple method in the class, as shown below:
public class PluginClass {private static String TAG = PluginClass.class.getSimpleName();public PluginClass(){Log.i(TAG, "initialized");}public void invoke(String s){Log.i(TAG, s);}}
2. Run this Android project on an Android device.
3. Create an Android project again, and define a class named host. In this class, implement DexClassLoader to dynamically load the plugin class in the first project, as shown below:
Public class HostClass {private static String TAG = HostClass. class. getSimpleName (); private Context mContext = null; public HostClass (Context contect) {mContext = contect;} public void useDexClassLoader () {Intent intent Intent = new intent (); Intent. setPackage ("com. example. plugin "); PackageManager pm = mContext. getPackageManager (); final List
Plugins = pm. queryIntentActivities (intent, 0); if (plugins. size () <= 0) {Log. I (TAG, "resolve info size is:" + plugins. size (); return;} ResolveInfo resolveInfo = plugins. get (0); ActivityInfo activityInfo = resolveInfo. activityInfo; String div = System. getProperty ("path. separator "); String packageName = activityInfo. packageName; String dexPath = activityInfo. applicationInfo. sourceDir; // path of the apk or jar where the target class is located. class loader uses this path to load the target class file String dexOutputDir = mContext. getApplicationInfo (). dataDir; // because the dex file is included in the apk or jar file, you must decompress the dex file before loading the class. dexOutputDir is the decompressed path String libPath = activityInfo. applicationInfo. nativeLibraryDir; // path for storing c or c ++ library files that may be used by the target class. I (TAG, "div:" + div + "" + "packageName:" + packageName + "" + "dexPath:" + dexPath + "" + "dexOutputDir: "+ dexOutputDir +" "+" libPath: "+ libPath); DexClassLoader dcLoader = new DexClassLoader (dexPath, dexOutputDir, libPath, this. getClass (). getClassLoader (); try {Class
Clazz = dcLoader. loadClass (packageName + ". pluginClass "); Object obj = clazz. newInstance (); Class [] param = new Class [1]; param [0] = String. class; Method action = clazz. getMethod ("invoke", param); action. invoke (obj, "test this function");} catch (ClassNotFoundException e) {Log. I (TAG, "ClassNotFoundException");} catch (InstantiationException e) {Log. I (TAG, "InstantiationException");} catch (IllegalAccessException e) {Log. I (TAG, "IllegalAccessException");} catch (NoSuchMethodException e) {Log. I (TAG, "NoSuchMethodException");} catch (IllegalArgumentException e) {Log. I (TAG, "IllegalArgumentException");} catch (InvocationTargetException e) {Log. I (TAG, "InvocationTargetException ");}}}
4. After running the second project, you can view the log and find that the host loads the pluginclass class through DexClassLoader, and successfully calls the method in the plugin.
I/HostClass( 8341): div:: packageName:com.example.plugin dexPath:/data/app/com.example.plugin-1.apk dexOutputDir:/data/data/com.example.host libPath:/data/app-lib/com.example.plugin-1D/dalvikvm( 8341): DexOpt: --- BEGIN 'com.example.plugin-1.apk' (bootstrap=0) ---D/dalvikvm( 8341): DexOpt: --- END 'com.example.plugin-1.apk' (success) ---D/dalvikvm( 8341): DEX prep '/data/app/com.example.plugin-1.apk': unzip in 39ms, rewrite 723msI/PluginClass( 8341): initializedI/PluginClass( 8341): test this functionD/libEGL ( 8341): loaded /system/lib/egl/libEGL_mali.soD/libEGL ( 8341): loaded /system/lib/egl/libGLESv1_CM_mali.soD/libEGL ( 8341): loaded /system/lib/egl/libGLESv2_mali.soD/OpenGLRenderer( 8341): Enabling debug mode 0I/HostClass( 8341): div:: packageName:com.example.plugin dexPath:/data/app/com.example.plugin-1.apk dexOutputDir:/data/data/com.example.host libPath:/data/app-lib/com.example.plugin-1I/PluginClass( 8341): initializedI/PluginClass( 8341): test this function