Gradle 入门到精通(三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/seemygoandroid/article/details/76125055

前言

根据我们上一篇的介绍,我们知道了项目的结构以及构建的流程,根据上面的知识,我们知道了构建的规则实际就是我们写在build.gradle的内容。gradle android插件读取这个文件的内容后,最后完成构建工作。在讲解实际内容前,我先提供一个网站给大家,因为gradle android 插件 是通过dsl语言编写的,所以我们需要知道在什么地方获取相应的api。

7 build.gradle文件分析

https://docs.gradle.org/3.5/dsl/

https://google.github.io/android-gradle-dsl/current/

第一个网站是gradle官方提供的dsl,第二个网站是google提供的dsl查询手册

7.1 根目录的build.gradle文件

我们来打开根目录下面的build.gradle文件,这个文件是整个项目的配置文件,我们一般是放置一些基础的配置。

上图是build.gradle文件的内容

7.1.1 buildscript

buildscript{} 这个是基础配置,所有的子模块都会读取到这个配置里面的内容,当构建开始的时候,就开始读取这个 buildscript{} 里面的内容。

repositories{} 这个模块的内容告诉gradle 去什么地址下载第三方的库。

jcenter() 代表 https://bintray.com/bintray/jcenter

mavenCentral() 代表使用maven的服务器 https://search.maven.org/

但是有一个问题就是上面的两个网站在中国访问速度慢

buildscript {
    repositories {
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
}

可以使用阿里云的maven服务

7.1.2 allprojects

allprojects 一般是配置所有模块的共同使用的内容。

    allprojects {
        repositories {
                jcenter()
      }
    }

这个是默认的配置,代表所有的子modle都是从jcenter获取第三方包的。我建议大家可以改成下面的写法

     allprojects {
         repositories {
           maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
     }
   }

7.1.3 gradle插件以及gradle版本的关系

在根目录上面的build.gradle的版本我们可以设置gradle 插件的版本号,初学者经常搞不懂插件与gradle的关系。特别是个版本之间的关系,下面我们来讲讲插件设置的方式。

最后的序号就是插件的版本号,注意插件不是gradle,插件是根据gradle特性编写为完成需求的jar包,插件依赖于gradle。

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

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

如果你使用的是2.3版本的插件,必须使用gradle3.3以上的版本。

如果你使用的是2.2版本的插件,必须使用gradle2.14.1以上的版本。

基本原则就是对照上面的表,看看你使用的是什么版本的插件。

那gradle的版本设置在哪里设置呢?我们打开gradle文件夹找到gradle-wrapper.properties文件,如下图所示

最后我再介绍一个方法,经常有同学说打开一个项目很久,其实就是去下载gradle.我们可以根据上面的这个表来手动下载gradle。然后放置到相应的文件夹内,下面的两张图片是插件的文件目录和gradle的文件目录

7.2 子项目的build.gradle

一般在稍微大一点的项目中,我们都按照业务逻辑分好不同的模块。根目录下的build.gradle是对所有模块起效果的基础配置,而每个模块下的build.gradle是这个模块的详细构建的配置,下面我们来学习一下有哪些内容。

上面的这张图片是默认的build的内容。我们看到内容可以分成三份。

7.2.1 apply

apply plugin: 'com.android.application'

这句话告诉gradle使用什么类型的插件进行构建。上面的是构建应用的,如果是构建库文件的是有下面的

 apply plugin: 'com.android.library'

7.2.2 dependencies{} 依赖配置

这个模块是声明项目的依赖,为什么我们要配置依赖呢?我们的项目大部分需要使用第三方库,而第三库很有可能还有其他的依赖,比如说Okhttp。这个依赖的内容由gradle进管理,免除了开发者下载、导入、设置等繁琐的炒作。这个内容不是android gradle 插件提供了,是gradle提供的,也就是说不止android,java,c++,只要是使用gradle构建的项目都能够使用这个模块声明。

这个模块是声明项目的依赖,可以依赖本地的文件,远程的资源库,本地的library库。详细的参数我们可以查询gradle Dsl的工具页面。

https://docs.gradle.org/current/userguide/artifact_dependencies_tutorial.html

如果英语好的同学可以看到,gradle支持了4种依赖的模式。

  • compile 意思是告诉gradle编译代码是需要使用的依赖。
  • runtime 产品代码在运行时需要的依赖。
  • testCompile 编译测试代码时所需要的依赖。
  • testRuntime 运行测试时需要的依赖。

其中 runtime会包括compile的依赖。 testRuntime会包括testCompile的依赖。但是很遗憾的是,android gradle plugings不支持runtime,所以android只包含上面的compile、testCompile两种模式。

那为什么会有两种不一样的模式了,其实是这样的,比如在java Web中,编译的时候需要的是servlet的依赖,但是运行的时候,就由服务器的容器提供,所以需要分开来,但是在android中,基本上使用的依赖就是一起把类文件编译打包到apk,所以没有runtime与compile的区别。

7.2.2.1 compile 编译时导入依赖

远程依赖

compile是gradle依赖使用最多的关键字,在build.gradle中使用了compile后,gradle就会去repositories中加载,我们看看如果在我们的项目中使用了OKHTTP的写法是怎么写的呢?

 compile 'com.squareup.okhttp3:okhttp:3.8.0'

这个是最简单的写法,我们刚开始从eclipse转到android studio开发的时候就知道整儿写了,但是世界实际这个一个简短的写法。规范的写法应用是这样。

 compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.8.0'

同步完成后,我们可以在External Libraries下面找到添加的依赖

)

本地依赖

gradle 提供了下载远程依赖包的能力,这个方式也是目前最流行的方式,但是考虑到国情等情况,我们也经常需要使用本地的jar包、AAR包、libery依赖。下面我们来学习这几种依赖的写法

本地jar包
  compile fileTree(include: ['*.jar'], dir: 'libs')

上面这句话就把libs下面的jar包,导入到项目中,也就是绑定到项目的classPath.也可以单独制定某一个jar包。

  compile files('libs/xxxx.jar')

上面的这两种方法都是导入jar包的方法,如果需要导入aar包,我们需要按照下面的来写。

本地aar包
 repositories {
     flatDir {
        dirs 'libs'
    }
}

增加一个本地的源目录。将aar文件放入libs文件夹。

 compile(name: '不带后缀的文件名', ext: 'aar')

同步完成后就可以使用导入的类库了。

library依赖

我们可以在项目中创建不同的module,创建的model的时候我们可以选择创建一个不同的类型。

)

上图是我们创建一个新的module的时候可以选择的选项,通常我们选择的是第一个,代表这个是一个可执行的项目。第二个代码是一个libery库,它与一般的项目不同,libery项目不能运行,libery项目最后会生成一个aar包,aar包与jar包类似。jar包是将编译的class打包的压缩包,aar包不止包括了class还有项目的资源生成的压缩包。

上面我们学习了怎么依赖一个aar包,下面我们来学习一下怎么依赖一个library项目,常见的有两种方法:

1 编写代码依赖

在需要依赖的模块上面的build.gradle文件内,查找到dependencies{}模块。添加以下代码:

 compile project(':名称')

在冒号后面输入模块的名称

2 ide添加依赖

我们在项目上面点击右键打开moduleseting

7.2.3 android{} 构建详细配置

android 模块的是该模块的详细设置,android app 的大部分的构建的内容都是在这个模块内配置的。

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.it520.x5webview"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

上面是android studio为我们创建的内容。

 compileSdkVersion 24

告诉 Gradle 用哪个 Android SDK 版本编译你的应用,建议使用最新的SDK 进行编译。在现有代码上使用新的编译检查可以获得很多好处,避免新弃用的 API ,并且为使用新的 API 做好准备。

buildToolsVersion "24.0.2"

构建工具的版本,其中包括了打包工具aapt、dx等等。这个工具的目录位于..your_sdk_path/build-tools/XX.XX.XX,注意这个工具和gradle版本有关系。

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

buildTypes 用来设置应用的构建版本。默认的情况会创建两个版本,1个版本是release(发布版),1个版本是debug(开发版)。默认的情况下,只显示了release的配置。我们一般都是在buildType中设置好相应的签名文件、打包加密方式、冗余资源等。

https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:minifyEnabled

上面的文档是buildType支持的所有的属性

  • applicationIdSuffix 包名的后缀
  • versionNameSuffix 版本的后缀

上面两个是我们在区分不同版本的时候增加的后缀名称

  • signingConfig

上面这个配置是设置打包的签名

  • shrinkResources
  • minifyEnabled

    上面的配置是去除冗余资源

    defaultConfig {…}

    默认配置,这里的代码块配置的在后面的各个构建变体(这里理解成不同的版本)都能够使用,这里面设置的值,在不同的构建变体内还可以再修改成具体的值。

    上面的配置是IDE默认生成的。了解默认的脚本后,我们来看看详细的配置。

7.2.3.1 签名配置 SigningConfig

我们生成一个apk需要经过一个过程就是给这个app进行签名的过程,这个过程我们要设置应用的签名,有同学不明白,为啥咱们调试的时候不需要?实际上默认提供了一个调试的签名文件.在mac系统的位置在~/.android
在windows系统的位置在(C:\Documents and Settings[User Name].android)(C:\Users.android)这两个位置中。我们可以看到一个文件叫做debug.keystore。这个文件就是我们的调试的签名文件。

但是在正式包的时候,我们是不能使用调试的签名文件的,我们需要使用对应的签名文件。

首先我们要生成一个签名文件,

生成完成后,我们要配置这个应用的签名,配置签名一般有以下几个参数,详细的参数请查看

https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.SigningConfig.html

上图的4个值分别是 签名的别名,签名的密码,签名的位置,签名的密码

 signingConfigs {
      debug {
      }
        realse {
            keyAlias 'xmg'
            keyPassword '123456'
            storeFile file('/Users/kay/Desktop/release_key.jks')
            storePassword '123456'
       }
    }

定义了两种类型的签名配置。

设置好签名配置,我们要给不同类型的构建设置签名。

 buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.realse
        }
        debug{
            applicationIdSuffix ".debug"
            versionNameSuffix "huangkai"
        }
    }

在上面的代码,我们给发布版设置了签名配置。

为了验证签名配置的情况,我们切换到Terminal对话框,在对话框下输入以下命令

./gradlew assembleRelease

除了可以使用配置的情况,我们也可以使用ide来配置达到一样的效果。

7.2.3.2 定制版本 productFlavors

我们现在在中国开发要面对大量的渠道商(360市场、小米商店、应用宝),为了统计不同的渠道商,我们需要提供不同的版本。这样就会给开发者增加大量的开发任务,而且也出现代码管理的问题。原来在eclipse的环境下,我们需要将代码复制多份,再运行打包脚本,打包成不同的渠道包。但是现在使用gradle进行代码管理,我们就不需要在做这个了,我们可以使用gradle来定制不同的版本,最后gradle会根据一定的规则把代码或者资源进行融合,最后生成我们需要的apk。

在android{}模块内部增加以下的代码

  productFlavors{

      free{

      }
      pay{

      }
  }

我们定义了当前的应用有两个版本,一个是free(免费),pay(收费)。我们预计要打两个版本的包。这里组合起来有四个版本。

  • freeDebug
  • freeRelease
  • payDebug
  • payRelease
定制版本的资源合并

gradle把不同版本的文件夹下的资源进行合并与替换,假设free与pay版本的区别在与某个资源文件。

我们在src文件中创建相关的资源文件夹。

接着我们在各个资源夹中创建一个string.xml资源文件,接着编写以下内容

!!!! 注意,在各个资源文件夹下的内容要不一样才看得到区别。

接着我们编写一个activity放置在main文件夹内,在activity的布局显示这个字符串title。

在左下方选择相应的构建类型,比如说我们选择的是payDebug

编写代码完成后,我们可以使用命令行来构建相应的版本。

 ./gradlew assembleFreeRelease

总结一下,同名的资源文件可以存在不同的版本文件内。

定制版本的java合并

上面的例子我们是通过一个资源来区分应用的版本,在实际的开发中,也存在这样的情况,不同的版本可能有不一样的业务逻辑,所以我们可能需要在不同的版本里面处理java代码。

首先我们还是在之前的项目结构上面进行开发,这里有两个版本,一个free,一个pay。

首先我们先选择一个build variants,在这里我们选择payDebug。

选择完成后,我们打开pay文件夹,我们需要创建一个Activity。我们知道java代码再android studio下面默认是存放在java文件夹下的。所以我们需要创建一个Java文件夹。

同样的步骤我们在free文件夹也操作一遍

我们发现了free 和 pay 的Java文件夹颜色不一样,pay的变成了蓝色,free还是普通的黄色。

我们尝试新建一个class。

很明显在free文件上面没法新建类。为什么呢?

因为我们之前选择的payDebug,ide就只编译了pay文件夹下面的Java类。如果我们选择了freeDebug,情况就刚好相反。

我们在free 和 pay 下面创建了两个同名的activity,并指派了不同的界面。分别运行后,发现每次运行只能选其中一种显示。

接着我们在main文件夹下面创建一个类,Util。接着我们无论在free或者pay下面都无法创建同名的类了,均会提示我们重复创建类错误。

总结一下:

  • 1 main 文件夹下有A类,那个其他版本的文件夹内不能有同名的类A
  • 2 不同版本的相同的文件A类,运行的时候请选择相应的build variants

上面的例子是我们使用productFlavors合并了java代码。

7.2.3.3 定制版本组合 flavorDimensions

在项目中,我们可能会碰到这样的需求,我们可能需要对某个版本提供特殊的功能,但是这个功能与当前的定制版本代码差别不大,如果根据每个定制版本都再新建一个定制版本出来就优点复杂了。比如说我们根据上面的例子来说,当前的应用提供了两个定制版本,一个是pay,一个是free。但是项目在测试的时候,测试组希望根据版本提供有log消息和没有log消息的版本。根据之前的我们需要新建payLog,payNoLog,freeLog,freeNoLog等版本。看起来还行吧,但是如果不止两个而是5个版本,pay,free,….free5,而且log和noLog的区别可能就是几句代码。那个这个项目的结构就太过复杂了。这个时候,我们就可以使用定制版本组合。

定制版本组合怎么操作呢,我们根据需求将代码分成不同的组,不同的组代表不同的功能,组和组可以互相组合,最终形成需要的版本。相对于productFlavors,flavorDimensions是productFlavors的补充选择,可以让我们版本定制更灵活。

以上面的例子来说:

我们可以将版本的需求分成两个维度,一个是支付状态,一个是输出消息状态。

 flavorDimensions "log","pay_status"

首先定义两个维度。下面我们要指定版本属于哪个维度。

productFlavors {

    withLog{
        dimension "log"
    }
    noLog{
        dimension "log"
    }

    free {
        dimension "pay_status"
    }
    pay {
        dimension "pay_status"
    }

}

最后gradle会自动组合版本

7.2.3.4 定制版本依赖

我们在上面的内容学习了依赖的写法,但是之前我们学习依赖的时候,这个依赖的是对这个项目整体生效的。意思就是项目所有的版本都生效,但是在实际开发中,我们可能会碰到这样的情况,比如说我们开发一个应用,这个应用分成收费版本和免费版本。收费版本不需要显示广告。免费版本因为没有付费,需要显示广告。在这里我们需要对我们的定制版本的依赖做细化的区分。原来在eclipse的时候,我们只能通过复制多一份代码来进行实现。现在我们可以同过gradle实现。

 free {
        dimension "pay_status"

        dependencies {
            freeCompile 'com.bm.photoview:library:1.4.1'
        }
    }

在上面的代码我们在版本定制内部添加了一个xxxxCompile的标签,这个意思就是告诉gradle是什么版本的依赖。xxxx是这个版本的名称。

7.2.3.5 packagingOptions 打包选项

我们可以使用这个参数来告诉Gradle什么文件打包到apk内,什么文件不打包,重复文件如何处理等。

  • pickFirst 路径,如果文件匹配这个路径,只有第一个文件打包进apk
  • Merge 合并两个文件进入apk,第二个文件会在第一个文件后
  • Exclude 不打包的文件的路径

    packagingOptions {
    //以下文件不加入apk里
    exclude ‘LICENSE.txt’
    }

未完待续……

展开阅读全文

没有更多推荐了,返回首页