├── .classpath ├── .gitignore ├── .project ├── AndroidManifest.xml ├── README.md ├── assets └── hello.dex ├── ic_launcher-web.png ├── libs └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── drawable-xxhdpi │ └── ic_launcher.png ├── layout │ └── activity_main.xml └── values │ └── strings.xml └── src └── nfh └── speeder └── sample └── android └── customloaddexfile ├── CustomizedDexClassLoader.java ├── DexPreparationTask.java └── MainActivity.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | !/assets/*.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | CustomLoadDexFile 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #CustomLoadDexFile 2 | 3 | **It works on a pure Java lib. It do NOT guarantee that it will work in all situation** 4 | 5 | This project is a sample Android project to load compiled dex file. 6 | 7 | Instead of dividing code in project, in my situation is code from third party Java library. 8 | 9 | #Example 10 | 11 | - Supposed `https://github.com/liratanak/hello-gradle` as the third party library 12 | - `hello-gradle.jar` should be found in folder `build/libs` 13 | - Compile `hello-gradle.jar` to `hello.dex` via this command `/path/to/sdk/build-tools/20.0.0/dx --dex --output="/path/to/CustomLoadDexFile/assets/hello.dex" "/path/to/hello-gradle/build/libs/hello-gradle.jar"` 14 | - The dex file should be in `assets` folder because the sample code is using that folder [_Remember_: Dex file could also be loaded from external resource such as SD card or even from network stream] 15 | 16 | 17 | #Reference 18 | - Custom Class Loading in Dalvik | http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html 19 | - Dex.java source code | https://android.googlesource.com/platform/libcore/+/master/dex/src/main/java/com/android/dex/Dex.java -------------------------------------------------------------------------------- /assets/hello.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liratanak/custom-load-dex-file/6af406f05af7a8c99c98a4fcb2b57559459f5bc1/assets/hello.dex -------------------------------------------------------------------------------- /ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liratanak/custom-load-dex-file/6af406f05af7a8c99c98a4fcb2b57559459f5bc1/ic_launcher-web.png -------------------------------------------------------------------------------- /libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liratanak/custom-load-dex-file/6af406f05af7a8c99c98a4fcb2b57559459f5bc1/libs/android-support-v4.jar -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liratanak/custom-load-dex-file/6af406f05af7a8c99c98a4fcb2b57559459f5bc1/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liratanak/custom-load-dex-file/6af406f05af7a8c99c98a4fcb2b57559459f5bc1/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liratanak/custom-load-dex-file/6af406f05af7a8c99c98a4fcb2b57559459f5bc1/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liratanak/custom-load-dex-file/6af406f05af7a8c99c98a4fcb2b57559459f5bc1/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CustomLoadDexFile 5 | 6 | -------------------------------------------------------------------------------- /src/nfh/speeder/sample/android/customloaddexfile/CustomizedDexClassLoader.java: -------------------------------------------------------------------------------- 1 | package nfh.speeder.sample.android.customloaddexfile; 2 | 3 | import java.io.File; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | import android.content.Context; 7 | import dalvik.system.DexClassLoader; 8 | 9 | public class CustomizedDexClassLoader { 10 | 11 | private static Context context; 12 | 13 | private static DexClassLoader loader; 14 | 15 | public static void setContext(Context context) { 16 | CustomizedDexClassLoader.context = context; 17 | } 18 | 19 | public static DexClassLoader load(final String dexFileName) throws RuntimeException { 20 | if(null == context) { 21 | throw new RuntimeException("No context provided"); 22 | } 23 | if(null == loader) { 24 | final File dexInternalStoragePath = new File(context.getDir("dex", Context.MODE_PRIVATE), dexFileName); 25 | if (!dexInternalStoragePath.exists()) { 26 | try { 27 | (new DexPreparationTask(context, dexFileName)).execute(dexInternalStoragePath).get(); 28 | } catch (InterruptedException e) { 29 | throw new RuntimeException(e); 30 | } catch (ExecutionException e) { 31 | throw new RuntimeException(e); 32 | } 33 | } 34 | final File optimizedDexOutputPath = context.getDir("outdex", Context.MODE_PRIVATE); 35 | 36 | loader = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(), optimizedDexOutputPath.getAbsolutePath(), null, context.getClassLoader().getParent()); 37 | } 38 | return loader; 39 | } 40 | } -------------------------------------------------------------------------------- /src/nfh/speeder/sample/android/customloaddexfile/DexPreparationTask.java: -------------------------------------------------------------------------------- 1 | package nfh.speeder.sample.android.customloaddexfile; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.File; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | 10 | import android.content.Context; 11 | import android.os.AsyncTask; 12 | 13 | public class DexPreparationTask extends AsyncTask { 14 | 15 | private Context mContext; 16 | private String mDexFileName; 17 | private final int BUF_SIZE = 8 * 1024; 18 | 19 | public DexPreparationTask(Context context, String dexFileName) { 20 | mContext = context; 21 | mDexFileName = dexFileName; 22 | } 23 | 24 | @Override 25 | protected Boolean doInBackground(File... dexInternalStoragePaths) { 26 | prepareDex(dexInternalStoragePaths[0]); 27 | return null; 28 | } 29 | 30 | public boolean prepareDex(File dexInternalStoragePath) { 31 | BufferedInputStream bis = null; 32 | OutputStream dexWriter = null; 33 | 34 | try { 35 | bis = new BufferedInputStream(mContext.getAssets().open(mDexFileName)); 36 | dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath)); 37 | byte[] buf = new byte[BUF_SIZE]; 38 | int len; 39 | while ((len = bis.read(buf, 0, BUF_SIZE)) > 0) { 40 | dexWriter.write(buf, 0, len); 41 | } 42 | dexWriter.close(); 43 | bis.close(); 44 | return true; 45 | } catch (IOException e) { 46 | if (dexWriter != null) { 47 | try { 48 | dexWriter.close(); 49 | } catch (IOException ioe) { 50 | throw new RuntimeException(ioe); 51 | } 52 | } 53 | if (bis != null) { 54 | try { 55 | bis.close(); 56 | } catch (IOException ioe) { 57 | throw new RuntimeException(ioe); 58 | } 59 | } 60 | return false; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/nfh/speeder/sample/android/customloaddexfile/MainActivity.java: -------------------------------------------------------------------------------- 1 | package nfh.speeder.sample.android.customloaddexfile; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | import android.annotation.SuppressLint; 7 | import android.app.Activity; 8 | import android.os.Bundle; 9 | import android.widget.TextView; 10 | import dalvik.system.DexClassLoader; 11 | 12 | @SuppressLint("NewApi") 13 | public class MainActivity extends Activity { 14 | 15 | TextView helloTextView; 16 | DexClassLoader dexClassLoader; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_main); 22 | 23 | CustomizedDexClassLoader.setContext(this); 24 | 25 | try { 26 | dexClassLoader = CustomizedDexClassLoader.load("hello.dex"); 27 | } catch (RuntimeException e) { 28 | throw new RuntimeException(e); 29 | } 30 | 31 | helloTextView = (TextView) findViewById(R.id.textview); 32 | } 33 | 34 | @Override 35 | protected void onStart() { 36 | super.onStart(); 37 | 38 | try { 39 | 40 | Class wordClass = dexClassLoader.loadClass("nfh.speeder.sample.gradle.hello.Word"); 41 | Method speederMethod = wordClass.getMethod("speeder"); 42 | String speeder = (String) speederMethod.invoke(wordClass.newInstance()); 43 | helloTextView.setText("Hello " + speeder); 44 | 45 | //The above 4 lines equals below 46 | //helloTextView.setText("Hello " + new nfh.speeder.sample.gradle.hello.Word().speeder()); 47 | 48 | } catch (ClassNotFoundException e) { 49 | } catch (NoSuchMethodException e) { 50 | } catch (IllegalAccessException e) { 51 | } catch (IllegalArgumentException e) { 52 | } catch (InvocationTargetException e) { 53 | } catch (InstantiationException e) { 54 | } 55 | 56 | } 57 | } 58 | --------------------------------------------------------------------------------