简介
Android构建流程是指将Android源代码转换成Apk(Android Application Package)这一过程,里面涉及到许多步骤和工具。构建流程由Gradle和Android Gradle Plugin插件来管理,既可以通过IDE方式,也可以通过命令行方式来进行。
构建流程
官网有一个简单的流程图,比较简略,图中主要展示了两步,且都是由Gradle和Andorid插件管理的:
- 编译。编译器将源代码编译成DEX文件和供前者直接使用的资源文件。
- 打包并签名。将上述DEX文件和资源文件合并成APK,之后进行签名生成最终可以用于安装、测试或发布的APK。
在许多博客中,都提到一个详细的流程图,说是来自官网,但我没有找到,可能以前存在,现在已经删除了,如下:
上述流程分为七个步骤,涉及许多工具,如AAPT、AIDL等,有些工具现在已经升级或改变名称了,如AAPT现在升级为AAPT2。
AAPT等工具位于{Android SDK}/build-tools/{版本号}。
七个步骤具体如下:
1. 编译资源文件
利用aapt
编译资源文件生成R.java
和resources.arsc
# R.java
$ aapt p -f -m -J app/out/R \
-M app/src/main/AndroidManifest.xml \
-S app/src/main/res \
-I $SDK/platforms/android-28/android.jar
# 生成包含resources.arsc的apk,之后添加dex文件
$ aapt p -f -F app/out/res/resource.apk \
-M app/src/main/AndroidManifest.xml \
-S app/src/main/res \
-I $SDK/platforms/android-28/android.jar
说明:
- 上面的示例工程是利用Android Studio生成的,并去掉了自动引入的第三方依赖。
- 需要生成必要的文件夹
$ mkdir -p app/out/R
和$ mkdir -p app/out/res
\
表示命令行换行。$SDK
可用命令$ export SDK=~/Library/Android/sdk
设置。- 命令的参数说明请见Android AAPT,或
$ aapt
查看输出信息。- 如果有第三方依赖,用-I继续添加, 可参考命令行编译Android。但我添加了com.android.support.constraint依赖,并用-I添加进命令行,执行命令后报错。
2. 编译AIDL文件
略
3. 编译Java文件
利用javac
编译.java
文件为.class
文件
$ javac -target 1.8 -source 1.8 \
-bootclasspath $SDK/platforms/android-28/android.jar \
-d app/out/class \
app/out/R/com/liang/clidemo/R.java app/src/main/java/com/liang/clidemo/*.java
生成
class
文件夹$ mkdir app/out/class
4. 生成Dex文件
$ dx --dex --output=app/out/dex app/out/class
需要生成
dex
文件夹$ mkdir app/out/dex
5. 打包生成apk
$ java -classpath $SDK/tools/lib/sdklib-26.0.0-dev.jar com.android.sdklib.build.ApkBuilderMain app/out/demo.apk \
-v -u -z app/out/res/resource.apk \
-f app/out/dex/classes.dex
6. 签名
签名debug版本的秘钥
$ jarsigner -verbose -keystore ~/.android/debug.keystore \
-storepass android \
-keypass android \
app/out/demo.apk androiddebugkey
7. 对齐
略
以上七个命令可以用来手动打包,但比较繁琐,而Gradle将这些命令封装起来作为任务,只需要执行$ ./gradlew assemleDebug
等即可,提高了工作效率。当然了,Gradle的功能不止如此。
执行./gradlew assembleDebug --console=plain
,可以看Gradle的任务执行顺序与用命令行打包顺序基本是一致的:
:app:checkDebugClasspath UP-TO-DATE
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
# 编译aidl
:app:compileDebugAidl NO-SOURCE
:app:compileDebugRenderscript UP-TO-DATE
:app:checkDebugManifest UP-TO-DATE
# 编译BuildConfig.java
:app:generateDebugBuildConfig UP-TO-DATE
:app:prepareLintJar UP-TO-DATE
:app:mainApkListPersistenceDebug UP-TO-DATE
# 生成R.java和res资源文件
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources UP-TO-DATE
:app:mergeDebugResources UP-TO-DATE
:app:createDebugCompatibleScreenManifests UP-TO-DATE
:app:processDebugManifest UP-TO-DATE
:app:splitsDiscoveryTaskDebug UP-TO-DATE
:app:processDebugResources UP-TO-DATE
:app:generateDebugSources UP-TO-DATE
:app:javaPreCompileDebug UP-TO-DATE
# javac编译java文件为class文件
:app:compileDebugJavaWithJavac UP-TO-DATE
:app:compileDebugNdk NO-SOURCE
:app:compileDebugSources UP-TO-DATE
:app:mergeDebugShaders UP-TO-DATE
:app:compileDebugShaders UP-TO-DATE
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets UP-TO-DATE
# 生成dex文件
:app:transformClassesWithDexBuilderForDebug UP-TO-DATE
:app:transformDexArchiveWithExternalLibsDexMergerForDebug UP-TO-DATE
:app:transformDexArchiveWithDexMergerForDebug UP-TO-DATE
:app:mergeDebugJniLibFolders UP-TO-DATE
:app:transformNativeLibsWithMergeJniLibsForDebug UP-TO-DATE
:app:transformNativeLibsWithStripDebugSymbolForDebug UP-TO-DATE
:app:checkDebugLibraries UP-TO-DATE
:app:processDebugJavaRes NO-SOURCE
:app:transformResourcesWithMergeJavaResForDebug UP-TO-DATE
:app:validateSigningDebug UP-TO-DATE
# 打包
:app:packageDebug UP-TO-DATE
:app:assembleDebug UP-TO-DATE
Android Plugin DSL Reference
Android Plugin DSL Reference详细描述了Android module构建脚本build.gradle
所用到的参数。
包括四个扩展内容,下面以应用型项目的build.gradle
为例,说下AppExtension
的语法。
简单的应用型项目的build.gradle
脚本:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.liang.clidemo"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
解释如下:
-
Project
实例的三个方法。最外层的apply
、android
和dependencies
都是Project
实例的方法。 -
apply
方法。全称为void apply(Map<String, ?> options)
,位于接口PluginAware.java
中(Project
实现了PluginAware
),用于增加插件。示例中表示当前项目为应用型项目。 -
android
方法。原始的Project
中并没有这个方法,应该位于Android插件的Project
的实例中,可以看源码。闭包里的参数设置详细说明位于Reference的AppExtension
中-
ompileSdkVersion
。编译版本。很奇怪的是AppExtension
中说它是String
类型的,但如果赋值为字符串,则又报错。 -
defaultConfig
。接收DefaultConfig
作为参数,其闭包里的参数说明见Reference的DefaultConfig -
buildTypes
。闭包里的参数设置请见BuildType
-
-
dependencies
方法。位于Project
中void dependencies(Closure configureClosure);
,参数说明详见闭包的代理DependencyHandler
:p,还是看源码比较直接。
待研究
-
aapt
命令中添加第三方依赖问题 -
aapt2
命令 - Android构建脚本配置。官网-Configure your build写的比较详细,目前不准备写。
- Android构建最佳实践。官网-Configure your build上写了许多,以后可以做些补充。
- Gradle和Android Plugin源码阅读和分析。非常值得研究,但需要花费很多时间,以后有时间加上。