Moosphan/Android-Daily-Interview

2019-09-19:谈谈安卓apk构建的流程?

MoJieBlog opened this issue · 7 comments

其他问法

  • 如何从我们看到的代码,打包成apk?
  • 点击as的run app,as帮我们做了哪些工作?

之前AS坏了,突发奇想自己用cmd控制aapt,javac等生成了一个apk,下面讲下我理解的编译过程

  1. 使用aapt处理资源文件,如编译AndroidManifest.xml,编译生成resources.arsc,生成R.java等

  2. 使用javac等工具编译java文件,生成class格式文件

  3. 使用dx等工具将.class和项目依赖的jar编译成.dex

  4. 将生成的这些文件压缩进一个zip中

  5. 签名

这只是最简单的过程,实际还会涉及到multidex,使用如proguard的工具处理生成的字节码,需要依赖aar文件,需要编译kotlin,使用jack,使用jni,使用d8/r8等情况~

1) aapt 为res 目录下资源生成R.java 文件,同时为AndroidMainfest.xml 生成Mainfeset.java文件
2)aidl 将项目中自定义的aidl 生成相应的Java文件
3) javac 将项目中所有java 代码编译成class 文件,包括 业务逻辑代码, aapt 生成 java文件,aidl 生成java 文件
4) proguard , 混淆同时生成mapping.txt ,这步可选
5) 将所有class 文件(包括第三方class 文件) 转换为dex 文件
6)aapt 打包, 将res资源,assets资源,打包成一个.ap_的文件
7)apkbuilder ,将所有dex 文件,.ap_文件, AndroidMainfest.xml打包为.apk 文件,这是一个未签名的apk包
8)jarsigner 对apk 进行签名
9)ziplign 对apk 进行对齐操作,以便运行时节约内存。

1) aapt 为res 目录下资源生成R.java 文件,同时为AndroidMainfest.xml 生成Mainfeset.java文件
2)aidl 将项目中自定义的aidl 生成相应的Java文件
3) javac 将项目中所有java 代码编译成class 文件,包括 业务逻辑代码, aapt 生成 java文件,aidl 生成java 文件
4) proguard , 混淆同时生成mapping.txt ,这步可选
5) 将所有class 文件(包括第三方class 文件) 转换为dex 文件
6)aapt 打包, 将res资源,assets资源,打包成一个.ap_的文件
7)apkbuilder ,将所有dex 文件,.ap_文件, AndroidMainfest.xml打包为.apk 文件,这是一个未签名的apk包
8)jarsigner 对apk 进行签名
9)ziplign 对apk 进行对齐操作,以便运行时节约内存。

关于9,补充下。我在网上看到好多说对齐操作的,这里说下我的理解,这里说的节约内存并不是节约apk的物理内存。而是app运行内存。在Android中,当资源文件通过内存映射对齐到4字节边界时,访问资源文件的代码才是有效率的。但是,如果资源本身没有进行对齐处理(未使用zipalign工具),就必须显式地读取它们,这个过程将会比较缓慢且会花费额外的内存。

可以明确一点,对齐主要是为了提高读取资源的效率。

ukyo6 commented

1) aapt 为res 目录下资源生成R.java 文件,同时为AndroidMainfest.xml 生成Mainfeset.java文件
2)aidl 将项目中自定义的aidl 生成相应的Java文件
3) javac 将项目中所有java 代码编译成class 文件,包括 业务逻辑代码, aapt 生成 java文件,aidl 生成java 文件
4) proguard , 混淆同时生成mapping.txt ,这步可选
5) 将所有class 文件(包括第三方class 文件) 转换为dex 文件
6)aapt 打包, 将res资源,assets资源,打包成一个.ap_的文件
7)apkbuilder ,将所有dex 文件,.ap_文件, AndroidMainfest.xml打包为.apk 文件,这是一个未签名的apk包
8)jarsigner 对apk 进行签名
9)ziplign 对apk 进行对齐操作,以便运行时节约内存。

关于9,补充下。我在网上看到好多说对齐操作的,这里说下我的理解,这里说的节约内存并不是节约apk的物理内存。而是app运行内存。在Android中,当资源文件通过内存映射对齐到4字节边界时,访问资源文件的代码才是有效率的。但是,如果资源本身没有进行对齐处理(未使用zipalign工具),就必须显式地读取它们,这个过程将会比较缓慢且会花费额外的内存。

可以明确一点,对齐主要是为了提高读取资源的效率。

是的,只是为了寄存器整读,和节约内存没关系

1.aapt 生成R.java mainfest.java
2.生成aidl的java
3.javac 编译所有的java文件生成 .class文件
4.把class生成dex文件
5.混淆
6.把资源文件打包
7.apkbuilder把上述dex和 资源文件 打包成apk
8.jarsinger 签名
9.zipaligin 对齐

yline commented
    1-1,「appt」将资源文件,编译成R.java文件<br>
    1-2,「aidl」将 .aidl接口,转换成 .java接口<br>
    1-3,「javac」将 java文件、R.java文件、.java接口,编译成.class文件<br>

    2-1,「dex」将 项目编译的.class、三方.class,转换成 .dex文件<br>

    3-1,「apk builder」将.dex文件、图片资源、assets资源打包成.apk文件<br>

    4-1,「jarsigner」将.apk文件进行签名<br>

    5-1,「zipalign」对齐.apk文件,增大内存开销,提高运行速度<br><br>

    .java -> .class -> .dex -> .apk -> 签名+对齐<br>
    <br>
  1. aapt工具将res中的资源生成 R.java文件和resources.arsc文件;
  2. 如果有aidl,那么aidl工具会将aidl接口转化为java类;
  3. javac将所有的java类编译为class文件;
  4. 如果有代码混淆,则会加入代码混淆;
  5. dx.bat将所有的class文件转化为classes.dex文件;
  6. ApkBuild将所有的资源(assets、so、jni)、resources.arcs以及上一步生成的dex文件,打包生成一个apk文件;
  7. 对上一步生成的apk进行签名;
  8. 使用Zipalign对签名后的apk进行优化。