Android应用程序插件化研究之DexClassLoader

简介: 文章首发:Android应用程序插件化研究之DexClassLoader|大利猫 最近在研究Android应用的插件化开发,看了好几个相关的开源项目。插件化都是在解决以下几个问题: * 如何把插件apk中的代码和资源加载到当前虚拟机。 * 如何把插件apk中的四大组

文章首发:[Android应用程序插件化研究之DexClassLoader|大利猫](http://www.liuguangli.win/archives/366)


最近在研究Android应用的插件化开发,看了好几个相关的开源项目,插件化都是在解决以下几个问题:

* 如何把插件apk中的代码和资源加载到当前虚拟机。

* 如何把插件apk中的四大组件注册到进程中。

* 如何防止插件apk中的资源和宿主apk中的资源引用冲突。


围绕着这几个问题,我将会写系列文章逐步分析插件化的原理和实现方案。本篇文章主要讲第一点:如何加载另一个apk中的class。我们要把一个包含class文件的jar加载到java虚拟机中,需要使用ClassLoader这个类。Android的编译系统中对class文件进行了进一步的处理:最后变成 .dex文件,.dex文件包含在apk中,google提供了一个类来加载.dex文件,这个类就是DexClassLoader,它继承自ClassLoader。本篇的重点是写一个例子来说明DexClassLoader的用法。先来熟悉下DexClassLoader。

# DexClassLoader介绍

DexClassLoader是一个类加载器,可以用来从.jar和.apk文件中加载class。可以用来加载执行没用和应用程序一起安装的那部分代码。构造函数:DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)

<br>dexPath:被解压的apk路径,不能为空。

<br>optimizedDirectory:解压后的.dex文件的存储路径,不能为空。这个路径强烈建议使用应用程序的私有路径,不要放到sdcard上,否则代码容易被注入攻击。

<br>libraryPath:os库的存放路径,可以为空,若有os库,必须填写。

<br>parent:父亲加载器,一般为context.getClassLoader(),使用当前上下文的类加载器。

关于DexClassLoader更深入的理解,我建议读者先去研究一下Java的累加载器,然后在去读一读DexClassLoader的源码,本章不做深究,接下来写一个DemoDex来演示ClassLoader的使用。

# 创建一个插件apk工程module:bundle


我把插件的包名命名为:com.dexclassdemo.liuguangli.apkbeloaded,我们创建一个类:ClassToBeLoad:


    package com.dexclassdemo.liuguangli.apkbeloaded;

      import android.util.Log;

      public class ClassToBeLoad {    

      public  void method(){      

            Log.v("ClassToBeLoad", "called method of class " +       ClassToBeLoad.class.getName());  

      }

    }




我们会演示这个方法如何在宿主中被调用的,并且我们可以跟踪这个类的类加载器。我们编译这个工程得到的ask文件为:apkbeloaded-debug.apk。

# 创建一个宿主apk工程

我把宿主包名命名为:dexclassloaderdemo。我们在assets目录下创建一个目录plugins,然后把apkbeloaded-debug.apk拷贝到该目录下。在MainActivity中创建一个方法为:loadApk

    

    public  void loadApk(String apkPath) {   

     Log.v("loadDexClasses", "Dex Preparing to loadDexClasses!");   

     File dexOpt = this.getDir("dexOpt", MODE_PRIVATE);       

     final DexClassLoader classloader = new DexClassLoader(                    apkPath,               

     dexOpt.getAbsolutePath(),      

          null,               

     this.getClassLoader());     

       Log.v("loadDexClasses", "Searching for class : "                + "com.registry.Registry");       

     try {        

        Class<?> classToLoad = (Class<?>)     classloader.loadClass("com.dexclassdemo.liuguangli.apkbeloaded.ClassToBeLoad");          

      Object instance = classToLoad.newInstance();         

       Method method = classToLoad.getMethod("method");    

            method.invoke(instance);   

     } catch (IllegalAccessException e) { 

           e.printStackTrace();     

       } catch (ClassNotFoundException e) {   

         e.printStackTrace();      

      } catch (NoSuchMethodException e) {     

         e.printStackTrace();      

      } catch (InvocationTargetException e) {    

        e.printStackTrace();     

       } catch (InstantiationException e) {         

        e.printStackTrace();       

     }

    }

我们从apkPath读取文件加载(本例中拷贝到sdcard,实际开发中最好拷贝到私有目录,防止被注入)。


最后我们来再 onCreate 方法中调用  loadApk :


    @Override

    protected void onCreate(Bundle savedInstanceState) {       

     super.onCreate(savedInstanceState);    

     setContentView(R.layout.activity_main);  

      String apkPath = Environment.getExternalStorageDirectory() + "/bundle.apk";    loadApk(apkPath);

    }  

    

编译 bundle 工程,然后把边缘后的 apk 文件拷贝到测试机的 sdcard 目录下,更名为 bundle.apk。 然后运行宿主 apk 验证结果。

Demo源码

下载源码:[https://github.com/liuguangli/DexClassLoaderDemo](https://github.com/liuguangli/DexClassLoaderDemo)

下篇文章研究:[如何加载插件中的资源](http://www.jianshu.com/p/c8c03bdd11e3)

目录
相关文章
|
7月前
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
293 64
|
7月前
|
存储 Android开发 数据安全/隐私保护
如何在Android设备上撤销Flutter应用程序的所有权限?
如何在Android设备上撤销Flutter应用程序的所有权限?
390 64
|
7月前
|
缓存 Android开发 开发者
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
1134 62
|
7月前
|
开发工具 Android开发 开发者
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
381 61
|
9月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
562 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
9月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
245 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
11月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
279 14
|
11月前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
198 13
|
11月前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
11月前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
210 0

热门文章

最新文章