一、温故动态加载ClassLoader机制

如果对Android的ClassLoader加载机制不熟悉,猛戳Android插件化开发动态加载基础之ClassLoader工作机制 http://blog.csdn.net/u011068702/article/details/53248960

二、介绍

         我们知道在Android中可以跟java一样实现动态加载jar,但是Android使用德海Dalvik VM,不能直接加载java打包jar的byte code,需要通过dx工具来优化Dalvik bytecode。
         Android在API中给出可动态加载的有:DexClassLoader 和 PathClassLoader(上面连接已经详细介绍)
         DexClassLoader:可加载jar、apk和dex,可以从SD卡中加载(这篇博客采用这种方式)

         PathClassLoader:只能加载已经安装搭配Android系统中的apk文件

三、曝Demo照片,不要怕,不多,很简单

Android插件化开发之DexClassLoader动态加载dex、jar小Demo_第1张图片

四、编写接口文件

package com.example.testclassloader;public interface ShowString {public String sayChenyu();}


五、编写接口实现文件

package com.example.testclassloader;import android.util.Log;public class ShowStringClass implements ShowString{public static final String TAG = "ShowStringClass";@Overridepublic String sayChenyu() {String chenyu = "chenyu";Log.i(TAG, chenyu);return chenyu;}}

六、打包成jar文件编译成dex

我们把ShowStringClass.java文件打包生成showStringClass.jar文件,然后把文件放到sdk目录下的build-tools下的23.0.1目录下,我用的是ubuntu,所以会看到dex文件,如果是window会在这个目录下看到dex.bat文件,然后用下面命令把showStringClass.jar生成showStringClass_imle.jar的dex文件
dx --dex --output=showStringClass_impl.jar showStringClass.jar
然后再把showStringClass_impl.jar文件放到手机目录里面去用这个命令
adb push showStringClass_impl.jar  /sdcard/
具体操作图片如下

七、然后编写MainActivity.java文件

package com.example.testclassloader;import java.io.File;import android.content.Context;import android.os.Bundle;import android.os.Environment;import android.support.v7.app.ActionBarActivity;import android.util.Log;import android.widget.TextView;import dalvik.system.DexClassLoader;public class MainActivity extends ActionBarActivity {    public static final String TAG = "MainActivityClassLoader";    public static final String SHOWSTRINGCLASS = "showStringClass_impl.jar";    public static final String SHOWSTRINGCLASS_PATH= "com.example.testclassloader.ShowStringClass";    public static final String DEX = "dex";    public ShowStringClass mShowStringClass = null;    public TextView mTv =  null;    public int i = 0;    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTv = (TextView)findViewById(R.id.hello);DexClassLoader(this);}/** * 使用DexClassLoader方式加载类 */public void  DexClassLoader(Context context) {// dex压缩文件的路径(可以是apk,jar,zip格式)        String dexPath = Environment.getExternalStorageDirectory().toString() + File.separator + SHOWSTRINGCLASS;        // dex解压释放后的目录        String dexOutputDirs = Environment.getExternalStorageDirectory().toString();        //指定dexoutputpath为APP自己的缓存目录        File dexOutputDir = context.getDir(DEX, 0);               // 定义DexClassLoader        // 第一个参数:是dex压缩文件的路径        // 第二个参数:是dex解压缩后存放的目录        // 第三个参数:是C/C++依赖的本地库文件目录,可以为null        // 第四个参数:是上一级的类加载器        //DexClassLoader dexClassLoader = new DexClassLoader(dexPath,dexOutputDirs,null,getClassLoader());        DexClassLoader dexClassLoader = new DexClassLoader(dexPath,dexOutputDir.getAbsolutePath(),null,getClassLoader());        Class libProvierClazz = null;        // 使用DexClassLoader加载类        try {            libProvierClazz = dexClassLoader.loadClass(SHOWSTRINGCLASS_PATH);            // 创建dynamic实例            mShowStringClass = (ShowStringClass) libProvierClazz.newInstance();            if (mShowStringClass != null) {            final String chenyu = mShowStringClass.sayChenyu();            if (chenyu != null) {            mTv.post(new Runnable() {@Overridepublic void run() {mTv.setText(chenyu);}            });            }            } else {            Log.d(TAG, "mShowStringClass is null");            }        } catch (Exception e) {            e.printStackTrace();        }}/** * 打印系统的classLoader */public void showClassLoader() {ClassLoader classLoader = getClassLoader();        if (classLoader != null){            Log.i(TAG, "[onCreate] classLoader " + i + " : " + classLoader.toString());            while (classLoader.getParent()!=null){                classLoader = classLoader.getParent();                Log.i(TAG,"[onCreate] classLoader " + i + " : " + classLoader.toString());                i++;            }        }}}

八、运行Demo的结果爆照

ubuntu终端打印结果如下 Android插件化开发之DexClassLoader动态加载dex、jar小Demo_第2张图片
手机上面照片如下 Android插件化开发之DexClassLoader动态加载dex、jar小Demo_第3张图片
说明加载外部的文件加载成功了
如果把上面那行代码改成这个
DexClassLoader dexClassLoader = new DexClassLoader(dexPath,dexOutputDirs,null,getClassLoader());
会报下面的错误 Android插件化开发之DexClassLoader动态加载dex、jar小Demo_第4张图片
需要加上缓存Dex文件的目录
      //指定dexoutputpath为APP自己的缓存目录        File dexOutputDir = context.getDir(DEX, 0);

九、总结

1、加深动态加载的理解 2、如何实现项目加载外部的Dex文件有了更好的理解 3、对DexClassLoader 、dexClassLoader.load(package.class)、 class.newInstance() 有了更好的理解

更多相关文章

  1. Android listview中嵌套Checkbox的布局文件
  2. [Android] 开发资料收集:动态加载、插件化、热修复技术
  3. android studio导入 so ,jar 文件。
  4. IDA动态调试Android的DEX文件
  5. android反编译apk文件
  6. android工程下的文件资源类型
  7. linux内核启动android文件系统过程分析
  8. Activity的四种加载模式

随机推荐

  1. Android视频录制、播放的两种方式
  2. Android进程间通讯——AIDL
  3. android DecorView
  4. 我的javaSE学习笔记
  5. Android(安卓)自定义 HorizontalScrollVi
  6. Activity类的runOnUiThread方法
  7. Android(安卓)SDK更新后报错 "Parsing Da
  8. Android(安卓)WebView开发全攻略
  9. [Android] 停止、恢复 背影音乐的播放
  10. attrs.xml文件中属性类型format值的格式