参考文档:https://developer.android.google.cn/studio/build/multidex.html#keep
1、由文档中可以知道 了解到 在Android5.0之前我们使用的是Dalvik虚拟机,默认情况下,Dalvik 限制应用的每个 APK 只能使用单个 classes.dex
字节码文件。要想绕过这一限制,您可以使用 Dalvik 可执行文件分包支持库,它会成为您的应用主要 DEX 文件的一部分,然后管理对其他 DEX 文件及其所包含代码的访问。
当然,当5.0以后,Android 5.0(API 级别 21)及更高版本使用名为 ART 虚拟机的运行时,后者原生支持从 APK 文件加载多个 DEX 文件。ART 在应用安装时执行预编译,扫描 classesN.dex
文件,并将它们编译成单个 .oat
文件,供 Android 设备执行。因此,如果您的 minSdkVersion
为 21 或更高值,则不需要 Dalvik 可执行文件分包支持库。
由于我们现在应用基本都在5.0以后的版本,所以大都支持多dex分包支持了,但是也会有一些其它的设备,比如智能家居等有使用低版本的时候,可能会遇到64K的问题,为了正常使用多分包功能,可以参考上面的文档中介绍的如下方式:
修改模块级 build.gradle
文件以启用 Dalvik 可执行文件分包,并将 Dalvik 可执行文件分包库添加为依赖项,如此处所示:
android {
defaultConfig {
...
minSdkVersion 15
targetSdkVersion 28
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.3'
}
2、我们一般的apk是这样的,直接打开apk是可以看到里面的源码的,如下图所示
这样对大家来说就不安全,我们所要做的就是把我们的apk中的dex文件加密,让别人就算拿到我们的apk里面啥也看不到。如下图所示,点击加密之后的apk,里面啥也没有,一个代码都看不到,这就是我们要做的:
2、具体怎么做呢?请看下图介绍
上图中左边是我们未加密的apk打开之后显示的文件结构,我们需要一个proxy代理application 以及一个 加密所用的Tools ,用tools来给左边的两个dex进行加密,然后在把加密之后的文件和左边其它的文件一起打包成apk 这样别人就看不到我们的源码了,但是新的文件的dex文件用户是无法运行的,这个时候,我们就需要一个proxy 的application,把我们新打包的apk所有内容交给代理application,然后让代理application去和Android系统对接,因为系统可以加载dex文件的,所以这个时候,我们的代理application要做的就是把拿到的加密的apk中的dex文件进行解密,然后在交给系统处理。
3、我们要先了解自己写的代码是如何被加载到内存的,可以在MainActivity中用以下代码查看:
Log.d("wwy",getClassLoader().toString()); 经过运行发现打印信息为:dalvik.system.PathClassLoader
我们在系统源码中查找这个PathClassLoader ,查看父类 BaseDexClassLoader:
我们通过Android系统源码找到 PathClassLoader 类 ------> BaseDexClassLoader -----> findClass()方法 -----> pathList.findClass() 方法 ,接着查看 pathList 类中都是什么,发现这个类中的方法 就是 findClass(String name,List<Throwable> suppressed) ;它通过循环遍历DexFile ,其实这就是获取dex文件,其实系统所有的dex文件都是要经过这里处理的
所以关键来了,既然所有的dex文件都是通过这里处理,也就是 dexElements , 它本身就是一个数组,我们只需要通过反射拿到这个数组,接着我们通过代码把我们自己的解密之后的dex文件放到我们定义的一个数组中,然后把我们的数组和系统的dex文件数组合并在一起,交给系统去处理。
这里我们在看系统的dex文件数组 dexElements 是怎么初始化的呢?通过查看系统源码,发现如下,
那么我们通过反射拿到这个方法,就可以拿到系统的dex文件数组了,然后再把我们的数据和系统合并后在赋给系统里面的dexElements 这样就把dexElements更新后,这样我们的dex文件就加载到android里面运行了。
好了具体的思路上面就介绍到这里,下面开始实现这个功能。
4、我们新建一个android project ,然后,在项目里面Create New Module 选择 Android Library ,这就是给我们代理的application ,命名为:proxy_core ;然后还需要一个加密工具,在项目中 Create New Module 选择 Java Library 这个java library不需要我们运行时处理,它直接在我们编译的时候就进行加密,这就是为什么创建的是java library ,这命名为:proxy_tools 建好之后,记得把这个proxy_tools 添加到项目中,如下:
添加编译完之后,在app的build.gradle中会自动如下所示:
好了,下面就开始写代码了!
具体的在下个博客中详细介绍。先下班了!哈哈。。。 代码用到的三个工具类请在移步:https://download.csdn.net/download/i123456789t/11239056
具体代码实现请看下一篇:https://blog.csdn.net/I123456789T/article/details/91819275