android 65535 多dex文件方案
来源:互联网 发布:协同过滤推荐算法实例 编辑:程序博客网 时间:2024/06/04 18:03
快过年了,项目进度放换了,看android 热修复方案的时候,顺便把多dex拆分方案,看了一下。
1.前提执行备案
方案需要大家了解只是:
1.ant编译android项目
step 1: 下载安装
2.android 编译apk过程
大概流程:
step 1. 收集所有的java文件,包括:R.java(通过android aapt生成),.java文件,.aidl文件(通过android AIDL 工具生成)
step 2.将生成的java文件,调用javac编译为.class文件
step 3.执行代码混淆
step 4.将所有的.class文件,通过android dex工具,打包为一个.dex文件()。
step 5. 将res,asset,dex,打包为apk
step 6. 签名
以上是android apk编译的大概流程。
2. 拆分dex原理:
3.实现方案
整体方案如下:
下面进入主题:
<!-- 拆分dex,从build_apk.xml移动到这里 -->
<propertyname="out.dir"value="bin"/>
<propertyname="out.absolute.dir"location="${out.dir}"/>
<propertyname="asset.dir"value="assets"/>
<propertyname="asset.absolute.dir"location="${asset.dir}"/>
<!-- 代码混淆后执行 -->
<target name="-post-obfuscate"/>
<!-- add by shehonghao ,拆分dex文件,结束-->
<!-- 代码混淆结束后,开始拆封class文件 -->
<!-- add by shehonghao,拆分dex文件,结束-->
<!-- 打包dex后执行 -->
<target name="-post-dex" />
<!-- 创建资源后执行 -->
<target name="-pre-crunch"></target>
<!-- add by shehonghao ,拆分dex文件,结束-->
F.找到: <macrodef name="dex-helper">,在<dex executalbe="${ds}的之后添加:
step 3: 创建多拆分包build_multi.xml,并在build.xml中引入:
文件内容:
<?xmlversion="1.0"encoding="UTF-8"?>
<project
name="MultiDemo_"
default="help">
<!-- 不需要修改的 开始 -->
<!-- dex在asset目录中的位置, -->
<propertyname="dex.asset.dir"value="dex"/>
<!-- aseent/dex目录中 -->
<propertyname="mulite.abs.dir"value="${asset.absolute.dir}/${dex.asset.dir}"/>
<!-- 不需要修改的 结束 -->
<!-- 拆分dex 1 -->
<!-- dex在dex.asset.dir文件夹中的文件名称 -->
<propertyname="dex.file.name1"value="classes1"></property>
<!-- 保存被拆分出来的class文件的路径-->
<propertyname="out.multi.classes.absolute.dir1"location="${out.dir}/${dex.file.name1}"/>
<!-- 编译后,生成的dex文件的绝对路径,包含文件名 -->
<propertyname="intermediate.dex.file1"location="${out.absolute.dir}/${dex.file.name1}.dex"/>
<!-- 拆分dex 2 -->
<propertyname="dex.file.name2"value="classes2"></property>
<!-- 保存被拆分出来的class文件的路径-->
<propertyname="out.multi.classes.absolute.dir2"location="${out.dir}/${dex.file.name2}"/>
<!-- 编译后,生成的dex文件的绝对路径,包含文件名 -->
<propertyname="intermediate.dex.file2"location="${out.absolute.dir}/${dex.file.name2}.dex"/>
<!-- 创建保存拆分class文件的路径,每个dex文件需要一个路径 , 需要修改 -->
<targetname="-init">
<!-- 创建第一个需要被拆分的文件路径 -->
<mkdirdir="${out.multi.classes.absolute.dir1}"></mkdir>
<mkdirdir="${out.multi.classes.absolute.dir2}"></mkdir>
</target>
<!-- 代码混淆后执行移动class文件策略,不需要修改 -->
<targetname="-post-obfuscate" depends="-init">
<!-- 将需要拆分的class文件,移动到相应的路径中 -->
<antcalltarget="-move-mulit-class"></antcall>
</target>
<!-- 移动class文件,不需要修改 -->
<macrodefname="move-class">
<attributename="srcDir"description="源class做在的相对路径,bin/目录开始"></attribute>
<attributename="disDir"description="目标class做在的相对路径,bin/目录开始"></attribute>
<sequential>
<if>
<condition>
<and>
<lengthstring="@{srcDir}" trim="true" when="greater"length="0" />
</and>
<and>
<lengthstring="@{disDir}" trim="true" when="greater"length="0" />
</and>
</condition>
<then>
<movefile="@{srcDir}" todir="@{disDir}" ></move>
</then>
<else>
<echo> 为设置远文件,或目标文件</echo>
</else>
</if>
</sequential>
</macrodef>
<!-- 移动需要拆分的class文件 ,需要修改-->
<targetname="-move-mulit-class">
<!-- 将所有需要拆封在一个dex文件中的class移动一个文件夹中 -->
<move-classsrcDir="${out.dir}/classes/com/multi/dex1"disDir="${out.multi.classes.absolute.dir1}/com/multi/"></move-class>
<!-- dex 2 中包含的class文件 -->
<move-classsrcDir="${out.dir}/classes/com/multi/dex2"disDir="${out.multi.classes.absolute.dir2}/com/multi/"></move-class>
</target>
<!-- 主dex编译结束后,编译拆分的dex,需要修改 -->
<targetname="-post-dex">
<!--打包第一个被拆分dex文件 -->
<echo>编译拆分dex 1</echo>
<dex executable="${dx}"
output="${intermediate.dex.file1}"
nolocals="@{nolocals}"
forceJumbo="${dex.force.jumbo}"
disableDexMerger="${dex.disable.merger}"
verbose="${verbose}">
<pathpath="${out.multi.classes.absolute.dir1}"/>
</dex>
<!-- 打包第二个被拆分的dex文件 -->
<echo>编译拆分dex 2</echo>
<dex executable="${dx}"
output="${intermediate.dex.file2}"
nolocals="@{nolocals}"
forceJumbo="${dex.force.jumbo}"
disableDexMerger="${dex.disable.merger}"
verbose="${verbose}">
<pathpath="${out.multi.classes.absolute.dir2}"/>
</dex>
</target>
<!-- 将分拆的dex文件,复制到assents/dex目录,需要修改 -->
<targetname="-pre-crunch">
<!-- copy dex1 -->
<echo>复制拆分dex 1</echo>
<movefile="${intermediate.dex.file1}"todir="${mulite.abs.dir}"></move>
<!-- copy dex2 -->
<echo>复制拆分dex 2</echo>
<movefile="${intermediate.dex.file2}"todir="${mulite.abs.dir}"></move>
</target>
<!-- 编译结束,删除压缩的dex文件, 需要修改-->
<targetname="-post-build">
<!-- 删除dex1 -->
<deletefile="${mulite.abs.dir}/${dex.file.name1}.dex"></delete>
<!-- 删除dex2 -->
<deletefile="${mulite.abs.dir}/${dex.file.name2}.dex"></delete>
</target>
</project>
通过项目三步,编译好的apk的asset/dex目录下,就会存在被拆分出来的dex文件。
最后一步,将拆分出来的dex文件添加到主classload中
/**
* 加载 指定dex到内存中
*
* @param context
* @param dexPath
* @param pathClassLoader
* @return
*/
private Object loadDex(Context context, String dexPath, PathClassLoader pathClassLoader) {
// 加载指定路径的dex文件
DexClassLoader dexClassLoader =
new DexClassLoader(dexPath, context.getDir("dex", 0).getAbsolutePath(), dexPath, pathClassLoader);
// 反射获取DexClasLoader的pathList属性
Object classLoaderPathList = getPathListByReflect(dexClassLoader);
if (classLoaderPathList == null) {
if (is_debug) {
Log.e(TAG, "路径--》" + dexPath + " 加载到任何的class,请确认文件格式是否正确");
}
return null;
}
// 反射获取dalvik.system.DexPathList的dexElements熟悉
return getDexElementsByReflect(classLoaderPathList);
}
3.将所有的dex,合并为一个数组,然后通过反射设置给主classloader。这样就完成,代码如下:
// 合并所有的dex文件
Object array = createObjectTypeArray(allDexElements[0].getClass(), dexNum);
Object[] list = (Object[]) array;
dexNum = 0;
for (int i = 0; i < allDexElements.length; i++) {
if (allDexElements[i] != null) {
elementList = (Object[]) allDexElements[i];
System.arraycopy(elementList, 0, list, dexNum, elementList.length);
dexNum = dexNum + elementList.length;
}
}
Object pathList = getPathListByReflect(pathClassLoader);
//
setFieldByReflect(pathList, pathList.getClass(), "dexElements", list);
具体可以参考源码:
源码代码
- android 65535 多dex文件方案
- Android dex分包方案 (多dex)
- Android dex分包方案 (多dex)
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex 分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- 过滤器(当前登录人的信息(session过期时)进行重新登录)
- 生成openfpyxl html格式帮助文档
- Linux:C/Socket多路复用select
- NSURLSession使用说明及后台工作流程分析
- EventBus猜想 ----手把手带你自己实现一个EventBus
- android 65535 多dex文件方案
- spring mvc+ mybaties+ehcache(maven工程),在mapper.xml中使用
- zookeeper应用场景练习(分布式锁)
- CLLocationCoordinate2D 初始化
- Angular的作用域Scope理解
- Redis 实例: 集群
- php中必须表单
- spring mvc+ mybaties+ehcache(maven工程),在service层中使用
- unity5中AssetBundle相关