AndroidStudio 构建应用过程

一、前言

Android Studio 选择Gradle构建应用,负责了从工程资源管理到最终编译、测试、打包、发布的几乎所有工作。在Android Studio中点击运行按钮后,会编译整个项目并将apk安装到手机上。在这个过程中,Gradle 和 Android Plugin for Gradle做了大量工作。整个过程就是Gradle执行一系列task的过程。

提示:命令行中gradle是在配置了Gradle环境后使用,如果没有环境请替换为gradlew

二、Android 项目的Gradle结构

Gradle中,每一个待编译的工程都叫一个Project。每一个Project在构建的时候都包含一系列的Task,Task里有需要执行的函数(代码块)。一个Project到底包含多少个Task,其实是由编译脚本指定的插件决定。插件是什么呢?插件就是用来定义Task,并具体执行这些Task的东西。

Gradle是一个框架,作为框架,它负责定义流程和规则。而具体的编译工作则是通过插件的方式来完成的。比如编译Java有Java插件,编译Groovy有Groovy插件,编译Android APP有Android APP插件,编译Android Library有Android Library插件。

在编译过程中, Gradle 会根据 build 相关文件,聚合所有的project和task,执行task 中的 action。因为 build.gradle文件中的task非常多,先执行哪个后执行那个需要一种逻辑来保证。这种逻辑就是依赖逻辑,几乎所有的Task 都需要依赖其他 task 来执行,没有被依赖的task 会首先被执行。所以到最后所有的 Task 会构成一个 有向无环图(DAG Directed Acyclic Graph)的数据结构。

编译过程分为三个阶段:

  • 初始化阶段:创建 Project 对象,如果有多个build.gradle,也会创建多个project。
  • 配置阶段:在这个阶段,会执行所有的编译脚本,同时还会创建project的所有的task,为后一个阶段做准备。
  • 执行阶段:在这个阶段,gradle 会根据传入的参数决定如何执行这些task,真正action的执行代码就在这里。

Android工程是一个Multi-Projects。因此会拥有两个及以上的build.gradle文件,除了每个module拥有以外,还会有一个全局的build.gradle文件(如图1)。

1.文件作用说明

①gradle.properties:配置文件
②settings.gradle:最常用的功能就是标识给Gradle这个项目包含哪些子project,除此之外还可以设置一些函数,在构建时候执行。
③gradle-wrapper.properties:保证用户在没有安装Gradle环境时候也可以构建Android项目。
④项目的全局build.gradle:

buildscript {                    //配置下载各种插件仓库以及详细路径和版本          
    repositories {               //仓库
        google()
        jcenter()
    }
    dependencies {               //依赖         
        classpath 'com.android.tools.build:gradle:3.0.1'//分为groupId、artifactId、version

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {                    //为所有module(gradle的project)统一配置    
    repositories {      
        google()
        jcenter()
    }
}

task clean(type: Delete) {        //可以额外设置一些task 
    delete rootProject.buildDir
}

gradle项目结构 图1
module的build.gradle

apply plugin: 'com.android.application'              //把当前Android plugin应用到这个project(module)中
android {
    compileSdkVersion 26                             //编译版本
    defaultConfig {                                  //定义了不同编译类型或不同渠道包的共享属性
        applicationId "org.gradle.helloworldgradle"  //项目的唯一标识
        minSdkVersion 19                             //项目支持的最低Android API版本
        targetSdkVersion 26                          //项目的目标Android API版本
        versionCode 1                                //版本号
        versionName "1.0"                            //版本名称
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"//配置单元测试
    }
    buildTypes {                                     //编译类型(Android应用默认支持release和debug版本)
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {                                       //应用依赖的各种libraries 
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
2.project(module)结构

新建项目名称为demo,并创建app依赖的新module,叫:customtoolbar,项目结构如图2:
项目结构
①列举3种查看project(module)方式

方式一:如果配置了gradle环境可以运行gradle projects命令,结果为

Root project 'demo'
+--- Project ':app'
\--- Project ':customtoolbar'

方式二:查看settings.gradle

include ':app', ':customtoolbar'

方式三:查看Android Studio右侧的gradle窗口(图3)
这里写图片描述 图3

3.Android tasks

有四个基本的 task, Android 继承他们分别进行了自己的实现:

  • assemble:对所有的 buildType 生成 apk 包。
  • clean:移除所有的编译输出文件,比如apk
  • check:执行lint检测编译。
  • build:同时执行assemble和check命令
  • connectedCheck 这个task将会在一个指定的设备或者模拟器上执行检查,它们可以同时在所有连接的设备上执行。
  • deviceCheck 通过APIs连接远程设备来执行检查,这是在CL服务器上使用的。

这些都是基本的命令,在实际项目中会根据不同的配置,会对这些task 设置不同的依赖。比如 默认的 assmeble 会依赖 assembleDebugassembleRelease,如果直接执行assmeble,最后会编译debug,和release 的所有版本出来。如果我们只需要编译debug 版本,我们可以运行assembleDebug

除此之外还有一些常用的新增的其他命令,比如 install命令,会将编译后的apk 安装到连接的设备。

我们运行的许多命令除了会输出到命令行,还会在build文件夹下生产一份运行报告。比如check命令会生成lint-results.html.在build/outputs中。

①查看project的所有task

方式一:gradle窗口目录打开(图4)
这里写图片描述 图4
方式二:如果配置了gradle环境可以运行gradle :projectName:tasks命令(如gradle :app:tasks
),结果更详细(会有描述信息)

> Task :app:tasks

------------------------------------------------------------
All tasks runnable from project :app
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for each variant.
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assembles all variants of all applications and secondary packages.
assembleAndroidTest - Assembles all the Test applications.
assembleDebug - Assembles all Debug builds.
assembleRelease - Assembles all Release builds.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
clean - Deletes the build directory.
cleanBuildCache - Deletes the build cache directory.
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources
mockableAndroidJar - Creates a version of android.jar that's suitable for unit tests.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':app'.
components - Displays the components produced by project ':app'. [incubating]
dependencies - Displays all dependencies declared in project ':app'.
dependencyInsight - Displays the insight into a specific dependency in project ':app'.
dependentComponents - Displays the dependent components of components in project ':app'. [incubating]
help - Displays a help message.
model - Displays the configuration model of project ':app'. [incubating]
projects - Displays the sub-projects of project ':app'.
properties - Displays the properties of project ':app'.
tasks - Displays the tasks runnable from project ':app'.

Install tasks
-------------
installDebug - Installs the Debug build.
installDebugAndroidTest - Installs the android (on device) tests for the Debug build.
uninstallAll - Uninstall all applications.
uninstallDebug - Uninstalls the Debug build.
uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.
uninstallRelease - Uninstalls the Release build.

Verification tasks
------------------
check - Runs all checks.
connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
connectedCheck - Runs all device checks on currently connected devices.
connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
deviceCheck - Runs all device checks using Device Providers and Test Servers.
lint - Runs lint on all variants.
lintDebug - Runs lint on the Debug build.
lintRelease - Runs lint on the Release build.
lintVitalRelease - Runs lint on just the fatal issues in the release build.
test - Run unit tests for all variants.
testDebugUnitTest - Run unit tests for the debug build.
testReleaseUnitTest - Run unit tests for the release build.

Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL in 0s

②运行task

方式一:gradle窗口中点击相应的task

方式二:命令行中运行gradle taskName,taskName为相应task的名称

③查看Build scan(图5)
在命令行后添加--scan,例如gradle build --scan,得到如下结果

gradle build --scan        //命令行

BUILD SUCCESSFUL in 1s
4 actionable tasks: 4 executed

Do you accept the Gradle Cloud Services license agreement (https://gradle.com/terms-of-service)? [yes, no]                
yes                       //输入yes
Gradle Cloud Services license agreement accepted.

Publishing build scan...
https://gradle.com/s/carzirlfjwjlo//打开该网址,并按提示操作

这里写图片描述 图5

三、Android 编译过程

1.apk编译过程(如下图所示)

这里写图片描述

2.task执行详情点击查看assembleRelease的详细执行过程!!!(非常详细,可根据时间顺序分析)
列出了一部分时间和功能(时间太晚了,抽时间补充上)

Path                                                  Started after     
:app:preBuildUP-TO-DATE                                  0.659s
:customtoolbar:preBuildUP-TO-DATE                        0.660s
:customtoolbar:preReleaseBuildUP-TO-DATE                 0.660s
:customtoolbar:checkReleaseManifestUP-TO-DATE            0.661s
:customtoolbar:processReleaseManifestUP-TO-DATE          0.662s  //编译Android Library的Manifest
:app:preReleaseBuildUP-TO-DATE                           0.664s  
:customtoolbar:compileReleaseAidlUP-TO-DATE              0.712s  //编译Android Library的 AIDL文件
:app:compileReleaseAidlUP-TO-DATE                        0.716s  //编译App的 AIDL文件    
:customtoolbar:packageReleaseRenderscriptNO-SOURCE       0.718s 
:app:compileReleaseRenderscriptUP-TO-DATE                0.719s  /编译App的 Renderscript文件
:app:checkReleaseManifestUP-TO-DATE                      0.721s 
:app:generateReleaseBuildConfigUP-TO-DATE                0.723s 
:app:prepareLintJarUP-TO-DATE                            0.724s 
:app:mainApkListPersistenceReleaseUP-TO-DATE             0.725s
:app:generateReleaseResValuesUP-TO-DATE                  0.726s 
:app:generateReleaseResourcesUP-TO-DATE                  0.726s
:customtoolbar:compileReleaseRenderscriptUP-TO-DATE      0.727s
:customtoolbar:generateReleaseResValuesUP-TO-DATE        0.729s 
:customtoolbar:generateReleaseResourcesUP-TO-DATE        0.729s
:customtoolbar:packageReleaseResourcesUP-TO-DATE         0.730s
:app:mergeReleaseResourcesUP-TO-DATE                     0.733s 
:app:createReleaseCompatibleScreenManifestsUP-TO-DATE    0.771s 
:app:processReleaseManifestUP-TO-DATE                    0.772s
:app:splitsDiscoveryTaskReleaseUP-TO-DATE                0.775s
:customtoolbar:platformAttrExtractorUP-TO-DATE           0.776s
:customtoolbar:generateReleaseRFileUP-TO-DATE            0.777s
:app:processReleaseResourcesUP-TO-DATE                   0.785s 
:app:generateReleaseSourcesUP-TO-DATE                    0.791s
:customtoolbar:generateReleaseBuildConfigUP-TO-DATE      0.791s 
:customtoolbar:generateReleaseSourcesUP-TO-DATE          0.793s
:customtoolbar:javaPreCompileReleaseUP-TO-DATE           0.793s
:customtoolbar:prepareLintJarUP-TO-DATE                  0.793s
:customtoolbar:compileReleaseJavaWithJavacUP-TO-DATE    
:customtoolbar:processReleaseJavaResNO-SOURCE
:customtoolbar:transformClassesAndResourcesWithPrepareIntermediateJarsForReleaseUP-TO-DATE  
:app:javaPreCompileReleaseUP-TO-DATE    
:app:compileReleaseJavaWithJavacUP-TO-DATE
:app:compileReleaseNdkNO-SOURCE
:app:compileReleaseSourcesUP-TO-DATE
:app:lintVitalRelease
:app:mergeReleaseShadersUP-TO-DATE  
:app:compileReleaseShadersUP-TO-DATE    
:app:generateReleaseAssetsUP-TO-DATE
:customtoolbar:mergeReleaseShadersUP-TO-DATE    
:customtoolbar:compileReleaseShadersUP-TO-DATE  
:customtoolbar:generateReleaseAssetsUP-TO-DATE
:customtoolbar:packageReleaseAssetsUP-TO-DATE
:app:mergeReleaseAssetsUP-TO-DATE   
:app:transformClassesWithDexBuilderForReleaseUP-TO-DATE
:app:transformDexArchiveWithExternalLibsDexMergerForReleaseUP-TO-DATE   
:app:transformDexArchiveWithDexMergerForReleaseUP-TO-DATE
:app:mergeReleaseJniLibFoldersUP-TO-DATE
:customtoolbar:compileReleaseNdkNO-SOURCE
:customtoolbar:mergeReleaseJniLibFoldersUP-TO-DATE  
:customtoolbar:transformNativeLibsWithMergeJniLibsForReleaseUP-TO-DATE  
:customtoolbar:transformNativeLibsWithIntermediateJniLibsForReleaseUP-TO-DATE
:app:transformNativeLibsWithMergeJniLibsForReleaseUP-TO-DATE    
:app:processReleaseJavaResNO-SOURCE
:app:transformResourcesWithMergeJavaResForReleaseUP-TO-DATE 
:app:packageReleaseUP-TO-DATE   
:app:assembleRelease    
:customtoolbar:extractReleaseAnnotationsUP-TO-DATE  
:customtoolbar:mergeReleaseConsumerProguardFilesUP-TO-DATE  
:customtoolbar:transformResourcesWithMergeJavaResForReleaseUP-TO-DATE   
:customtoolbar:transformClassesAndResourcesWithSyncLibJarsForReleaseUP-TO-DATE  
:customtoolbar:transformNativeLibsWithSyncJniLibsForReleaseUP-TO-DATE   
:customtoolbar:bundleReleaseUP-TO-DATE  
:customtoolbar:compileReleaseSourcesUP-TO-DATE
:customtoolbar:mergeReleaseResourcesUP-TO-DATE  
:customtoolbar:verifyReleaseResourcesUP-TO-DATE 
:customtoolbar:assembleReleaseUP-TO-DATE

3.编译过程概括

①资源合并
- 合并Manifest文件,生成Merged Manifest(使用Manifest Merger插件)
- 合并Resources文件,生成Merged Resources(使用Resource Merger插件)
- 合并Assests文件,生成Merged Assests(使用Assest Merger插件)

②打包资源文件,生成R.javaCompiled Resources(使用aapt构建工具)
③将.aidl文件处理成.java文件(使用aidl构建工具)
④将java文件(R.java、aidl处理过的.java以及java代码)编译为.class文件(使用JDK中的javac工具)
⑤将④中的.class文件和三方库中的.class文件生成混淆的.jar文件(使用proguard插件)
⑥将.jar文件打包成.dex文件(使用dex构建工具)
⑦将Compiled Resources、项目中的Resources和.dex文件打包生成未签名的.apk文件(使用apkbuilder插件)
⑧用keystore文件进行签名(使用JDK中的Jarsigner工具)
⑨优化apk(使用zipalign 构建工具)

提示

  1. 上述构建工具位于SDK中的/build-tools目录中
  2. 上述JDK工具位于其JDK路径中的/bin目录中
  3. 上述其他插件位于SDK中的/tools目录中

四、参考文献

猜你喜欢

转载自blog.csdn.net/jq_motee/article/details/80780075
今日推荐