配置Gradle构建

jopen 8年前

这一节是在 android构建系统总览用Android Studio构建及运行android app 之上构建起来的,它向你展示了如何使用基于product flavors和build types的build variants。

构建配置基础

Android Studio项目包含一个顶层的构建文件,而每个模块也都有自己的构建文件。构建文件被称为build.gradle,它们是纯文本文件,使用Groovy语法通过Gradle的Android插件提供的元素来配置构建过程。在大多数情况下,你只需要编辑模块级的构建文件。比如,在BuildSystemExample项目里,app模块的构建文件是这样的:

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'为这次构建应用Gradle的Android插件。这一行向顶层构建tasks中添加了Android特有的构建tasks,并使得android {...}元素能够描述Android特有的构建选项。

android {...}配置了所有Android特有的构建选项:

compileSdkVersion属性指定了编译目标。

buildToolsVersion属性指定了使用的构建工具的版本。要安装多个版本的构建工具,请使用SDK Manager。注意:请总是使用主修订版本号大于等于你的编译目标和目标SDK的构建工具。

defaultConfig元素在构建系统中动态地配置manifest文件(AndroidManifest.xml)中的核心设定及项(entries)。defaultConfig中的值会覆盖manifest文件中的值。defaultConfig元素中描述的配置项应用于所有的build variants,除非一个build variant的配置覆盖了这些值。

buildTypes元素控制如何构建及打包你的app。默认情况下,构建系统定义了两种build types:debugrelease。debug build type包含了调试的符号信息并用debug key签名。默认情况下release build type不签名。在这个例子中,构建文件配置了使用ProGuard的release版本。

dependencies元素在android元素的外面,且在它的后面。这个元素声明了这个模块的依赖(dependencies)。下面的部分会来讲解依赖(dependencies)

注意:当对你项目中的构建文件做了修改,Android Studio会请求一个projec sync来导入构建配置的改动。点击Android Studio中出现的黄色通知栏上的 Sync Now来导入变动。


图1. 于Android Studio中同步project

声明依赖

这个例子中的app模块声明了三个依赖:

...  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'])  }

这些依赖都将在下面进行描述。构建系统会把所有的compile依赖都添加到编译的classpath中,并把它们都包含进最终的包里。

模块依赖

app模块依赖lib模块,因为MainActivity要启动Open an Activity from a Library Module中所描述的LibActivity1。

compile project(":lib")声明了一个对BuildSystemExample的lib模块的依赖。当你构建app模块时,构建系统会汇集并包含lib模块。

远程二进制依赖

app和lib模块都使用了Android Support Library里的ActionBarActivity类,因而这些模块都依赖于它。

compile 'com.android.support:appcompat-v7:19.0.1'通过指定它的Maven坐标声明了一个对于版本为19.0.1的Android Support Library的依赖。Android Support Library能在Android SDK的Android Repository包中找到。如果你的SDK包中没有这个包,请使用SDK Manager下载并安装它。

本地二进制依赖

有些模块不使用本地文件系统上的任何二进制依赖。如果你有模块需要本地的二进制依赖,请把这些依赖的JAR文件复制到你的项目的<moduleName>/libs目录下。

compile fileTree(dir: 'libs', include: ['*.jar'])告诉构建系统app/libs里的所有JAR文件都是必需的,且应该被包含进编译classpath及最终的包里面。

更多关于 Gradle里的依赖的信息,请参考Gradle用户指南(Gradle User Guide)里的Dependency Management Basics

运行ProGuard

构建系统可以在构建过程中运行ProGuard来混淆你的类。在BuildSystemExample中,修改app模块的构建文件为release build运行ProGuard:

...  android {      ...      buildTypes {          release {              minifyEnabled true              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'          }      }  }  ...

getDefaultProguardFile('proguard-android.txt')从Android SDK包中获取默认的ProGuard设置。Android Studio会添加位于模块的根目录的模块特有规则文件proguard-rules.pro,你可以向这个文件中添加定制的ProGuard规则。

用应用程序ID标识包

在Android构建系统中,applicationId属性用于为发布唯一地标识应用程序包。应用程序ID在build.gradle文件的android段设置。

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"      }      ...

注意applicationId只在你的build.gradle文件中设置,而不是AndroidManifest.xml文件中。

当使用build variants时,构建系统使你能为每种product flavors和build type唯一地标识不同的包。build type中的应用程序ID会被作为一个后缀添加到product flavors的应用程序ID上。

productFlavors {          pro {              applicationId = "com.example.my.pkg.pro"          }          free {              applicationId = "com.example.my.pkg.free"          }      }        buildTypes {          debug {              applicationIdSuffix ".debug"          }      }      ....

包名仍然必须在manifest文件中指定。它在你的源代码中使用,用于引用你的R类,及解析任何相关的activity/service注册。

package="com.example.app">

注意:如果你有多个manifests(比如,一个product flavor特有的manifest及一个build type manifest),那些manifests里的包名是可选的。如果在那些manifest里指定了包名,则它们必须与src/main/目录下的manifest文件中指定的包名一致。

配置签名设定

app的debug和release版本,不仅在 是否能在安全的设备上被调试 这一点是不同的,它们的APK的签名方法也是不同的。构建系统使用已知的认证信息(credentials)通过一个默认的key和证书(certificate)来签名debug版以避免在构建的时候弹出一个密码提示框。构建系统不签名release版,除非显式地为这次构建定义一个签名配置。如果你没有release key,你可以按照Signing your Applications中描述的那样生成一个。

使用build variants

这一部分描述构建系统如何帮助你由一个单独项目创建相同应用程序不同版本。当你的app有一个演示版及一个付费版时或者你想要在Google Play上为不同的设备配置分发多个APKs时这很有用

构建系统使用product flavors来创建你的app的不同产品版本。你的app的每个产品版本可以具有不同的功能或设备要求。构建系统也对每个产品版本使用build types来应用不同的构建及打包设定。每个product flavor和build type组合形成一个build variant。构建系统为你的app的每个build variant产生一个不同的APK。

Build variants

这个示例项目由两个默认的build types(debugrelease)及两个app类型(demo和full) product flavors组成。关于build variants的高级使用的更多信息,请参考 android构建系统总览

Product flavors

创建你的app的不同产品版本:

  1. 在构建文件(build file)中定义product flavors。
  2. 为每个flavor创建额外的源码目录。
  3. 添加flavor特有的源码进你的项目。

这一节的其余部分将使用一个BuildSystemExample项目带你详细地了解这些步骤。你为BuildSystemExample app创建两个flavors,一个demo flavor和一个full flavor。这两个Flavors共享MainActivity,你在它里面添加一个新的按钮来启动一个新的activity,SecondActivity。不同flavor的这个新activity是不同的,因而你模拟这样一种情形,即full flavor中的这个新activity相比于demo flavor中的那个将具有更多的功能。在这个练习的最后,你以两个不同的APKs结束,每个flavor一个。

在构建文件(build file)中定义product flavors

要定义两个product flavors,则编辑app模块的构建文件(build file)并添加如下的配置:

...  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元素相同的属性。所有flavors的基本配置在defaultConfig中指定,而每个flavor则可以覆盖默认值。上面的构建文件(build file)使用了applicationId属性来为每个flavor分配一个不同的包名:因为每个flavor定义创建一个不同的app,它们都需要一个不同的包名。

注意:要在Google Play中使用Multiple APK Support分发你的app,则请为所有的variants分配相同的包名,并为每个variant提供一个不同versionCode。要在Google Play中以不同的apps分发你的app的不同变体(variant),则为每个variant分配一个不同的包名。

为每个flavor添加额外的源码目录

现在你需要为每个flavor创建源码目录并添加一个SecondActivity。要为demo flavor创建源码目录结构则执行:

  1. Project面板,展开BuildSystemExample,然后展开app目录。
  2. 右键单击app下的src目录并选择New > Directory
  3. 键入"demo"作为新目录的名字并点击OK
  4. 类似地,创建下面的这些目录:
  • app/src/demo/java
  • app/src/demo/res
  • app/src/demo/res/layout
  • app/src/demo/res/values

最终的目录结构看上去如下图1所示的那样。


图1. demo flavor的新源码目录

给每个flavor添加一个新的activity

给demo flavor添加SecondActivity:

  1. Project面板,右键单击app模块并选择 New > Activity
  2. 选择Blank Activity并点击Next
  3. 键入"SecondActivity"作为activity名字。
  4. 键入"com.buildsystemexample.app"作为包名并点击Finish
  5. 右键单击app/src/demo下的java目录并选择New > Package
  6. 键入"com.buildsystemexample.app"作为包名并点击OK
  7. SecondActivity拖到app/src/demo/java里的新包下。
  8. 接受默认值并点击Refactor

给demo flavor添加一个字符串资源并为SecondActivity添加layout:

  1. app/src/main/res/layout里的activity_second.xml拖到app/src/demo/res/layout下。
  2. 接受窗口中出现的默认值并点击OK
  3. app/src/main/res下的strings.xml复制到app/src/demo/res里。
  4. 用下面的内容替换新复制的strings.xml里的内容:

<?xml version="1.0" encoding="utf-8"?>  <resources>      <string name="hello_world">Demo version only.</string>  </resources>

现在通过创建一份demo flavor的拷贝来为full flavor添加源码目录和SecondActivity:

Project面板,右键单击app/src下的demo目录并选择Copy

右键单击app/下的/src目录并选择Paste

在出现的窗口中,键入"full"作为新的名字并点击OK

用下面的内容替换src/full/res/values下的strings.xml里的内容:

<?xml version="1.0" encoding="utf-8"?>  <resources>      <string name="hello_world">This is the full version!</string>  </resources>

注意:从现在开始,你可以独立地开发每个flavor里的SecondActivity了。比如,你可以为full flavor里的这个activity添加更多的功能。

要基于一个特定flavor的文件来工作,则点击IDE窗口左边的Build Variants,并选择Build Variants面板里你想要修改的falvor,如图2所示的那样。Android Studio可能显示在Build Variants面板里被选中之外的flavors源码文件里有错误,但这不影响构建的最终输出。


图2. Build Variants面板

从主activity启动一个flavor特有activity

由于两个flavors中的flavor特有activity (SecondActivity)具有相同的包名及activity名,你可以在主activity中启动它,所有flavors的启动方法一样。修改主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>
点击layout文件中标红的区域并按下Alt+ Enter。遵循Android Studio的提示,添加一个值为“Open Second Activity”的新字符串资源,并给MainActivity添加一个onButton2Clicked方法。

把下面的代码添加进MainActivity的onButton2Clicked方法:

public void onButton2Clicked(View view) {      Intent intent = new Intent(this, SecondActivity.class);      startActivity(intent)
</span>

编辑app的manifest包含一个对SecondActivity的引用:

<manifest ...>      <application ...>          ...          <activity              android:name="com.buildsystemexample.app.SecondActivity"              android:label="@string/title_activity_second" >          </activity>      </application>  </manifest>

Build types

Build types表示为每个app包产生的构建打包版本(build packaging versions)。默认提供了debug和release两个build types。

...  android {      ...      defaultConfig { ... }      signingConfigs { ... }      buildTypes { ... }      productFlavors {...}      buildTypes {          release {              minifyEnabled false              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'          }           debug {              debuggable true          }      }  }  ...

注意:尽管只有release build type出现在默认的build.gradle文件里,但每次构建都会应用release和debug两个build types。

在这个例子里,product flavors和build types创建了如下的build variants:

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease

要构建这个例子,请点击Build菜单选项,或者在命令行上调用assemble task。

注意: Build > Make Project选项编译整个项目中自上次编译以来被修改过的所有的源文件。Build > Rebuild Project选项重编译项目中的所有源文件。

每个build variants会有不同的输出文件夹创建出来。

Android Studio默认配置项目使用Maven Central Repository。(这个配置被包含在项目的顶层build file中。)

Done。

原文