Brief introduction
"class loader" (ClassLoader), as the name suggests, is used to dynamically load class files. The standard Java SDK has a ClassLoader class that allows you to load the required class files, provided that the ClassLoader class initialization must develop the path to the class file.
The difference between the class file referenced by the Import keyword and the classloader dynamic load class:
The two features of the Import reference class:
1, must exist locally, when the program runs the class, the internal class loader will automatically load the class.
2, compile-time must be in the field, otherwise the compilation process will not be able to find the reference file can not compile correctly.
The characteristics of ClassLoader are precisely the opposite of import, and are more free and flexible.
Each ClassLoader must have a parent ClassLoader, when the class file is loaded, the child ClassLoader first requests its parent ClassLoader to load the file, and only if the file is not found by its parent ClassLoader The ClassLoader will inherit the class. This is a security mechanism. For Android, the final apk file contains the Dex type of file, Dex file is the class file repackaging, packaging rules are not simply compressed, but the class file inside the various function tables, variable table optimization, resulting in a new file, that is, Dex file. So loading this special class file requires a special ClassLoader dexclassloader.
The classloader involved in Java is ClassLoader this class, by Classloader.forname () method can load the class we need, so as to realize the need to dynamically load class libraries at runtime. But using ClassLoader directly in Android is not a viable option because of the Java bytecode files that ClassLoader loaded, and the DEX-formatted bytecode used in Android. This Android specifically provides a Dexclassloader class to complete the dynamic load APK requirements.
Instance
Here is a simple example to illustrate the use of this class of Dexclassloader, which involves two of knowledge points: Resource & Reflection invocation methods across packets. First create a client project, this project is simple, only a simple layout and a SayHello () method.
public class Main extends activity {
@Override
protected void onCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
This.setcontentview (R.layout.main);
}
@SuppressWarnings ("unused")
private void SayHello (String msg) {
log.d ("Mmtag", msg);
}
Then build another project that calls the view in the client project and calls the SayHello () method in this project. This class is mainly concerned with the use of this class of Dexclassloader.
Package com.example.dexclassloaderserver;
Import Java.lang.reflect.Method;
Import java.util.Collections;
Import java.util.List;
Import Dalvik.system.DexClassLoader;
Import Android.annotation.SuppressLint;
Import android.app.Activity;
Import android.content.Intent;
Import Android.content.pm.ActivityInfo;
Import Android.content.pm.PackageManager;
Import Android.content.pm.ResolveInfo;
Import Android.os.Bundle;
Import Android.util.Log; public class Mainactivity extends activity {@Override protected void onCreate (Bundle savedinstancestate) {Supe
R.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Usedexclassloader ();
@SuppressLint ("Newapi") public void Usedexclassloader () {Intent mintent = new Intent ();
Mintent.setclassname ("Com.example.dexclassloaderclient", "com.example.dexclassloaderclient.MainActivity");
Packagemanager pm = This.getpackagemanager (); list<resolveinfo> mlist = Pm.queryintentactivitieS (mintent, packagemanager.match_default_only);
Resolveinfo info = mlist.get (0);
String Apkpath = Info.activityInfo.applicationInfo.sourceDir;
String Optpath = This.getcodecachedir (). GetAbsolutePath ();
String libpath = Info.activityInfo.applicationInfo.nativeLibraryDir;
Dexclassloader Clsloader = new Dexclassloader (Apkpath, Optpath, Libpath, This.getclass (). getClassLoader ());
try {Class cls = Clsloader. LoadClass ("com.example.dexclassloaderclient.MainActivity");
Object obj = cls.newinstance ();
Method InvokeMethod = Cls.getdeclaredmethod ("SayHello", new class[] {string.class});
Invokemethod.setaccessible (TRUE);
Invokemethod.invoke (obj, "Hello World,dexclassloader");
catch (Exception e) {e.printstacktrace ();
}
}
}
The resulting results are:
I/dex2oat (20250): Dex2oat took 1.547s (threads:4)
D/mmtag (20229): Hello world,dexclassloader
d/ Openglrenderer (20229): Render Dirty Regions Requested:tru
This makes it a successful call to other methods in the APK.