Android项目构建之路——AndroidGradle

    • Gradle Wrapper
      • DSL的概念:
      • Gradle Wrapper的概念
      • Wrapper配置
      • gradle-wrapper.properties
      • 自定义Wrapper Task
    • Gradle构建脚本的基础
      • settings文件
      • Build文件
    • Gradle插件
      • 插件的作用
      • 插件应用
        • 二进制插件
        • 应用脚本插件
        • 应用第三方发布的插件
    • Java Gradle插件
      • 配置第三方依赖
      • compile和testCompile(implementation和testImplementation)
        • api(compile)指令
        • implementation指令
        • compileOnly
        • annotationProcessor与compileOnly的区别
      • SourceSet源码集合概念
    • Android Gradle插件
      • 简介:
      • Android Gradle插件的分类:
      • buildscript{}配置
      • Android Gradle 任务
    • Android Gradle高级自定义
      • 使用共享库uses-library
      • 批量修改生成的apk文件名
      • 隐藏签名文件信息
      • 动态配置AndroidManifest文件(多渠道打包)
      • 突破65535方法限制
      • DEX选项配置
    • Android Gradle 多项目构建
      • Android项目区别
      • Android多项目设置
      • 库项目引用和配置
    • AndroidGradle测试
      • Lint 支持

能有那么一两句,说到你心里,惟愿足以!

Gradle Wrapper

Gradle是一款非常优秀的构建系统工具,它的DSL基于Groovy实现,可以让你很方便的通过代码控制这些DSL来达到你构建的目的。Gradle构建的大部分功能都是通过插件的方式来实现,所以非常灵活方便,如果内置插件不能满足的要求你可以自定义自己的插件。

DSL的概念:

DSL(Domain Specific Language)领域特定语言,及时专门关注某一领域的语言,她在于专,而不是全,所以才叫领域特定的,而不是像Java这用通用全面的语言。
Gradle就是一门DSL,它是基于Groovy的,专门解决自动化构建的DSL。开发者主要按照Gradle DSL定义的语法,书写相应的Gradle脚本就可以达到自动化构建的目的。

Gradle Wrapper的概念

所谓wapper其实就是对gradle的一层包装,便于在团队开发过程中统一gradle构建的版本,这样大家都已使用统一的gradle 版本进行构建,避免因为gradle版本不统一带来的不必要问题。
我们在项目开发中,用的都是Wrapper这种方式,而不是自己下载zip压缩包,配置gradle的环境的方式,wrapper在Windows下是一个批处理脚本,在Linux下是一个shell脚本,当你使用wrapper启动gradle的时候,wrapper会检查gradle有没有被下载关联,如果没有将会从配置的地址(一般是gradle官方库)进行下载并运行构建。这对开发人员是非常方便,因为不用去专门配置环境,只要执行wrapper命令,它会帮你搞定一切。这种方式也方便我们在服务器上做持续集成(CI),因为我们不用再服务器上配置Gradle环境。

Wrapper配置

–gradle-version 用于指定使用的gradle版本
gradle-distribution-url 用于指定下载Gradle发行版的URL地址

gradle-wrapper.properties

该配置文件是gradle wrapper的相关配置文件,是由Wrapper Task生成的额,我们上述的配置都会写入该文件,字段说明如下:

#Tue May 01 18:18:48 CST 2018

#下载gradle压缩包解压后储存的主目录
distributionBase=GRADLE_USER_HOME

##相对于distributionBase的解压后的Gradle压缩包的路径
distributionPath=wrapper/dists

#同distributionBase,只不过是存放zip压缩包的
zipStoreBase=GRADLE_USER_HOME

#同distributionPath,只不过是存放zip压缩包的
zipStorePath=wrapper/dists

#Gradle发行版压缩包的下载地址
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

Android项目构建之路——AndroidGradle_第1张图片

我们关注的就是distributionUrl这个字段,这个决定你的gradle wrapper依赖哪个gradle版本,我们通常都会把bin改成all,这样开发过程中就可以gradle的源码了。

自定义Wrapper Task

在build.gradle构建文件中录入以下脚本:其中task并不是一个关键字,其实他是Project对象的一个函数,

task wrapper(type: Wrapper){
     gradleVersion = '4.4'
    archiveBase ='GRADLE_USER_HOME'
    archivePath ='wrapper/dists'
    distributionBase='GRADLE_USER_HOME'
    distributionPath='wrapper/dists'
    distributionUrl='https\\://services.gradle.org/distributions/gradle-4.4-all.zip'
}

Android项目构建之路——AndroidGradle_第2张图片

这样在执行gradle wrapper的时候,就是默认生成4.4版本的wrapper,而不用使用-gradle-version 4.4进行指定了。

Gradle构建脚本的基础

settings文件

在Gradle中定义了一个设置文件,用于初始化以及工程树的配置。设置文件的默认名字是setting.gradle,放在根工程目录下。
设置文件大多数的作用都是为了配置子工程,在Gradle中多工程是通过工程树表示的,就相当于AS看到的project和module的概念一样。
一个子工程只有在setting文件里配置了Gradle才会被识别,才会在构建的时候被包含进去:
Android项目构建之路——AndroidGradle_第3张图片

Build文件

每个Project都会有一个Build文件,该文件是Project构建的入口,可以在这里针对该Project进行配置,比如配置版本,需要哪些插件,依赖哪些库等。rootProject也不例外,他可以获取到所有的childProject,所以在Root Project的Build文件里我们可以对Child Project统一配置,比如应用的插件,依赖的Maven中心库等。比如配置所有Child Project的仓库为jcenter,这样我们依赖的的jar包就可以从jcenter中心库中下载了:

allprojects {
    repositories {
        google()
        jcenter()
    }
}

Android项目构建之路——AndroidGradle_第4张图片

除了allprojects还有subprojects,他们是两个方法,接受一个闭包(一段代码片)作为参数,对工程进行遍历,遍历的过程中调用我们自定义的闭包,所以我们可以在闭包里配置,打印,输出或者修改Project的属性都可以。

Gradle插件

插件的作用

  1. 可以添加任务到你的项目中,帮助完成测试,编译,打包等。
  2. 可以添加依赖配置大你的项目中,我们可以通过他们配置我们项目在构建过程中需要的依赖,例如第三的库等。
  3. 可以向项目中现有的对象类型添加新的扩展属性,方法等,让你可以使用他们帮助我们配置,优化构建,比如android{}这个配置块就是Android Gradle插件为project对象添加的一个扩展。
  4. 可以对项目队形一些约定,比如应用Java插件后,约定src/main/java目录下使我们的源代码存放位置,在编译的时候也是编译这个目录下Java源代码文件。

这就是插件,我们只需要按照他约定的方式,使用它提供的任务,方法,扩展,就可以对我们项目进行构建。

插件应用

二进制插件

二进制插件就是实现了org.gradle.api.Plugin接口的插件,它们可以有plugin id,例如:

apply plugin :'java'
上边的语句就是把Java插件应用到我们的项目中了,’java’就是Java插件的plugin id,他是唯一的。对于Gradle自带的核心插件都有一个容易记住的短名,成为plugin id,
二进制插件一般都是被打包在一个jar里独立发布的,比如我们自定义的插件,在发布的时候我们也可以为其指定plugin id,这个plugin id 最好是一个全限定名字,就像包名那样,避免重复

应用脚本插件

应用脚本插件,其实就是把这个脚本加载进来,和二进制插件不同的是它使用的是from关键字,后边紧跟的是一个脚本文件,可以是本地的,也可以是网络的(要使用HTTP URL )

apply from:'version.gradle'

version.gradle

//用ext标记自定义版本号属性
ext {
    versionName='1.0.0'
    versionCode=1
}

Android项目构建之路——AndroidGradle_第5张图片

应用第三方发布的插件

第三方发布的作为jar的二进制插件,我们在应用的时候,必须要现在buildscript{}里配置其classpath才能使用,这个不像Gradle为我们提供的内置插件。比如我们的Android Gradle插件,就属于Android发布的第三方插件,如果要使用就要先配置;

buildscript {

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.1'


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

buildscript{}块是一个在构建项目之前,为项目进行前期准备和初始化相关配置依赖的地方,配置好所需的依赖,就可以应用插件了:

apply plugin: 'com.android.application'

Java Gradle插件

配置第三方依赖

要想使用第三方依赖,你要告诉Gradle如何找到这些依赖,也就是依赖的配置,一般情况下都是从仓库中查找我们需要的jar包,首先要告诉gradle我们要使用什么类型的仓库,这些仓库的位置,这样就知道从哪里去下载jar包

repositories {
    flatDir {
        dirs 'libs'//自定义把jar包发布到本地目录

    }
    maven { url "https://jitpack.io" }
    mavenCentral()
}

compile和testCompile(implementation和testImplementation)

3.0以上的AS用implementation和testImplementation,以下的AS已经弃用了compile和testCompile,我们用最新的规定说明

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    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'
}

这里解释一下依赖的区别

api(compile)指令

完全等同于compile指令,依赖可以传递,没区别,你将所有的compile改成api,完全没有错。

implementation指令

这个指令的特点就是,对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,也就是将该依赖隐藏在内部,而不对外部公开。
简单的说,就是使用implementation指令的依赖不会传递。
依赖首先应该设置为implementation的,如果没有错,那就用implementation,如果有错,那么使用api指令。使用implementation会使编译速度有所增快。使用implementation会使编译速度有所增快:比如我在一个library中使用implementation依赖了gson库,然后我的主项目依赖了library,那么,我的主项目就无法访问gson库中的方法。这样的好处是编译速度会加快,我换了一个版本的Gson库,但只要library的代码不改动,就不会重新编译主项目的代码。

compileOnly

等同于provided,只在编译时有效,不会参与打包,不会包含到apk文件中。可以用来解决重复导入库的冲突

annotationProcessor与compileOnly的区别

annotationProcessor与compileOnly都是只编译并不打入apk中,他俩到底有什么区别呢?扮演的角色不一样,annotationProcessor作用是编译时生成代码,编译完真的就不需要了,compileOnly是有重复的库,为的是剃除只保留一个库,最终还是需要的。

SourceSet源码集合概念

SourceSet是Java插件用来描述和管理源代码及其资源的一个抽象概念,是一个Java源代码文件和资源文件的集合。通过源集我们可以很方便的访问源代码目录,有了源集,我们就能针对不同的业务和应用对我们源代码进行分组,比如用于主要业务产品的main以及用于单元测试的test,Java插件在Project下为我们提供一个sourceSet属性以及一个sourceSets{}闭包来访问和配置源集。sourceSet{}闭包配置的都是SourceSet对象,以下就是设置main这个源集的Java源文件和资源文件的存放目录

sourceSets{
    main{
        java {
            java.srcDirs = ['src/main/java']
        }
        resources {
            java.srcDirs = ['src/main/resources']
        }
    }
}

Android Gradle插件

简介:

从gradle的角度看,Android其实就是Gradle的一个第三方插件,从Android的角度看,Android插件是基于Gradle构建的。

Android Gradle插件的分类:

  • APP插件id:com.android.application. App应用工程,可以生成一个可运行的apk应用;
  • Library 插件 id:com.android.library. 可以生成AAR包给其他的APP工程公用,就和我们的jar一样,但是它包含了Android的资源等信息是一个特殊的jar包;
  • Test 插件id:com.android.test. 用于对APP工程或者Library库工程进行单元测试。

buildscript{}配置

这部分可以写在根工程的build.gradle脚本文件中,这样所有的子工程就不用重复配置了。

apply from:'version.gradle'
buildscript {

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.1'

    }
}

moudle下的build.gradle脚本中就可以应用AndroidGradle插件了

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.gradle.ytf.gradleapplication"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
  • android{}是Android插件提供的一个扩展类型,可以让我们自定义Android Gradle工程。
  • compileSdkVersion 是编译所依赖的AndroidSDK版本,这里是API Level;
  • buildToolsVersion是构建该Android工程所用构建工具的版本。可以在AndroidSDK目录里看到,它是一个工具包,包括appt,dex等工具,我们可以通过buildToolsVersion方法赋值,也可以通过android.buildToolsVersion这个属性读写他的值。
  • defaultConfig 是默认配置,他是一个ProductFlavor。允许我们根据不同的情况同事生成多个不同的apk包,就是多渠道打包,如果不单独配置,会为这个ProductFlavor使用默认的defaultConfig 的配置
  • minSdkVersion 15是最低支持的Android系统的API Level
  • targetSdkVersion 27 表明我们是基于哪个Android版本开发的,这里是27
  • versionCode表明我们的APP应用内部的版本号,一般用于控制APP升级。
  • versionName “1.0” 表明我们的APP应用的版本名称,用户可以看到就是我们发布版本,这里是1.0
  • applicationId 是ProductFlavor的一个属性,用于指定生成APP的包名,默认为null,构建时候回从manifest文件中读取,
  • testApplicationId,用于配置测试APP的包名,默认情况下是applicationId+“.test”。一般默认即可
  • testInstrumentationRunner,用于配置单元测试时使用的Runner,默认使用的是android.test.InstrumentationTestRunner,可以修改。
  • signingConfig 配置默认的签名信息,生成APP签名。
  • applicationIdsuffix,buildType的属性,用于配置基于默认applicationid的后缀,用于构建debug.apk
  • debuggable 用于配置是否生成一个可供调试的apk
  • jniDebuggable和debuggable类似,用于配置是否生成一个可供调试jni(C/C++)代码的apk
  • multiDexEnable 用于配置是否启用自动拆分多个dex的功能(方法数超过65535的时候)
  • shrinkResources 用于配置是否自动清理未使用的资源,默认false
  • 启用zipAlign优化,提高系统和应用的运行效率,更快的写入apk中的资源,降低内存的使用
   buildTypes {
        release {
            minifyEnabled false
            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

以上所有配置对用的都是ProductFlavor类里的方法或者属性。
- buildTypes 是一个域对象,NamedDomainObjectContainer类型,和SourceSet一样,里边有release,debug等,
- minifyEnabled 是否为该构建类型启用混淆
- resConfigs ‘zh’//只保留zh资源其他非zh都不会被打包到apk中,是资源限定符
- proguardFiles,当我们启用混淆时,所使用的proguard的配置文件,我们通过他配置如何进行混淆,比如混淆的级别,哪些类和方法不进行混淆等。对应BuildType里的proguardFiles方法,可以接受一个可变参数。所以我们可以配置多个配置文件,比如

 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

getDefaultProguardFile是Android扩展的一个方法,它可以获取你的AndroidSDK目录下默认的proguard配置文件。在android-sdk/tools/proguard/目录下,文件名及时我们传入的参数名字proguard-android.txt。全限定写法:android.getDefaultProguardFile,只需要传递一个文件名给这个方法,就会返回tool/proguard目录下的该文件的绝对路径,方法原型为:

 public File getDefaultProguardFile(String name) {
        if (!ProguardFiles.KNOWN_FILE_NAMES.contains(name)) {
            extraModelInfo
                    .getSyncIssueHandler()
                    .reportError(
                            EvalIssueReporter.Type.GENERIC, ProguardFiles.UNKNOWN_FILENAME_MESSAGE);
        }
        return ProguardFiles.getDefaultProguardFile(name, project);
    }

Android Gradle 任务

Android插件是基于Java的插件,所以Android插件基本上包含了所有Java插件的功能,包括集成的任务,比如assemble ,check,build等,还添加了以下任务

  1. connectedCheck 在所有连接的设备或者模拟器上运行check检查
  2. deviceCheck 通过API连接远程设备运行checks.他被用于CI(持续集成)服务器上。
  3. lint 在所有的ProductFlavor上运营lint检查。
  4. install和uninstall类的任务可以直接在我们已连接的设备安装或者卸载你的APP。
  5. signingReport 可以打印APP的签名
  6. androidDependencies可以打印Android的依赖。

Android Gradle高级自定义

使用共享库uses-library


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gradle.ytf.gradleapplication">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <uses-library
            android:name="com.google.android.maps"
            android:required="true">uses-library>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>
    application>

manifest>

这样我们就声明了需要使用maps这个共享库,声明之后,在安装apk包的时候,系统会根据我们的定义,帮助检测手机系统是否有我们需要的共享库,因为设置了android:required=”true”,如果手机系统不满足,将不能安装该应用。另外还有两种库,一种是add-ons库,大部分是第三方厂商或者公司开发,让开发者使用,不暴露具体标准实现,还有一类是optional库,一般用来兼容旧版本API,比如:org.apache.http.legacy,这是一个HTTPClient的库,从API23开始,标准SDK中不再包含HTTPclient库,要想使用,就要使用org.apache.http.legacy这个可选库。

批量修改生成的apk文件名

//    applicationVariants.all { variant ->
//        if (variant.buildType.name == "release") {
//            variant.outputs.each { output ->
//                def appName = 'hibook'
//                def oldFile = output.outputFile
//                def buildName
//                def releaseApkName
//
//                variant.productFlavors.each { product ->
//                    buildName = product.name
//                }
//
//                releaseApkName = appName + '-' + buildName + '-' + getDate() + '.apk'
//                output.outputFile = new File(oldFile.parent, releaseApkName)
//            }
//        }
//    }

    //AS3.0以上版本
    android.applicationVariants.all { variant ->
        variant.outputs.all {
            if (variant.name.endsWith("Debug")) {
                //debug包
                outputFileName = "$applicationId _v${defaultConfig.versionName}_${getDate()}_code${defaultConfig.versionCode}_debug.apk"
            } else {
                //release包
                variant.outputs.each { output ->
                def appName = 'hibook'
                def oldFile = output.outputFile
                def buildName
                def releaseApkName

                variant.productFlavors.each { product ->
                    buildName = product.name
                }

                releaseApkName = appName + '-' + buildName + '-' + getDate() + '_release.apk'
//                output.outputFile = new File(oldFile.parent, releaseApkName)
                    outputFileName =releaseApkName
//                  outputFileName = "$applicationId _v${defaultConfig.versionName}_code${defaultConfig.versionCode}_${getDate()}_release.apk"
            }

            }
        }
    }

}

//获取时间戳
static def getDate() {
    def date = new Date()
    def formattedDate = date.format('yyyy-MM-dd-HH_mm')
    return formattedDate
}

隐藏签名文件信息

把签名文件和密钥信息放到服务器上,打正式包的时候去读取即可。

  signingConfigs{
        def appStoreFile=System.getenv("STORE_FILE")//获取名字为“STORE_FILE”的环境变量的值
        def appStroePassword=System.getenv("STORE_PASSWORD")
        def appKeyAlias=System.getenv("KEY_ALIAS")
        def appKeyPassword=System.getenv("KEY_PASSWORD")
//        当不能从环境变量中获得签名信息的时候,就使用项目中带的dubug签名
        if(!appStoreFile||!appStroePassword||!appKeyAlias||!appKeyPassword){
            appStoreFile="debug.keystore"
            appStroePassword="android"
            appKeyAlias="androiddebugkey"
            appKeyPassword="android"
        }
        release{
            storeFile file(appStoreFile)
            storePassword appStroePassword
            keyAlias appKeyAlias
            keyPassword appKeyPassword
        }
    }

动态配置AndroidManifest文件(多渠道打包)

<meta-data android:value="Channel ID" android:name="UMENG_CHANNEL">meta-data>

动态配置AndroidManifest文件就是可以在构建过程中动态修改manifest文件的一些内容,比如上述的友盟统计,就是要指定渠道名Channel ID,通过使用manifestPlaceholder,Manifest占位符,manifestPlaceholder是ProductFlavor的一个属性,是一个map类型,所以我们可以同时配置多个占位符

android{

 productFlavors{
        google{
            manifestPlaceholders.put("UMENG_CHANNEL","google")
        }
        baidu{
            manifestPlaceholders.put("UMENG_CHANNEL","baidu")
        }
    }
}

上述例子我们就定义了两个渠道,Google和baidu,并且配置了他们的manifestPlaceholders,他们的key都是一样,就是我们在manifest文件中的占位符变量,在构建的时候它会把manifest文件中所有占位符变量为UMENG_CHANNEL的内容替换为manifestPlaceholders中对用的value值
使用:

  productFlavors {
        Baidu {
        }
        Server {
        }
        Xiaomi {
        }
        Huawei {
        }
        Vivo {
        }
        Oppo {
        }
        Tencent {
        }

    }

    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: flavor.name]
    }

或者:

data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}"/>
productFlavors {
        Baidu {
        }
        Server {
        }
        Xiaomi {
        }
        Huawei {
        }
        Vivo {
        }
        Oppo {
        }
        Tencent {
        }

    }

    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: flavor.name]
    }

突破65535方法限制

对于android5.0之前系统的虚拟机,它只认识一个DEX,名字还必须是class.dex.所以必须在程序入口application处进行控制,如果没有自定义application,直接使用MultiDexApplication即可,首先添加依赖:
implementation ‘com.android.support:multidex:1.0.1’
build.gradle

 defaultConfig {
        applicationId "com.gradle.ytf.gradleapplication"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        multiDexEnabled true//启用multidex
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

在manifest文件中配置:(5.0以后不需要配置)

android:name="android.support.multidex.MultiDexApplication"

如果有自定义的Application,并且直接继承Application,那么直接改继承为MultiDexApplication即可
如果自定义的application是继承其他第三方提供的Application,就不能改变继承,重写attachBaseContex()方法

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(base);

    }

DEX选项配置

  1. incremental属性 用来配置是否启用dx的增量模式,默认为false,可以提高速度,但是限制多,要慎用,启动改为true即可。
android{
 dexOptions{
        incremental true     }
}
  1. javaMaxHeapSize 配置执行dex命令时候,为其分配的最大内存,主要用来解决执行dx时内存不够用的情况,前提是你的计算机要有足够的内存够用,例如:javaMaxHeapSize '4g'
  2. jumboMode 用来配置是否开启jumbo模式,有时候项目比较大,函数超过了65535个,就要强制开启此模式才能构建成功 jumboMode true
  3. preDexLibraries 配置是否预执行dex Libraries库工程,开启后会大大提高构建速度,但是会影响clean构建的速度,默认为true,当我们要生成多个dex或者库工程有冲突的时候要改为false ,preDexLibraries false
  4. threadCount 是integer类型,用来配置Android Gradle运行dx命令时使用的线程数量,适当的数量可以提高dx的效率。

Android Gradle 多项目构建

Android项目区别

android项目一般分为库项目,应用项目,测试项目,对应Android Gradle的3中插件,分别是com.android.library、com.android.application、com.android.test。
库项目一般和Java库相似,多一些Android特有的资源配置,一般具有公用特性的类,资源等都可以抽象成一个库工程,可以被其他项目引用,还有一种情况,就是工程复杂,可以根据业务把工程分成一个个库项目,然后通过一个应用项目引用他们,组合起来就是一个复杂的APP了。
应用项目,一般只有一个,可以打包成apk,如果要发布不同特色的APP,但是又是同类APP,就会有多个应用项目,比如QQ的标准版,轻聊版等
测试项目,是为了对APP进行测试而创建的,是Android基于Junit提供的一种测试Android项目的框架方法。

Android多项目设置

在setting.gradle里边配置

include ':app',':libraries libs1',':libraries libs2'

如果路径太多可以指定配置

include ':libs1'
project(':libs1').projectDir = new File(rootDir,'chapter09/libs1')

通过如上方法我们直接指定项目的目录即可。这样我们整个多项目配置的架子就搭好了,增减项目可以模拟这个框架。

库项目引用和配置

Android库项目引用和Gradle是一样的,都是通过dependencies实现:

dependencies { compile project(':libraries libs1')}

这样就引用了这个lib库项目沿用了Gradle的依赖关系。

AndroidGradle测试

Lint 支持

android为我们提供了针对代码,资源的优化工具Lint,可以帮助我们检查出哪些资源没有被使用,哪些使用了新的api,哪些资源没有国际化等,会生成一份报告,告诉我们哪些需要优化。

  1. abortOnError false 用于配置Lint发现错误时是否退出Gradle构建
  2. check ‘NewApi’//检测issue id 为’NewApi’属性是一个Set集合,方法对应两个,参数不同,写法有三种
  3. lintOptions{
        abortOnError false //用于配置Lint发现错误时是否退出Gradle构建
    //        check 'NewApi'//检测issue id 为'NewApi'属性是一个Set集合,方法对应两个,参数不同
        def checkSet =new HashSet()
        checkSet.add("NewApi")
        checkSet.add("InlinedApi")
        check=checkSet
    //        使用方法传参check
        check 'NewApi','InlinedApi'
    }
    
    }
    public void  check(String id){
    check.add(id)
    }
    public void check(String...ids){
    for (String id:ids) {
        check(id)
    }
    }

Android项目构建之路——AndroidGradle_第6张图片

  1. checkAllWarnings true 检测所有警告的issue,包括哪些默认被关闭的issue,false则不检查

  2. checkReleaseBuilds true 在release构建构成中,Lint是否检查知名的错误问题,默认是ture,一旦发现有‘fatal’级别的问题,release构建终止

  3. explainIssues true 配置Lint检测出的错误报告是否应该包含解释说明,默认开启,也就是报告文档中会有就该问提的解释说明
  4. noLines true 默认为true,表示error输出将不会包含源代码的行号
  5. quiet true 安静模式 为true意味着Lint分析的进度和其他信息将不会显示
  6. showAll true //用于标记是否显示所有输出,比如位置信息,并且不会对过长的信息进行截断。
  7. textOutput(“E:/ytf文件”) //指定生成text格式的报告的路径,类似xmlOutput,生成xml格式的报告
  8. textReport true //配置是否生成text报告,默认false,类似xmlReport
  9. warningsAsErrors false //是否把所有的警告当成错误处理。

你可能感兴趣的:(Exception,Android,Gradl,说)