之前我们写过关于gradle分包的文章,它依靠MultiDex实现,主要用于AndroidStudio开发。而Ant分包一般用于Eclipse开发,通过改写编译脚本命令实现分包。
Ant分包实现步骤
- 下载Ant,如果eclipse里面有集成的就忽略。
- 通过Ant命令编译android工程,编译完成后会生成一个build.xml
- 自定义一个custom_rules.xml文件,通过改写target命令,实现分包
这里就不贴出代码部分,大家可以参考github上的一个开源项目Dex65535,它的实现原理就是通过改写custom_rules.xml文件来实现分包的。
Ant分包原理浅析
编译android程序时,build编译脚本运行流程为:
其中,target name=”-post-compile”这一步就是编译过程,所以我们可以在custom_rules.xml中配置我们想要实现的功能。配置语法大家参考Dex65535项目中的custom_rules.xml。配置完成后,编译工程时,build.xml脚本就会调用我们自定义的custom_rules.xml文件,然后就会执行我们的分包命令,实现分dex。
Ant分包之动态加载dex
Ant分包中动态加载dex的基本原理是通过反射,将DexClassLoader设置为PathClassLoader的父类加载器,这样在加载的时候就会调用DexClassLoader去加载分dex了。下面贴出我的实现方法:
/**
* 动态加载分dex
*/
private void install(){
//1.创建dex目录
File dexDir = new File(getFilesDir()+"dex");
if (dexDir != null && !dexDir.exists()){
dexDir.mkdir();
}
//2.创建odex目录
File odexDir = new File(getFilesDir()+"odex");
if (odexDir != null && !odexDir.exists()){
odexDir.mkdir();
}
//3.将分包编译后的dex拷贝到dexDir(即拷贝Assets目录下的libs.apk)
File dexFile = new File(dexDir,"libs.apk");
InputStream in = null;
OutputStream out = null;
int len = -1;
byte[] m = new byte[1024];
try {
in = getAssets().open("libs.apk");
out = new FileOutputStream(dexFile);
while((len = in.read(m)) != -1){
out.write(m,0,len);
}
if (in != null){
in.close();
}
if (out != null){
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
//获取Application的类加载器
ClassLoader loader = getClassLoader();
//将loader的父加载器设置为DexClassLoader的父加载器
DexClassLoader dexClassLoader = new DexClassLoader(dexFile.getAbsolutePath(),odexDir.getAbsolutePath(),null,loader.getParent());
//通过反射将DexClassLoader设置为loader的父加载器
try {
Field fieldParent = ClassLoader.class.getDeclaredField("parent");
if (fieldParent != null){
fieldParent.setAccessible(true);
fieldParent.set(loader,dexClassLoader);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Ant分包与gradle分包的区别
Ant分包:
- 优点:可以指定哪些类放入分dex
- 缺点: 分 dex 不能混淆;
如果分dex中引用了主dex中的类,那么次方法失效
Gradle分包:
- 优点:使用简单,只需要简单的配置;
分dex可以混淆 - 缺点:无法手动指定哪些类放入分dex