一、构建过程
典型的构建过程如下所述:
- Android Asset Packaging Tool (aapt) 将资源文件带给你的应用程序,比如AndroidManifest.xml和你的Activity要用的XML布局文件,并将它们编译后生产R.java以供你从java代码中引用资源文件。
- aidl工具将任何.aidl接口转换成java接口
- 所有java代码,包括R.java和.aidl文件,都被java编译器编译成.class文件
- dex工具把.class文件转换成Dalvik字节码。任何第三方的库和.class文件也被转换成dex文件,这使得它们最终能够被打包进apk文件中
- 所有编译、为编译的资源以及dex文件被发送给apkbuilder工具来打包成apk文件
- 一旦apk编译好了,它必须使用debug或release密钥来将其进行签名
- 最后,如果app使用release模式签名,你还要使用zipalign工具来对齐apk,使得当程序运行时减少内存使用
二、构建配置基础
AS包含一个顶级的build文件以及各个module独有的build文件——build.gradle。它们是用groovy语法来配置build的清晰明了的文本文件,使用的元素是由Android的Gradle插件提供的。大部分情况下,你只需要修改module级别的build文件。例如:
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "19.0.0"
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile project(":lib")
compile 'com.android.support:appcompat-v7:19.0.1'
compile fileTree(dir: 'libs', include: ['*.jar'])
}
apply plugin: 'com.android.application'
在这个构建中应用Android的Gradle插件。这把Android专用的构建任务添加到顶级构建任务中,并使得android {…}元素对指定的Android专用构建选项可用。
android {...}
配置所有的Android专用构建选项
compileSdkVersion
指明编译的目标版本
buildToolsVersion
指明buildtool版本
defaultConfig
动态地对核心设置及manifest文件的入口进行配置。defaultConfig中的值会覆盖manifest文件中的值。defaultConfig中指定的配置应用于所有的build,除非某个build重写了这其中的部分值
buildTypes
控制如何构建及打包你的app。默认情况下,构建系统定义了两种方式:debug和release. debug方式包含调试标识,并且用debug key进行签名。release方式默认没有签名。上面的例子中,build文件使用release版本,并使用了混淆。
dependencies
是在android元素之后,这个元素声明了该module的依赖关系。
三、依赖关系
声明依赖关系:
...
dependencies {
// Module dependency
compile project(":lib")
// Remote binary dependency
compile 'com.android.support:appcompat-v7:19.0.1'
// Local binary dependency
compile fileTree(dir: 'libs', include: ['*.jar'])
}
构建系统将所有的编译依赖加入到classpath中,并将它们加入最终的包里。
Module dependencies(模块依赖)
compile project(":lib")
声明了一个对lib模块的依赖。当你构建app模块时,构建系统会装配并包含lib模块。
Remote binary dependencies(远程二进制依赖)
compile 'com.android.support:appcompat-v7:19.0.1'
通过指明Maven地址声明了一个对Android Support Library 19.0.1版本的依赖。AS默认工程使用Maven中心仓库(这是在工程的顶级build文件中配置的)
Local binary dependencies(本地二进制依赖)
有些模块没有使用任何来自本地文件系统的二进制依赖。如果你有需要使用本地二进制依赖的模块,将这些依赖用到的jar文件复制到你的工程的/libs下。
compile fileTree(dir: 'libs', include: ['*.jar'])
告诉构建系统任何一个app/libs下的jar文件都是一个依赖并且需要被包含到编译的classpath和最终的package中。
四、运行代码混淆
...
android {
...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
...
getDefaultProguardFile('proguard-android.txt')
从android sdk的安装目录获取默认的混淆配置文件。AS在module的根目录添加了module专用的规则文件proguard-rules.pro,你可以在这里面加入自己的混淆规则
五、用于包标识的Application ID
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "19.1"
defaultConfig {
applicationId "com.example.my.app"
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
...
当使用build variants时,构建系统允许你唯一地为不同package中的每个product flavors和build types进行标识。build type中的application ID是作为后缀为那些指定的product flavors添加的
productFlavors {
pro {
applicationId = "com.example.my.pkg.pro"
}
free {
applicationId = "com.example.my.pkg.free"
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
....
包名仍然需要在manifest文件中指明。它用于在你的源代码中引用R文件和使用相对路径名的Activity/service的注册
六、使用build variants(构建变体)
当你有一个demo版和一个付费版app,或者你想要在Google play上为不同的设备分发不同多个apk时,这将很有用。
构建系统使用product flavors来创建不同的app版本。每个app版本可以有不同的特性或者设备配置要求。构建系统还使用build types为每个版本应用不同的构建和打包配置。每个product flavor和build type联合形成一个构建变体。构建系统为每个构建变体创建一个不同的app。
Product flavors
为你的app创建不同版本:
- 在build文件中定义product flavors
- 为每个flavor创建另外的源目录
- 将指定flavor来源加入你的工程
七、例子
1.在构建文件中定义product flavor
编辑app模块下的build文件如下:
...
android {
...
defaultConfig { ... }
signingConfigs { ... }
buildTypes { ... }
productFlavors {
demo {
applicationId "com.buildsystemexample.app.demo"
versionName "1.0-demo"
}
full {
applicationId "com.buildsystemexample.app.full"
versionName "1.0-full"
}
}
}
...
product flavor定义支持相同的defaultConfig属性。所有的基础配置由defaultConfig指定,每种flavor重写任意的默认值。上面的build文件用applicationId属性来为每个flavor分配不同的包名:由于每个flavor定义创建一个不同的app,它们每个都需要一个独有的包名。
2.为每种flavor添加额外的源目录
- 在project视图下,展开工程目录,展开app文件夹
- 右键点击app目录下的src目录,选择New > Directory,输入“demo”,点击OK 。类似地,创建以下目录(效果如下图):
app/src/demo/java
app/src/demo/res
app/src/demo/res/layout
app/src/demo/res/values
3.为每个flavor添加一个新的Activity
添加SecondActivity到demo flavor:
- project视图下,右键app module,选择New > Activity
- 选择Blank Activity,点击Next
- 输入SecondActivity作为Activity名
- 输入com.buildsystemexample.app作为包名并点击finish
- 右键app/src/demo下的java目录,选择New > Package
- 输入com.buildsystemexample.app作为包名,点击OK
- 把SecondActivity拖到上面的包下
- 接受默认值并点击Refactor
为demo flavor添加布局和string文件:
- 把app/src/main/res/layout下的activity_second.xml拖到app/src/demo/res/layout.
- 保持默认点OK
- 把string.xml从app/src/main/res复制到app/src/demo/res
- 修改app/src/demo/res下的string:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello_world">Demo version only.</string>
</resources>
将源文件夹和secondActivity从demo flavor复制到full flavor:
- project视图下,右键app/src下的demo目录选择copy
- 右键app/下的src目录选择paste
- 输入full作为新名字点OK
- 修改src/full/res/values下string的内容:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello_world">This is the full version!</string>
</resources>
要想运行一个特定的flavor,点击AS左侧下方的Build Variants,在Build Variants面板中选择你要修改的flavor。
4.从main Activity启动一个指定flavor的Activity
由于所有flavor中都有相同包名和Activity名的flavor-specific activity (SecondActivity),你可以从main Activity启动它,这对于所有flavor来说是通用的。修改main Activity:
- 编辑activity_main.xml,添加一个新按钮到MainActivity:
<LinearLayout ...>
...
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button2"
android:onClick="onButton2Clicked"/>
</LinearLayout>
- 给button设置文字“Open Second Activity”,在MainActivity中添加onButton2Clicked点击事件
- 在点击事件中启动SecondActivity
- 在manifest文件中包含SecondActivity的引用
<manifest ...>
<application ...>
...
<activity android:name="com.buildsystemexample.app.SecondActivity"
android:label="@string/title_activity_second" >
</activity>
</application>
</manifest>
5.Build types
Build types表示构建打包版本,默认debug和release。
...
android {
...
defaultConfig { ... }
signingConfigs { ... }
buildTypes { ... }
productFlavors {...}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
}
}
}
...