Guo Xiaoxing
Weibo: Guo Xiaoxing's Sina Weibo
Email:[email protected]
Blog: http://blog.csdn.net/allenwells
Github:https://github.com/allenwell
In the article Dalvik the mechanism of virtual machine load class, we discuss the principle of Dalvik virtual machine load class, this article discusses how to use these mechanisms provided by Dalvik for dynamic loading of Dex/jar.
The first thing to note is that while the Dalvik virtual machine can be dynamically loaded, it is not as easy as a Java virtual machine to load the jar dynamically, nor does it support loading class files from a byte stream.
The reason for this is that the Dalvik virtual machine runs not the class bytecode in the Java packaged jar, but rather optimizes the converted Dalvik bytecode with the DX tool. In the Android Project package apk, the introduced Jar will also be packaged into the classes.dex.
Here's an example of how to invoke Dex/jar dynamically.
(1) Write the interface class
package com.allenwells.dexdynamiccalldemo;import android.content.Context;publicinterface LibraryInterface{ publicvoidshowAwesomeToast(Context context, String message);}
(2) Implement the interface class
PackageCom.allenwells.dexdynamiccalldemo.lib;ImportCom.allenwells.dexdynamiccalldemo.LibraryInterface;ImportAndroid.content.Context;ImportAndroid.widget.Toast; Public class libraryprovider implements libraryinterface{ Public void Showawesometoast(Context context, String message) {if(Context = =NULL) {return; } toast.maketext (Context, String.Format ("Libraryprovider Print: + +%s + +", message), Toast.length_long). Show (); }}
(3) Packaging the interface implementation class Libraryprovider into a jar file
After packaging as shown:
At this point the jar contains the JVM bytecode, which can only be recognized by the Java Virtual machine.
(4) Convert class file to Dex file
The DX tool is under android_sdk_home\build-tools\android-4.3, so skip the command line to the current directory, copy the Jvmcode.jar to the directory, and execute the following command:
dx--dex--output==DalvikCode.jarJVMCode.jar
After the command executes, the Dalvikcode.jar file is generated in the current directory, although Dalvikcode.jar is the file name suffix of the. jar, but it contains the Dex file, as shown in:
Put the generated dalvikcode.jar into the project's assets folder and delete the Com.allenwells.dexdynamiccalldemo.lib package, as shown in:
(5) Implement mainactivity, make external dex dynamic call.
PackageCom.allenwells.dexdynamiccalldemo;ImportJava.io.BufferedInputStream;ImportJava.io.BufferedOutputStream;ImportJava.io.File;ImportJava.io.FileOutputStream;ImportJava.io.IOException;ImportJava.io.OutputStream;Importandroid.app.Activity;ImportAndroid.app.ProgressDialog;ImportAndroid.content.Context;ImportAndroid.os.AsyncTask;ImportAndroid.os.Bundle;ImportAndroid.view.View;ImportAndroid.widget.ImageButton;ImportDalvik.system.dexclassloader;public class mainactivity extends Activity {PrivateStaticFinalString Secondary_dex_name ="Dalvikcode.jar";/ * * Set the copy cache size, this example uses 8*1024, or you can set the cache based on the actual size of the Secondary_dex.jar */ PrivateStaticFinalint buf_size =8*1024x768;PrivateImageButton Mtoastbutton =NULL;PrivateProgressDialog Mprogressdialog =NULL;@Overridepublic void OnCreate (Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (R.layout.activity_main); Mtoastbutton = (ImageButton) Findviewbyid (R.id.toast_button);/ * Copy the Secondary_dex.jar from the Aeest resource to the store for Dexclassloader calls * / FinalFile Dexinternalstoragepath =NewFile (Getdir ("Dex", context.mode_private), secondary_dex_name);if(!dexinternalstoragepath.exists ()) {Mprogressdialog = Progressdialog.show ( This, Getresources (). getString (R.string.diag_title), Getresources (). getString (r.string. Diag_message),true,false);/ * File copy in asynchronous task * /(NewPreparedextask ()). Execute (Dexinternalstoragepath); }Else{mtoastbutton.setenabled (true); } mtoastbutton.setonclicklistener (NewView.onclicklistener () {public void OnClick (view view) {/ * Dexclassloader The internal path that will be written to the optimized Dex file * / FinalFile Optimizeddexoutputpath = Getdir ("Outdex", context.mode_private);/ * Initialize Dexclassloader with third-party DEX files * /Dexclassloader Dexclassloader =NewDexclassloader (Dexinternalstoragepath.getabsolutepath (), Optimizeddexoutput Path.getabsolutepath (),NULL, getClassLoader ()); Class<?> Libproviderclazz =NULL;Try{/ * Load Libraryprovider class with class loader * /Libproviderclazz = Dexclassloader. LoadClass ("Com.allenwells.dexdynamiccalldemo.lib.LibraryProvider");/ * * Converts the returned object to a type, making it possible to make method calls directly in the interface. Another way to call it is to call with reflection, but this is a complex and inefficient operation. */Libraryinterface lib = (libraryinterface) libproviderclazz. newinstance ();/ * Call method, output print * /Lib.showawesometoast (View.getcontext (),"Hello"); }Catch(Exception Exception) {Exception.printstacktrace (); } } }); }/ * Copy the third-party Dex file from the asset resource file to the memory store * / PrivateBoolean Preparedex (File dexinternalstoragepath) {Bufferedinputstream bis =NULL; OutputStream Dexwriter =NULL;Try{bis =NewBufferedinputstream (Getassets (). Open (Secondary_dex_name)); Dexwriter =NewBufferedoutputstream (NewFileOutputStream (Dexinternalstoragepath)); byte[] buf =NewByte[buf_size]; int Len; while(len = Bis.read (buf,0, buf_size)) >0) {Dexwriter.write (buf,0, Len); } dexwriter.close (); Bis.close ();return true; }Catch(IOException e) {if(Dexwriter! =NULL) {Try{Dexwriter.close (); }Catch(IOException IoE) {Ioe.printstacktrace (); } }if(bis! =NULL) {Try{Bis.close (); }Catch(IOException IoE) {Ioe.printstacktrace (); } }return false; } }Private class preparedextask extends asynctask<File, Void, Boolean>{@Override protectedvoid oncancelled () {Super. oncancelled ();if(Mprogressdialog! =NULL) Mprogressdialog.cancel (); }@Override protectedvoid OnPostExecute (Boolean result) {Super. OnPostExecute (Result);if(Mprogressdialog! =NULL) Mprogressdialog.cancel (); }@Override protectedBoolean doinbackground (File ... dexinternalstoragepaths) {Preparedex (dexinternalstoragepaths[0]);return NULL; } }}
Click Ddms to view the file information for the app under File Explorer, and you can see that Dalvikcode.jar is saved in the internal storage as shown in:
All work done from this, click on the Test button, run the program, as shown in the effect:
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Dalvik virtual machine dynamic load Dex/jar