与Gradle的那些年

既然要学习Gradle,首先要知道它是什么,它又能干什么,以及怎么使用它。

Gradle是什么?

Gradle 是以Groovy为基础,面向java应用,基于DSL语法的自动化构建工具。
是google引入,替换ant和maven的新工具,其依赖兼容maven和ivy。

Gradle能干什么?

1.更容易重用资源和代码;
2.可以更容易创建不同的版本的程序,多个类型的apk包;
3.更容易配置,扩展;
4.更好的IDE集成;

Android Studio中的android项目通常至少包含两个build.gradle文件,一个是project范围的,另一个是module范围的,由于一个project可以有多个module,所以每个module下都会对应一个build.gradle。

project->build.gradle

project下的build.gradle是整个project的配置,主要配置gradle 版本及 全局依赖仓库、库或者其他全部参数。android studio 现在重要仓库采用jcenter(),之前版本放在mavenCentral。另外有时还没有加入jcenter()仓库的第三方库,也需要在这里配置他们的库地址。需要在这里配置,才能将第三方库拉下来。

apply from: "config.gradle"
buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
        jcenter()
        maven {
            url 'https://jitpack.io'
        }
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'com.sensorsdata.analytics.android:android-gradle-plugin2:1.0.2'
        classpath "io.realm:realm-gradle-plugin:4.1.1"
    }
}
allprojects {
    repositories {
        mavenLocal()
        mavenCentral()
        jcenter()
        maven {
            url 'https://jitpack.io'
        }
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
    }
}

apply from: “config.gradle” :外部配置文件,下面会讲到
buildscript和allprojects中都包含有repositories,是因为他们的作用域不同,buildscript中的仓库是gradle脚本自身需要的资源,而allprojects下的仓库是项目所有模块需要的资源。

config.gradle

ext {

    android = [
            //编译SDK的版本
            compileSdkVersion: 26,
            //buildtool 的版本
            buildToolsVersion: "26.0.2",
            //支持最小android sdk 版本
            minSdkVersion    : 17,
            // 目标版本
            targetSdkVersion : 26
            //应用版本号
            versionCode = 1
            //应用版本名称
            versionName = "v1.0.0"
    ]

    dependVersion = [
            support: "26.0.2"
    ]
    //服务器一 路由地址
    serverOneAPIUrl = [
            api_url_debug  : "\"https://devone.gradle.cn/\"",//开发
            api_url_test   : "\"https://testone.gradle.cn/\"",//内测 
            api_url_preview: "\"https://preone.gradle.cn/\"",//预览
            api_url_release: "\"https://one.gradle.cn/\""//正式
    ]
   //服务器二 路由地址
   serverTwoAPIUrl = [
            api_chat_url_debug  : "\"https://devtwo.gradle.cn/\"",//开发
            api_chat_url_test   : "\"https://testtwo.gradle.cn/\"",//内测
            api_chat_url_preview: "\"https://pretwo.gradle.cn/\"",//预览
            api_chat_url_release: "\"https://two.gradle.cn/\""//正式
    ]
    //服务器三 路由地址
    serverThreeUrl = [
            api_url_debug  : "\"https://devthree.gradle.cn/\"",//开发
            api_url_test   : "\"https://testthree.gradle.cn/\"",//内测
            api_url_preview: "\"https://prethree.gradle.cn/\"",//预览
            api_url_release: "\"https://three.gradle.cn/\""//正式
    ]

    dependencies = [
            //------------- 分包  ------------
            multidex                  : "com.android.support:multidex:1.0.1",

            // ------------- Android -------------
            supportV4                 : "com.android.support:support-v4:${dependVersion.support}",
            appcompatV7               : "com.android.support:appcompat-v7:${dependVersion.support}",
            design                    : "com.android.support:design:${dependVersion.support}",
            cardview                  : "com.android.support:cardview-v7:${dependVersion.support}",
            junit                     : "junit:junit:4.12",

            // ------------- reyclerview ------------
            recyclerview              : "com.android.support:recyclerview-v7:${dependVersion.support}",

            // ------------- 网络请求 -------------
            retrofit                  : 'com.squareup.retrofit2:retrofit:2.3.0',
            retrofit_rxjava           : 'com.squareup.retrofit2:adapter-rxjava2:2.3.0',
            retrofit_converter_gson   : 'com.squareup.retrofit2:converter-gson:2.3.0',
            okhttp_logging_interceptor: 'com.squareup.okhttp3:logging-interceptor:3.8.0',

            // ------------- 图片加载 -------------
            glide                     : 'com.github.bumptech.glide:glide:4.3.1',
            glideAp                     : 'com.github.bumptech.glide:compiler:4.3.1',

            // ------------- 通信 -------------
            eventbus                  : 'org.greenrobot:eventbus:3.0.0',

            // ------------- RxAndroid -------------
            rxAndroid                 : 'io.reactivex.rxjava2:rxandroid:2.0.1',
            rxJava                    : 'io.reactivex.rxjava2:rxjava:2.0.1',

            // ------------- json解析 -------------
            gson                      : 'com.google.code.gson:gson:2.8.1',
    ]
}

项目配置文件,ext全局变量,在每个module的build.gradle文件中都可以随时引用

module->build.gradle

apply plugin: 'com.android.application'
android {
    compileSdkVersion rootProject.ext.android.compileSdkVersion
    buildToolsVersion rootProject.ext.android.buildToolsVersion

    //加载本地配置文件local.properties
    Properties properties = new Properties()
    InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream();
    properties.load(inputStream)

    //安卓构建过程需要配置的参数
    defaultConfig {
        applicationId "com.demo.gradle"
        minSdkVersion rootProject.ext.android.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion
        multiDexEnabled true
        versionCode rootProject.ext.android.versionCode
        versionName rootProject.ext.android.versionName
    }
    //ndk配置参数
    ndk {
        abiFilters "armeabi-v7a", "arm64-v8a", "x86"
    }
    //java版本号
    compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
    }
    //渠道Flavors_打包
    productFlavors {
        //可以设置不同渠道渠道号,应用名称
        dev { // 开发
            buildConfigField "String", "CHANNEL_NUMBER", '"11111"'
        }
        '360' {
            buildConfigField "String", "CHANNEL_NUMBER", '"11112"'
        }
        GooglePlay {
            buildConfigField "String", "CHANNEL_NUMBER", "11113"'
    }

    //定义apk文件名称格式
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}_${releaseFormatTime()}.apk")
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }

    //签名
    signingConfigs {
        release {
            keyAlias properties.getProperty('keyAlias')
            keyPassword properties.getProperty('keyPassword')
            storeFile file(properties.getProperty('storeFile'))
            storePassword properties.getProperty('storePassword')
        }
    }

    buildTypes {
        debug {
            minifyEnabled false
            zipAlignEnabled false
            shrinkResources false
            (..各个服务器的dubug路由地址..)
        }

         preview {
            debuggable false // 是否保留调试信息
            minifyEnabled true  //是否混淆
            zipAlignEnabled true // 包优化
            shrinkResources true // 移除不必要的资源
            // 签名
            signingConfig signingConfigs.release
            // 代码混淆规则文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            (..各个服务器的preview路由地址..)
        }

        release {
            //加上后缀
            applicationIdSuffix ".release"
            minifyEnabled true //是否混淆
            zipAlignEnabled true // zip对齐优化
            shrinkResources true // 移除不必要的资源

            // 不显示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"

            // 签名
            signingConfig signingConfigs.release
            //混淆文件的位置
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            (..各个服务器的release路由地址..)
        }
    }

    // 为了解决部分第三方库重复打包了META-INF的问题
    packagingOptions {
        exclude 'META-INF/ASL2.0'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/MANIFEST.MF'
        exclude 'sign.properties'
        exclude 'keystore.jks'
    }

    //执行lint检查,有任何的错误或者警告提示,都会终止构建,我们可以将其关掉。
    lintOptions {
        abortOnError false
    }
   
    dataBinding {
        enabled = true
    }

    dexOptions {
        //支持最大工程模式
        jumboMode = true 
        javaMaxHeapSize "10g"
        //使用增量模式
        //incremental false

        preDexLibraries = false //预编译
        threadCount = "8" //线程数目
    }

}
//定义打包时间格式化
def releaseFormatTime() {
    return new Date().format("yyyy-MM-dd HH:mm", TimeZone.getDefault())
}

// 发布的日更新包时间尾巴
def releaseFormatDayTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getDefault())
}
// 定义打包时间戳
def releaseTime() {
    return new Date().getTime();
}

repositories {
    flatDir {
        dirs 'aars'
    }
    maven {
        url 'https://maven.google.com/'
        name 'Google'
    }
}
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile rootProject.ext.dependencies.multidex
    compile rootProject.ext.dependencies.bugtags
    //------------  Android support  -----------
    //compile rootProject.ext.dependencies.supportV4
    compile rootProject.ext.dependencies.design
    compile rootProject.ext.dependencies.appcompatV7
    compile rootProject.ext.dependencies.cardview
    //------------  recyclerview  -------------
    compile rootProject.ext.dependencies.recyclerview
    compile rootProject.ext.dependencies.recyclerview_divider
    //------------  通信  --------------
    compile rootProject.ext.dependencies.eventbus
    //------------  网络  ----------
    compile project(':api')
    //------------  rxAndroid-----------
    compile rootProject.ext.dependencies.rxAndroid
    compile rootProject.ext.dependencies.topsnackbar
    compile rootProject.ext.dependencies.glide
    annotationProcessor rootProject.ext.dependencies.glideAp
}

1.buildTypes是指建构的类型,一般只用两种默认类型 debug 和 release,顾名思义 debug 用来配置开发过程中的一些内容;release 用来配置正式发布版本的内容。有时我们需要发布介于debug与release之间的preview 版本。
2.签名信息,可以直接将信息写到gradle.properties或者,然后在然后在build.gradle中引用即可。
3.多渠道的关键在于定义不同的product flavor。这里的flavor名如果是数字开头,必须用引号引起来。

BuildConfig

在build.gradle中配置buildConfigField参数,编译后会在..\app\build\generated\source\buildConfig文件夹下会自动生成对应版本对应module的BuildConfig.java。BuildConfig就会包含对应版本的配置信息。程序中可以直接引用这些数据。例如BuildConfig.DEBUG。

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.demo.gradle";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "wandoujia";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "v1.0.0_debug";
  public static final int BUILD_TYPE_INT = 0;
  public static final boolean IS_DEBUG = true;
  (..各个服务器路由地址..)
}

module 调整目录结构sourceSets

默认情况下,java文件和resource文件分别在src/main/java和src/main/res目录下,在build.gradle文件,andorid{}里面添加下面的代码,便可以将java文件和resource文件放到src/java和src/resources目录下。

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

Gradle常用命令

./gradlew, ./代表当前目录,gradlew代表 gradle wrapper,意思是gradle的一层包装,大家可以理解为在这个项目本地就封装了gradle,即gradle wrapper, myAPP/gradle/wrapper/gralde-wrapper.properties**文件中声明了它指向的目录和版本。只要下载成功即可用grdlew wrapper的命令代替全局的gradle命令。

理解了gradle wrapper的概念,下面一些常用命令也就容易理解了。

./gradlew 下载更新gradle
./gradlew -v 版本号
./gradlew assemble 构建项目输出
./gradlew check 运行检测和测试任务
./gradlew clean 清除9GAG/app目录下的build文件夹
./gradlew build 运行check和assemble,检查依赖并编译打包
这里注意的是 ./gradlew build 命令把debug、release环境的包都打出来,如果正式发布只需要打Release的包,该怎么办呢,下面介绍一个很有用的命令 assemble<build type=”” name=””>, 如</build>
./gradlew assembleDebug 编译并打Debug包
./gradlew assembleRelease 编译并打Release的包所有渠道的
./gradlew assembleWandoujiaRelease 编译并打包豌豆荚的Release版本
./gradlew assembleWandoujia 编译并打包豌豆荚的所有版本
./gradlew installRelease Release模式打包并安装
./gradlew uninstallRelease 卸载Release模式包

    原文作者:Ent_zhaolu
    原文地址: https://www.jianshu.com/p/5feb9279697d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞