Android Dynamic loading code technology

Source: Internet
Author: User

Android Dynamic loading code technology

In the process of developing an Android app, you might want to implement a plug-in software architecture, publish some of the code separately in the form of another apk, and load and execute the code in this apk in the main program.

The general approach to this task is to:

Load class Clscontext Plugincontext = Maincontext.createpackagecontext (plugin_pkg, context.context_ignore_security | Context.context_include_code); ClassLoader loader = Plugincontext.getclassloader (); Class<?> cls = Loader.loadclass (class_name);//Invoking methods in the CLS through reflection technology, here is an example where the actual code depends on the case object obj = Cls.newinstance () ; method = Cls.getdeclaredmethod ("SomeMethod"); Method.invoke (obj);

However, this method has some problems in Android 4.1 and later systems: for charging apps, Google play installs it under an encrypted directory (specifically/data/app-asec), rather than a normal directory (specifically/data/app) , the application installed in the encrypted directory, we can not use the above method to load and execute code, and the reality is that we often rely on plug-in applications to charge.

One solution to this problem is to copy the binary code of the plug-in to the SD card, and the main program loads and executes its code from the SD card.

The specific ways to accomplish this are:

Class<?> cls = null;try {
Try the first method of CLS = LoadClass1 (Maincontext, pkg, entrycls);} catch (Exception e) {
Try the second method of cls = LoadClass2 (Maincontext, pkg, entrycls);}
Sample code
Object obj = cls.newinstance ();
method = Cls.getdeclaredmethod ("SomeMethod");
Method.invoke (obj);
The first method of loading
Private class<?> LoadClass1 (Context maincontext, String pkg, String entrycls) throws Exception {
Context Plugincontext = Maincontext.createpackagecontext (pkg, Context.context_include_code | context.context_ignore_security);
ClassLoader loader = Plugincontext.getclassloader ();
Return Loader.loadclass (ENTRYCLS);
}

The second method of loading
Private class<?> LoadClass2 (Context maincontext, String pkg, String entrycls) throws Exception {
Context Plugincontext = Maincontext.createpackagecontext (pkg, Context.context_include_code | context.context_ignore_security);
String path = Generateplugindexpath (Maincontext, pkg);
Ensurefileexist (plugincontext, pkg, path);
Cachedir must be a private directory of the main program, or Dexclassloader may refuse to load
String Cachedir = Maincontext.getapplicationinfo (). DataDir;
ClassLoader Parentloader = Plugincontext.getclassloader ();
Dexclassloader loader = new Dexclassloader (path, cachedir, NULL, parentloader);
Return Loader.loadclass (ENTRYCLS);
}

Get the program version number
private int Getversioncode (context context, String pkg) {
PackageInfo info = null;
int versioncode = 0;
try {
info = Context.getpackagemanager (). Getpackageinfo (pkg, packagemanager.get_activities);
Versioncode = Info.versioncode;
} catch (Exception e) {}
return versioncode;
}

Get the storage location of the plug-in binaries, pay attention to versioning; the path must end with. Dex or load will be problematic
private string Generateplugindexpath (context context, String pkg) {
int version = Getversioncode (context, pkg);
String path = Getmyapppath () + ". Classes/" + pkg + version + ". Dex";
return path;
}

The data directory of the main program on the SD card
Private String Getmyapppath () {
Return Environment.getexternalstoragedirectory (). GetAbsolutePath () + "/myapp/";
}
Copy the binary code of the plugin to the SD card
private void Ensurefileexist (Context plugincontext, string pkg, string path) throws Exception {
File File = new file (path);
if (file.exists ()) return;
File.getparentfile (). Mkdirs ();
Resources res = plugincontext.getresources ();
int id = res.getidentifier ("Classes", "raw", pkg);
InputStream in = Res.openrawresource (ID);
FileOutputStream out = new FileOutputStream (file);
try {
byte[] buffer = new byte[1024 * 1024];
int n = 0;
while ((n = in.read (buffer)) > 0) {
Out.write (buffer, 0, N);
} out.flush ();
} catch (IOException e) {
In.close ();
Out.close ();
}
}

The plug-in project side also need to make corresponding changes:

1. Compile the plug-in project;

2. Copy the Classes.dex under the bin directory to the/res/raw directory;

3. Recompile the plug-in project;

4. Release the plugin apk.

From: frydsh

Android Dynamic loading code technology

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.