Android构建06-Android应用构建基础

简介

Android构建流程是指将Android源代码转换成Apk(Android Application Package)这一过程,里面涉及到许多步骤和工具。构建流程由Gradle和Android Gradle Plugin插件来管理,既可以通过IDE方式,也可以通过命令行方式来进行。



构建流程

官网有一个简单的流程图,比较简略,图中主要展示了两步,且都是由Gradle和Andorid插件管理的:

  1. 编译。编译器将源代码编译成DEX文件和供前者直接使用的资源文件。
  2. 打包并签名。将上述DEX文件和资源文件合并成APK,之后进行签名生成最终可以用于安装、测试或发布的APK。

在许多博客中,都提到一个详细的流程图,说是来自官网,但我没有找到,可能以前存在,现在已经删除了,如下:

Android构建06-Android应用构建基础_第1张图片
Android构建流程

上述流程分为七个步骤,涉及许多工具,如AAPT、AIDL等,有些工具现在已经升级或改变名称了,如AAPT现在升级为AAPT2。

AAPT等工具位于{Android SDK}/build-tools/{版本号}。

七个步骤具体如下:

1. 编译资源文件

利用aapt编译资源文件生成R.javaresources.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实例的三个方法。最外层的applyandroiddependencies都是Project实例的方法。
  • apply方法。全称为void apply(Map options),位于接口PluginAware.java中(Project实现了PluginAware),用于增加插件。示例中表示当前项目为应用型项目。
  • android方法。原始的Project中并没有这个方法,应该位于Android插件的Project的实例中,可以看源码。闭包里的参数设置详细说明位于Reference的AppExtension
    • ompileSdkVersion。编译版本。很奇怪的是AppExtension中说它是String类型的,但如果赋值为字符串,则又报错。
    • defaultConfig。接收DefaultConfig作为参数,其闭包里的参数说明见Reference的DefaultConfig
    • buildTypes。闭包里的参数设置请见BuildType
  • dependencies方法。位于Projectvoid dependencies(Closure configureClosure);,参数说明详见闭包的代理DependencyHandler

:p,还是看源码比较直接。



待研究

  • aapt命令中添加第三方依赖问题
  • aapt2命令
  • Android构建脚本配置。官网-Configure your build写的比较详细,目前不准备写。
  • Android构建最佳实践。官网-Configure your build上写了许多,以后可以做些补充。
  • Gradle和Android Plugin源码阅读和分析。非常值得研究,但需要花费很多时间,以后有时间加上。


参考

  1. 官网-Configure your build
  2. Android APK 编译打包流程
  3. APK打包安装过程
  4. 详细打包流程图
  5. 命令行编译Android
  6. How to make Android apps without IDE from command line
  7. Android AAPT
  8. AAPT2官方文档
  9. aapt2 资源 compile 过程
  10. 官网-Android Plugin DSL Reference
  11. Android Gradle Plugin 源码阅读与编译

你可能感兴趣的:(Android构建06-Android应用构建基础)