├── .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 |
--------------------------------------------------------------------------------