Android Studio项目Gradle构建实践

参考

名词

  • 构建类型(BuildType),编译时的类型,如debug, release
  • 产品风味(ProductFlavor),不同的产品特征,可以有不同的包名等等。
  • 构建变体(BuildVariant),每一个特定唯一确定版本apk都是一个构建变体的产物,其由构建类型和产品风味组成。
  • APG,全称是Android Plugin for Gradle,google为使用gradle构建而开发的插件。

Demo下载

demo下载地址:https://github.com/shenbibo/GradleBuildDemo2

1 一个典型的Android Studio 项目

1.1 项目结构

一个新建的Android Stuido项目结构如下:

项目结构

包含三个.gradle文件:

  • settings.gradle 文件对应脚本执行时的setting对象,该文件最先被解析和执行,一些通用的初始化操作可以放在这里执行,项目包含多个子工程或者模块时,必须在该文件中include,这也是其最重要的功能之一。新建项目默认的settings.gradle
include ':app'

这里我想在脚本刚执行时打印项目的存放路径操作:

String projectDir = rootProject.projectDir.getAbsolutePath();
println projectDir
include ':app'
  • 项目根目录下的build.gradle,对应脚本执行时的rootProject对象,一般不做具体的模块构建操作,用于指定项目所依赖的远程仓库和使用的Gradle plugin 插件版本,适用与所有的子工程或者模块。
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
   
    //jcenter一个著名的远程代码仓库
    repositories {
        jcenter()
    }


    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
  1. 上面指定远程仓库的作用就是在需要依赖的库在本地找不到时,会到该仓库中去寻找并自动下载。
  2. 依赖的构建插件,注意该插件不是Gradle的版本,是插件的版本,由google开发。
  • 每个子项目或模块下单独的build.gradle脚本文件,在这里指定各自依赖的SDK,库属性等等,这也是我们编译的脚本的主体。
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.1"
    defaultConfig {
        applicationId "com.inpor.fmcdevicedemon"
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.1'
    testCompile 'junit:junit:4.12'
}
  • apply plugin 指定要加载的插件,这里是一个应用,所以加载com.android.application插件,注意这个插件是我们上面使用的google开发的com.android.tools.build:gradle:2.2.3中携带的。

  • android闭包来自于google插件,这里查看其DSL文档:http://google.github.io/android-gradle-dsl/

1.2 Gradle Project

我们的AS项目对于Gradle而言就是一个个Gradle项目,而Gradle项目对于我们而言就是一个个task构成的,我们可以点击Android Studio的最右边的Gradle工具栏,可以查看其项目结构。
gradle project

比如上面我们点开other目录,双击第一个任务,此时就可以直接这个任务,生成一个apk。
gradle project2

2 配置基本编译参数

2.1 基本使用

这里主要是指设置编译时指定的SDK、bulidtools版本,包名,应用版本号等等,注意这里面定义的属性会覆盖AndroidMainfest.xml文件中定义的。

//编译时的SDK版本号
compileSdkVersion 25

//编译时指定的buildtools版本
buildToolsVersion "25.0.1"

defaultConfig {
    //应用的包名
    applicationId "com.inpor.fmcdevicedemon"

    //指定应用可以安装到的系统的最低版本,这里14对应的是android 4.0
    minSdkVersion 14

    //运行时指定使用的sdk的版本,主要针对当存在多个sdk版本时,优先使用的SDK版本
    targetSdkVersion 25

    //应用版本号
    versionCode 1
    versionName "1.0"

    //执行单元测试时指定的Runner,在正式打包时并不会使用到
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
2.2 提取公用字段定义到其他文件中

前面说过我们可以把一个通用的属性存放到项目根目录下的build.gradle中。

//使用ext表示导出
ext {
    compileSdk = 25
    buildTools = "25.0.1"
    targetSdk = 25
    minSdk = 14
}

然后在app的build.gradle文件中使用定义的通用属性

compileSdkVersion rootProject.ext.compileSdk
buildToolsVersion rootProject.ext.buildTools
defaultConfig {
    applicationId "com.inpor.fmcdevicedemon"
    minSdkVersion rootProject.ext.minSdk
    targetSdkVersion rootProject.ext.targetSdk
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

如果是多项目关联,把一些共有的属性提取出来就很有用了。

2.3 使用resConfigs只打包需要的资源

只打包我们需要的资源。我们知道google给我们的apk提供了国际化支持,如适应不同的屏幕分辨率的drawable资源,还有适应不同语言的字符串资源等等,但是在很多情况下我们只需要一些指定分辨率和语言的资源就可以了,这个时候我们可以使用resConfigs方法来配置。

defaultConfig中添加如下配置之后

defaultConfig {
    .....
    // 过滤,对于国际化支持只打包中文资源,和"xxhdpi"
    // 注意如果在这里指定了dpi,则flavor中不能指定的dpi与这里必须一致否则会报错
    resConfigs "zh-rCN", "xhdpi"
}

在添加resConfigs之前,反编译的res目录截图:
未过滤图片

在添加上述resConfigs配置之后,反编译res目录:

过滤后的图片

注意:

  • 使用resConfigs并不会过滤默认的drawable, values目录,这是为了保证App在任何时候都有一个默认的可选值。
  • resConfigs也可以在后面要讲到的productFlavor中也可以使用。

3 signingConfigs(Apk签名配置)

3.1 配置不同的签名

在默认情况下,AS中编译apk使用的是SDK中的Debug签名,不需要显式的指定签名配置项,在signingConfigs的闭包中我们可以自定义多个签名配置,一个典型的签名配置:

signingConfigs {

    //debug签名
    debug {
        //签名秘钥库文件的存放的位置,这里使用的是相对路径
        storeFile file('sign/debug.keystore')

        //秘钥库的访问密码
        storePassword 'android'

        //别名,因为一个密码库可以供多个项目使用,所以别名不同,最后的签名也是不同的。
        keyAlias 'androidreleasekey'

        //别名的私钥密码
        keyPassword 'android'
    }


    release {
        storeFile file('sign/platform.keystore')
        storePassword 'android'
        keyAlias 'androidreleasekey'
        keyPassword 'android'
    }
}
3.2 从指定文件加载签名和秘钥

如果希望不在build.gradle中暴露自己的签名秘钥,可以将这些参数放到一个专门的文件中,比如在项目的根目录下添加一个keystore.properties文件。

//test
debugStoreFile=sign/debug.keystore
debugStorePassword=android
debugKeyAlias=androidreleasekey
debugKeyPassword=android

//release
releaseStoreFile=sign/platform.keystore
releaseStorePassword=android
releaseKeyAlias=androidreleasekey
releaseKeyPassword=android

在app模块的build.gradle中,解析这个文件

// Create a variable called keystorePropertiesFile, and initialize it to your
// keystore.properties file, in the rootProject folder.
def keystorePropertiesFile = rootProject.file("keystore.properties")

// Initialize a new Properties() object called keystoreProperties.
def keystoreProperties = new Properties()

// Load your keystore.properties file into the keystoreProperties object.
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

android{
    .....
}

修改signConfigs闭包,引用文件中定义的属性

signingConfigs {
    debug {
        keyAlias keystoreProperties['debugKeyAlias']
        keyPassword keystoreProperties['debugKeyPassword']
        storeFile file(keystoreProperties['debugStoreFile'])
        storePassword keystoreProperties['debugStorePassword']
    }

    release{
        keyAlias keystoreProperties['releaseKeyAlias']
        keyPassword keystoreProperties['releaseKeyPassword']
        storeFile file(keystoreProperties['releaseStoreFile'])
        storePassword keystoreProperties['releaseStorePassword']
    }
}

4 编译类型(buildTypes

在Android studio中我们可以自定义不同的编译类型,如调试版本,发行版本,在不同的版本中可以配置不同的参数与添加属性,工程自带有一个debug编译类型,另外用户无法自定义为testtype,它已经被单元测试占用。

比如下面我定义了三个不同的buildType,分别设置不同的属性值

buildTypes {

    debug {
        //指定签名文件的配置,不指定则使用SDK中默认的debug签名
        signingConfig signingConfigs.debug

        //压缩对齐,提高运行时的效率,也可以使用zipAlignEnabled true
        setZipAlignEnabled(true)

        //可以调试
        debuggable true

        //jni可调试
        jniDebuggable true

        //渲染脚本可调试
        renderscriptDebuggable true
    }


    //在发行版本中,不允许调试,并且添加代码混淆
    release {

        setZipAlignEnabled(true)
        debuggable false
        jniDebuggable false
        renderscriptDebuggable false

        //指定签名文件为release签名,注意非debug,如果不指定签名,则打出来的包不会签名
        signingConfig signingConfigs.release

        //minifyEnabled表示代码是否可以压缩,裁剪优化,需要配合其他的工具一起使用,如proguard
        //添加代码混淆,注意添加混淆时,必须将
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值