简介
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
1 2 3 4 5
| $ 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
|
1 2 3 4 5
| $ 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
文件
1 2 3 4
| $ 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文件
1
| $ dx --dex --output=app/out/dex app/out/class
|
需要生成dex
文件夹$ mkdir app/out/dex
5. 打包生成apk
1 2 3
| $ 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版本的秘钥
1 2 3 4
| $ 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的任务执行顺序与用命令行打包顺序基本是一致的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| :app:checkDebugClasspath UP-TO-DATE :app:preBuild UP-TO-DATE :app:preDebugBuild UP-TO-DATE
:app:compileDebugAidl NO-SOURCE :app:compileDebugRenderscript UP-TO-DATE :app:checkDebugManifest UP-TO-DATE
:app:generateDebugBuildConfig UP-TO-DATE :app:prepareLintJar UP-TO-DATE :app:mainApkListPersistenceDebug UP-TO-DATE
: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
: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
: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
脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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,还是看源码比较直接。
待研究
参考
- 官网-Configure your build
- Android APK 编译打包流程
- APK打包安装过程
- 详细打包流程图
- 命令行编译Android
- How to make Android apps without IDE from command line
- Android AAPT
- AAPT2官方文档
- aapt2 资源 compile 过程
- 官网-Android Plugin DSL Reference
- Android Gradle Plugin 源码阅读与编译