Android Studio 的 build 过程

 

如图,html

  • 编译器源代码(包括 Application Module 及其所依赖的全部 Library 源代码)转换成 DEXDalvik Executable)文件(其中包括运行在 Android 设备上的字节码),将全部其余内容转换成已编译资源。(
    • 源代码(包括 Application Module 和 Library Module)编译成 class 文件,再将全部的 class 文件(包括第三方库中)打包生成 dex 文件。
    • 解压全部 aar 包中的资源文件,并和项目中全部资源文件合并到一个目录。
    • 生成资源文件的索引文件。
  • APK 打包器DEX 文件和已编译资源打包生成单个 APK。不过,必须先对 APK 签名,才能将应用安装并部署到 Android 设备上。
  • APK 打包器使用 Debug 或 Release 密钥库对 APK 签名
    • 若是您构建的是 Debug 版本的应用(即专用于测试和分析的应用),打包器会使用 Debug 密钥库签名应用。Android Studio 自动使用 Debug 密钥库配置新项目。
    • 若是您构建的是打算向外发布的 Release 版本应用,打包器会使用 Release 密钥库签名应用。
  • 在生成最终 APK 以前,打包器会使用 zipalign 工具对应用进行优化减小其在设备上运行时的内存占用

 

2. Gradle 构建 tasks 说明

咱们经过 Android Studio 的 build -> Build APK 功能来看下, build 过程当中是怎样的。 Build APK 会执行如下 Gradle task。 ( 注:这里是用 Debug 模式作例子, Release 模式时只需将 task 中的 Debug 替换成 Release 理解便可)

Executing tasks: [:app:assembleDebug]

:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:compileDebugAidl UP-TO-DATE
:app:compileDebugRenderscript UP-TO-DATE
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources UP-TO-DATE
:app:mergeDebugResources UP-TO-DATE
:app:transformDataBindingBaseClassLogWithDataBindingMergeGenClassesForDebug UP-TO-DATE
:app:dataBindingGenBaseClassesDebug UP-TO-DATE
:app:checkDebugManifest UP-TO-DATE
:app:generateDebugBuildConfig UP-TO-DATE
:app:prepareLintJar UP-TO-DATE
:app:mainApkListPersistenceDebug UP-TO-DATE
:app:createDebugCompatibleScreenManifests UP-TO-DATE
:app:processDebugManifest
:app:splitsDiscoveryTaskDebug UP-TO-DATE
:app:processDebugResources
:app:generateDebugSources
:app:dataBindingExportBuildInfoDebug
:app:javaPreCompileDebug UP-TO-DATE
:app:transformDataBindingWithDataBindingMergeArtifactsForDebug UP-TO-DATE
:app:compileDebugJavaWithJavac
:app:compileDebugNdk NO-SOURCE
:app:compileDebugSources
:app:mergeDebugShaders UP-TO-DATE
:app:compileDebugShaders UP-TO-DATE
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets UP-TO-DATE
:app:transformClassesWithDexBuilderForDebug
:app:transformDexArchiveWithExternalLibsDexMergerForDebug
:app:transformDexArchiveWithDexMergerForDebug
:app:mergeDebugJniLibFolders UP-TO-DATE
:app:transformNativeLibsWithMergeJniLibsForDebug UP-TO-DATE
:app:processDebugJavaRes NO-SOURCE
:app:transformResourcesWithMergeJavaResForDebug UP-TO-DATE
:app:validateSigningDebug UP-TO-DATE
:app:packageDebug
:app:assembleDebug


BUILD SUCCESSFUL in 20s
特别说明:因为 Gradle 会尝试经过不重复执行输入未发生变化的 task 来节省时间(这些 task 被标记为 UP-TO-DATE,如上所示)
因此第一次编译运行会比较久,然后面就不会了。

  

上面列出来的 Gradle 构建过程,大体可分为五个阶段java

  1. Preparation of dependecies 在这个阶段 Gradle 检测 Module 依赖的全部 library 是否 ready。若是这个 Module 依赖于另外一个 Module ,则另外一个 Module 也要被编译。
  2. Merging resources and processing Manifest 打包资源Manifest 文件。
  3. Compiling 在这个阶段处理编译器的注解源码被编译成字节码
  4. Postprocessing 全部带 transform 前缀的 task 都是这个阶段进行处理的。
  5. Packaging and publishing 这个阶段 library 生成.aar文件,Application 生成.apk文件。

这五个阶段和上面的构建过程当中 task 的时序有大体的对应关系,你们能够相互映照着理解。android

为了便于你们理解,下面给出一些关键 task 的说明:git

  • mergeDebugResources 解压全部的 aar 包输出到app/build/intermediates/exploded-aar,而且把全部的资源文件合并到app/build/intermediates/res/merged/debug目录里。github

  • processDebugManifest 把全部 aar 包里的AndroidManifest.xml中的节点,合并到项目的AndroidManifest.xml中,并根据app/build.gradle中当前buildType 的 manifestPlaceholders配置内容替换 manifest 文件中的占位符,最后输出到app/build/intermediates/manifests/full/debug/AndroidManifest.xmlapi

  • processDebugResourcesapp

    1. 调用 aapt 生成项目和全部 aar 依赖的R.java,输出到app/build/generated/source/r/debug目录;
    2. 生成资源索引文件app/build/intermediates/res/debug/resources-debug.ap_
    3. 符号表输出到app/build/intermediates/symbols/debug/R.txt
  • compileDebugJavaWithJavac 用来把 java 文件编译成 class 文件,输出的路径是app/build/intermediates/classes/debugide

    编译的输入目录有工具

    • 项目源码目录,默认路径是app/src/main/java,能够经过 sourceSetsdsl 配置,容许有多个(打印project.android.sourceSets.main.java.srcDirs能够查看当前全部的源码路径,具体配置能够参考 android-doc,以及这里
    • app/build/generated/source/aidl
    • app/build/generated/source/buildConfig
    • app/build/generated/source/apt(继承javax.annotation.processing.AbstractProcessor作动态代码生成的一些库,输出在这个目录)的代码。
  • transformClassesWithMultidexlistForDebug这个任务在使用 Multidex 才会出现)它有两个做用测试

    • 扫描项目的AndroidManifest.xml文件和分析类之间的依赖关系,计算出那些类必须放在第一个 dex 里面,最后把分析的结果写到app/build/intermediates/multi-dex/debug/maindexlist.txt文件里面
    • 生成混淆配置项输出到app/build/intermediates/multi-dex/debug/manifest_keep.txt文件里

    项目里的代码入口是 manifestapplication 节点的属性 android.name 配置的继承自 Application 的类,在 Android 5.0 之前的版本系统只会加载一个 dex(classes.dex),classes2.dex .......classesN.dex 通常是使用android.support.multidex.MultiDex加载的,因此若是入口的 Application 类不在 classes.dex5.0 如下确定会挂掉,另外当入口 Application 依赖的类不在 classes.dex 时初始化的时候也会由于类找不到而挂掉,还有若是混淆的时候类名变掉了也会由于对应不了而挂掉,综上所述就是这个任务的做用。

相关文章
相关标签/搜索