Android使用gradle入门

1.gradle是什么?

Gradle是新一代的自动化构建工具一个基于JVM的构建工具,它是一个独立的项目,跟AS,Android无关,类似Ant,Maven这类构建工具都是基于xml来进行描述的,很臃肿,而Gradle采用的是一种叫做Groovy的语言,语法跟Java语法很像,但是一种动态语言,而且在Java基础上做了不少改进,用起来更加简洁、灵活,而且Gradle完全兼容Maven、lvy,这点基本上宣布Maven、lvy可以被抛弃了,Gradle的推出主要以Java应用为主,当然目前还支持Android、C、C++

构建工具就是对你的项目进行编译、运行、签名、打包、依赖管理等一系列功能集合,传统的构建工具有Make、Ant、Maven、lvy等,而Gradle是新一代的自动化构建工具;

gradle优势(gradle提供了什么)

1). 一种可切换的,像maven一样的基于约定的构建框架,却又从不锁住你(约定优于配置)

2). 强大的支持多工程的构建

3). 强大的依赖管理(基于Apache Ivy),提供最大的便利去构建你的工程

4). 全力支持已有的Maven或者Ivy仓库基础建设

5). 支持传递性依赖管理,在不需要远程仓库和pom.xml和ivy配置文件的前提下

6). 基于groovy脚本构建,其build脚本使用groovy语言编写

7). 具有广泛的领域模型支持你的构建

参考:gradle_百度百科

2.gradle如何引用?

Gradle 跟 Android Studio 其实没有关系,但是 Gradle 官方还是很看重 Android 开发的,Google 在推出 AS 的时候选中了 Gradle 作为构建工具,为了支持 Gradle 能在 AS 上使用,Google 做了个 AS 的插件叫 Android Gradle Plugin所以我们能在 AS 上使用 Gradle 完全是因为这个插件的原因。在项目的根目录有个 build.gradle 文件,里面有这么一句代码:

buildscript {
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.2"
    }
}

这个就是依赖 gradle 插件的代码,后面的版本号代表的是 android gradle plugin 的版本,而不是 Gradle 的版本,这个是 Google 定的,跟 Gradle 官方没关系。

Android Gradle Plugin每个版本的具体变化和具体功能参考:Android Gradle 插件版本说明  |  Android 开发者  |  Android Developers

3.gradle、android gradle plugin、gradle wrapper区别和联系

  • Gradle是个构建系统,可以简化你的编译、打包、测试过程。熟悉Java的同窗,能够把Gradle类比成Maven。
  • Gradle Wrapper的做用是简化Gradle自己的安装、部署。现在默认新建一个项目,然后点击 AS 上的运行,默认就会直接帮你安装 Gradle ,我们不需要额外的安装 Gradle 了,但是其实这个 Gradle 不是真正的 Gradle ,他叫 Gradle Wrapper ,意为 Gradle 的包装,什么意思呢?假设我们本地有多个项目,一个是比较老的项目,还用着 Gradle 1.0 的版本,一个是比较新的项目用了 Gradle 2.0 的版本,但是你两个项目肯定都想要同时运行的,如果你只装了 Gradle 1.0 的话那肯定不行,所以为了解决这个问题,Google 推出了 Gradle Wrapper 的概念,就是他在你每个项目都配置了一个指定版本的 Gradle ,你可以理解为每个 Android 项目本地都有一个小型的 Gradle ,通过这个每个项目你可以支持用不同的 Gradle 版本来构建项目。
  • Android Plugin for Gradle是一堆适合Android开发的Gradle插件的集合,主要由Google的Android团队开发,Gradle不是Android的专属构建系统,可是有了Android Plugin for Gradle的话,你会发现使用Gradle构建Android项目尤为的简单。

4.Android工程gradle配置?

4.1.Android下多模块gradle配置目录结构

project

├─── setting.gradle

├─── build.grade

├─── app

│         └─── build.gradle

└─── libraries      

        ├─── library1      

         │       └─── build.gradle      

        └─── library2          

                  └─── build.gradle

以一个测试项目为例,来介绍下一个完整的Android项目包含的基本Gradle相关的配置:

 红色标记部分从上到下一步步分析;

4.1.1.FlotWindow/app/build.gradle

这个文件是app文件夹下这个Module的gradle配置文件,也可以算是整个项目最主要的gradle配置文件,具体里面的配置下面会介绍;

每个Module都需要有一个gradle配置文件,语法都是一样,唯一不同的是开头可能不一样;

可以独立为APP的Module使用开头:

plugins {
    id 'com.android.application'
}

作为library的Module使用开头:

plugins {
    id 'com.android.library'
}

4.1.2FloatWindow/gradle

这个目录下有个wrapper文件夹,里面可以看到两个文件,我们主要看下gradle-wrapper.properties这个文件的内容:

#Thu Nov 04 13:56:00 CST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https://services.gradle.org/distributions/gradle-6.5-bin.zip

其中GRADLE_USER_HOME通常指~/.gradle,从图示项目中能够知道我要使用gradle-6.5版本,从https://services.gradle.org/distributions/gradle-6.5-bin.zip下载,下载到本地的~/.gradle/wrapper/dists目录。那是否是各个项目的Gradle都要经过Gradle Wrapper下载,能不能全部的项目共用一个Gradle?这样理论上是能够的,可是因为Gradle自己不必定保持彻底的兼容性因此新老项目共用一个Gradle有时可能会遇到意想不到的问题。指定对应版本的Gradle,而不经过Gradle Wrapper下载的设置方式是选择Specified location同时指定Gradle home

4.1.3FloatWindow/build.gradle

这个文件是整个项目的gradle基础配置文件,默认的内容就是声明了android gradle plugin的版本;

buildscript {
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.2"
    }
}

4.1.4FloatWindow/setting.gradle

这个文件是全局项目配置文件,里面主要生命一些需要加入gradle的module,我们看看FloatWindow内容:

include ':app'
include ':library'
rootProject.name = "FloatWindowL"

5.Android工程下全局build.gradle配置和Module下build.gradle配置说明?

5.1Project全局build.gradle配置

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {//这里是gradle脚本执行所需依赖,分别对应的maven库和插件
    repositories {
        google()//Android Studio3.0后新增了google()配置,可以引用google上的开源项目
        jcenter()//是一个类似于github的代码托管仓库,声明了jcenter()配置,可以轻松引用 jcenter上的开源项目
    }
    dependencies {
        //此处是android的插件gradle,gradle是一个强大的项目构建工具
        classpath "com.android.tools.build:gradle:4.1.2"

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

allprojects {    //这里是项目本身需要的依赖,比如项目所需的maven库
    repositories {
        google()
        jcenter()
    }
}
//运行gradle clean时,执行此处定义的task任务;
//该任务继承自Delete,删除根目录中的build目录
//相当于执行Delete.delete(rootProject.bulidDir)
//gradle使用groovy语言,调用method时可以不用加()。
task clean(type: Delete) {
    delete rootProject.buildDir
}
  • buildscript{}闭包里是gradle脚本执行所需依赖,分别是对应的maven库和插件;
  • allprojects{}闭包里是项目本身需要的依赖,比如项目所需要的maven库;
  • task clean(type: Delete){}是运行gradle clean时,执行此处定义的task任务,该任务继承自Delete,删除根目录中的build目录;其中buildscript包含repositories闭包和dependencies闭包;

repositories{}闭包:配置远程仓库

该闭包中声明了jcenter()和google()的配置,其中jcenter是一个代码托管仓库,上面托管了很多Android开源项目,在这里配置了jcenter后我们可以在项目中方便引用jcenter上的开源项目,从Android Studio3.0后新增了google()配置,可以引用google上的开源项目;

dependencies{}闭包:配置构造工具

该闭包使用classpath声明了一个gradle插件,由于gradle并不是用来构建Android项目,因此此处引入相关插件来构建Android项目,启动4.1.2为该插件的版本号,可以根据最新的版本号调整;

5.2Module下build.gradle配置

从文件内容可以看出,主要分为三部分,如下:

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.gome.floatwindowl"
        minSdkVersion 17
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.navigation:navigation-fragment:2.2.2'
    implementation 'androidx.navigation:navigation-ui:2.2.2'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

5.2.1plugin

//声明Android程序
//com.android.application 表示这是一个应用程序模块
//com.android.library 标识这是一个库模块
//区别:前者可以直接运行,后者是依附别的应用程序运行
plugins {
    id 'com.android.application'
}

文件中第一行使用plugin表示应用一个插件,该插件一般有两种值选择:

  • com.android.application,表示该模块为应用程序模块,可以直接运行,打包得到的是.apk文件
  • com.android.library,表示该模块为库模块,只能作为代码库依附于别的应用程序模块来运行,打包得到的是.aar文件

5.2.2android{}闭包

这个闭包主要为了配置项目构建的各种属性;

添加signingConfigs{}闭包:

signingConfigs {// 自动化打包配置
    release {// 线上环境
        keyAlias 'test'
        keyPassword '123456'
        storeFile file('test.keystore')
        storePassword '123456'
    }
    debug {// 开发环境
        keyAlias 'test'
        keyPassword '123456'
        storeFile file('test.keystore')
        storePassword '123456'
    }
}

可以手动添加签名配置,也可以通过Project Structure选中app,点击Signing添加,具体步骤如下图所示:

 签名配置完成后可以方便带签名打包,在module的Build Variants中有两个Type,分别是debug和release,可以选择任意一个类型进行打包,并且他们会利用各自配置的Key进行打包,执行 Run app或者Build->Build apk就会自动在module name/app/build/outputs/apk路径下生成Apk文件。另一种打包方式是Build->Generate Signed APK填写签名信息生成Apk。

compileSdkVersion:设置编译时用的Android版本;

buildToolsVersion:设置编译时使用的构建工具版本,Android Studio3.0后去除此项配置;

defaultConfig{}闭包:

compileSdkVersion 30        //设置项目编译时用的Android版本
buildToolsVersion "30.0.3"
defaultConfig {
    applicationId "com.gome.floatwindowl"        //项目包名
    minSdkVersion 17        //项目最低的兼容版本
    targetSdkVersion 30        //项目的目标版本
    versionCode 1          //版本号
    versionName "1.0"        //版本名称
        
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" //表明要使用AndroidJUnitRunner进行单元测试
}
  • applicationId:指定了项目的包名。
  • minSdkVersion:指定项目最低兼容的版本,如果设备小于这个版本或者大于maxSdkVersion(一般不用)将无法安装这个应用,这里指定为16,表示最低兼容到Android 4.1系统。
  • targetSdkVersion:指定项目的目标版本,表示在该目标版本上已经做过充分测试,系统会为该应用启动一些对应该目标系统的最新功能特性,Android系统平台的行为变更,只有targetSdkVersion的属性值被设置为大于或等于该系统平台的API版本时,才会生效。例如,若指定targetSdkVersion值为22,则表示该程序最高只在Android5.1版本上做过充分测试,在Android6.0系统上(对应targetSdkVersion为23)拥有的新特性如系统运行时权限等功能就不会被启用。
  • versionCode:表示版本号,一般每次打包上线时该值只能增加,打包后看不见。
  • versionName:表示版本名称,展示在应用市场上。
  • testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"表明要使用AndroidJUnitRunner进行单元测试。

buildTypes{}闭包:

这个闭包主要指定生成安装文件的主要配置,一般包含两个子闭包,一个是debug闭包,用于指定生成测试版安装文件的配置,可以忽略不写;另一个是release闭包,用于指定生成正式版安装文件的配置。两者能配置的参数相同,最大的区别默认属性配置不一样,两种模式支持的属性配置如下图:

 buildTypes {// 生产/测试环境配置
        release {// 生产环境
            buildConfigField("boolean", "LOG_DEBUG", "false")//配置Log日志
            buildConfigField("String", "URL_PERFIX", ""https://release.cn/"")// 配置URL前缀
            minifyEnabled false//是否对代码进行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
            signingConfig signingConfigs.release//设置签名信息
            pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多
            zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率
            applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
            versionNameSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
        }
        debug {// 测试环境
            buildConfigField("boolean", "LOG_DEBUG", "true")//配置Log日志
            buildConfigField("String", "URL_PERFIX", ""https://test.com/"")// 配置URL前缀
            minifyEnabled false//是否对代码进行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
            signingConfig signingConfigs.debug//设置签名信息
            debuggable false//是否支持断点调试
            jniDebuggable false//是否可以调试NDK代码
            renderscriptDebuggable false//是否开启渲染脚本就是一些c写的渲染方法
            zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率
            pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多
            applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
            versionNameSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
        }
    }

release{}闭包和debug{}闭包两者能配置的参数相同,最大的区别默认属性配置不一样:

  • minifyEnabled:表明是否对代码进行混淆,true表示对代码进行混淆,false表示对代码不进行混淆,默认的是false。
  • proguardFiles:指定混淆的规则文件,这里指定了proguard-android.txt文件和proguard-rules.pro文件两个文件,proguard-android.txt文件为默认的混淆文件,里面定义了一些通用的混淆规则。proguard-rules.pro文件位于当前项目的根目录下,可以在该文件中定义一些项目特有的混淆规则。
  • buildConfigField:用于解决Beta版本服务和Release版本服务地址不同或者一些Log打印需求控制的。例如:配置buildConfigField(“boolean”, “LOG_DEBUG”, “true”),这个方法接收三个非空的参数,第一个:确定值的类型,第二个:指定key的名字,第三个:传值,调用的时候BuildConfig.LOG_DEBUG即可调用。
  • debuggable:表示是否支持断点调试,release默认为false,debug默认为true。
  • jniDebuggable:表示是否可以调试NDK代码,使用lldb进行c和c++代码调试,release默认为false
  • signingConfig:设置签名信息,通过signingConfigs.release或者signingConfigs.debug,配置相应的签名,但是添加此配置前必须先添加signingConfigs闭包,添加相应的签名信息。
  • renderscriptDebuggable:表示是否开启渲染脚本就是一些c写的渲染方法,默认为false。
  • renderscriptOptimLevel:表示渲染等级,默认是3。
  • pseudoLocalesEnabled:是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多。
  • applicationIdSuffix:和defaultConfig中配置是一的,这里是在applicationId 中添加了一个后缀,一般使用的不多。
  • versionNameSuffix:表示添加版本名称的后缀,一般使用的不多。
  • zipAlignEnabled:表示是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率,release和debug默认都为true。

sourceSets{}闭包:配置目录指向

sourceSets {//目录指向配置
        main {
            jniLibs.srcDirs = ['libs']//指定lib库目录
        }
    }

配置 jniLibs.srcDirs = [‘libs’],可以在Android studio的Android视图下生成jniLibs文件夹,可以方便我们存放jar包和库文件,其中Android视图下的jniLibs和project视图下的libs指向同一文件夹(app→libs),如下图所示:

当需要调试版本和正式版本使用不同的manifest文件时,可以做如下配置:

sourceSets {
    main {
        if (isDebug.toBoolean()) {
            manifest.srcFile 'src/main/debug/AndroidManifest.xml'
        } else {
            manifest.srcFile 'src/main/release/AndroidManifest.xml'
        }
    }
}

packagingOptions{}闭包:打包时的相关配置

当项目中依赖的第三方库越来越多时,有可能会出现两个依赖库中存在同一个(名称)文件。如果这样,Gradle在打包时就会提示错误(警告)。那么就可以根据提示,然后使用以下方法将重复的文件剔除,比较常用的是通过exclude去除重复的文件,例如:

 packagingOptions{
        //pickFirsts做用是 当有重复文件时 打包会报错 这样配置会使用第一个匹配的文件打包进入apk
        // 表示当apk中有重复的META-INF目录下有重复的LICENSE文件时  只用第一个 这样打包就不会报错
        pickFirsts = ['META-INF/LICENSE']

        //merges何必 当出现重复文件时 合并重复的文件 然后打包入apk
        //这个是有默认值得 merges = [] 这样会把默默认值去掉  所以我们用下面这种方式 在默认值后添加
        merge 'META-INF/LICENSE'

        //这个是在同时使用butterknife、dagger2做的一个处理。同理,遇到类似的问题,只要根据gradle的提示,做类似处理即可。
        exclude 'META-INF/services/javax.annotation.processing.Processor'
    }

productFlavors{}闭包:多个渠道配置

这个配置是经常会使用到的,通常在适配多个渠道的时候,需要为特定的渠道做部分特殊的处理,比如设置不同的包名、应用名等。场景:当我们使用友盟统计时,通常需要设置一个渠道ID,那么我们就可以利用productFlavors来生成对应渠道信息的包,如:

productFlavors {
    wandoujia {
        //豌豆荚渠道包配置
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
        //manifestPlaceholders的使用在后续章节(AndroidManifest里的占位符)中介绍
    }
    xiaomi {
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
        applicationId "com.wiky.gradle.xiaomi" //配置包名

    }
    _360 {
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "_360"]
    }
    //...
}

当然也有更简洁的方式

android {  
    productFlavors {
        wandoujia {}
        xiaomi {}
        _360 {}
       //...
    }  

    productFlavors.all { 
        //批量修改,类似一个循序遍历
        flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] 
    }
}

配置完之后,在命令行窗口中(Terminal)中输入gradlew assembleRelease(windows)即可开始打包,在Mac系统中对应指令应该是./gradlew assembleRelease。当然,如果想要debug版本的包,将指令中assembleRelease改为assembleDebug即可。最后生成的包还是在
app/build/outputs/apk中,默认命名格式如app-wandoujia-release-unsigned.apk,在module的Build Variants中可以选择相应的渠道。
注:Android Studio3.0需在主app的build.gradle里面的
defaultConfig {applicationId:"xxx.xxx.xxx"
targetSdkVersion:***
minSdkVersion :***
versionCode:***
versionName :***
//版本名后面添加一句话,意思就是flavor dimension 它的维度就是该版本号,这样维度就是都是统一的了
flavorDimensions “versionCode”
}

lintOptions{}闭包:代码扫描分析

Lint 是Android Studio 提供的 代码扫描分析工具,它可以帮助我们发现代码结构/质量问题,同时提供一些解决方案,而且这个过程不需要我们手写测试用例。

Lint 发现的每个问题都有描述信息和等级(和测试发现 bug 很相似),我们可以很方便地定位问题,同时按照严重程度进行解决。

//程序在编译的时候会检查lint,有任何错误提示会停止build,我们可以关闭这个开关
    lintOptions {
        abortOnError false //即使报错也不会停止打包
        checkReleaseBuilds false  //打包release版本的时候进行检测
    }

5.2.3dependencies{}闭包

该闭包定义了项目的依赖关系,一般项目都有三种依赖方式:本地依赖、库依赖和远程依赖。本地依赖可以对本地的jar包或目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖可以对jcener库上的开源项目添加依赖关系。从Android Studio3.0后compile引入库不在使用,而是通过api和implementation,api完全等同于以前的compile,用api引入的库整个项目都可以使用,用implementation引入的库只有对应的Module能使用,其他Module不能使用,由于之前的项目统一用compile依赖,导致的情况就是模块耦合性太高,不利于项目拆解,使用implementation之后虽然使用起来复杂了但是做到降低偶合兴提高安全性。

dependencies {//项目的依赖关系
    implementation fileTree(include: ['*.jar'], dir: 'libs')//本地jar包依赖
    implementation 'com.android.support:appcompat-v7:27.1.1'//远程依赖
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    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'
}
  • implementation fileTree(include: [’*.jar’], dir: ‘libs’):implementation fileTree是一个本地依赖声明,表示将libs目录下所有.jar后缀的文件都添加到项目的构建路径当中。
  • implementation ‘com.android.support:appcompat-v7:27.1.1’:implementation语句为 远程依赖声明,'com.android.support:appcompat-v7:27.1.1’为一个标准的远程依赖库格式,其中com.android.support为域名部分,用于区分不同公司的库;appcompat-v7为组件名称,用于区分同一个公司的不同库;27.1.1为版本号,用于区分同一个库的不同版本。加上这句声明后,Gradle在构建项目时会先检查一下本地是否已经缓存过该库,若没有缓存则自动联网下载,下载后自动添加到项目的构建路径中去。
  • testImplementation和androidTestImplementation:表示声明测试用例库。

5.3Module完整的build.gradle配置

// 声明是Android程序,
//com.android.application 表示这是一个应用程序模块
//com.android.library 标识这是一个库模块
//而这区别:前者可以直接运行,后着是依附别的应用程序运行
apply plugin: 'com.android.application'

android {
    signingConfigs {// 自动化打包配置
        release {// 线上环境
            keyAlias 'test'
            keyPassword '123456'
            storeFile file('test.jks')
            storePassword '123456'
        }
        debug {// 开发环境
            keyAlias 'test'
            keyPassword '123456'
            storeFile file('test.jks')
            storePassword '123456'
        }
    }
    compileSdkVersion 27//设置编译时用的Android版本
    defaultConfig {
        applicationId "com.billy.myapplication"//项目的包名
        minSdkVersion 16//项目最低兼容的版本
        targetSdkVersion 27//项目的目标版本
        versionCode 1//版本号
        versionName "1.0"//版本名称
        flavorDimensions "versionCode"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"//表明要使用AndroidJUnitRunner进行单元测试
    }
    buildTypes {// 生产/测试环境配置
        release {// 生产环境
            buildConfigField("boolean", "LOG_DEBUG", "false")//配置Log日志
            buildConfigField("String", "URL_PERFIX", ""https://release.cn/"")// 配置URL前缀
            minifyEnabled false//是否对代码进行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
            signingConfig signingConfigs.release//设置签名信息
            pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多
            zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率
            applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
            versionNameSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
        }
        debug {// 测试环境
            buildConfigField("boolean", "LOG_DEBUG", "true")//配置Log日志
            buildConfigField("String", "URL_PERFIX", ""https://test.com/"")// 配置URL前缀
            minifyEnabled false//是否对代码进行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
            signingConfig signingConfigs.debug//设置签名信息
            debuggable false//是否支持断点调试
            jniDebuggable false//是否可以调试NDK代码
            renderscriptDebuggable false//是否开启渲染脚本就是一些c写的渲染方法
            zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率
            pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多
            applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
            versionNameSuffix 'test'//在applicationId 中添加了一个后缀,一般使用的不多
        }
    }

    sourceSets {//目录指向配置
        main {
            jniLibs.srcDirs = ['libs']//指定lib库目录
        }
    }

    packagingOptions{//打包时的相关配置
        //pickFirsts做用是 当有重复文件时 打包会报错 这样配置会使用第一个匹配的文件打包进入apk
        // 表示当apk中有重复的META-INF目录下有重复的LICENSE文件时  只用第一个 这样打包就不会报错
        pickFirsts = ['META-INF/LICENSE']

        //merges何必 当出现重复文件时 合并重复的文件 然后打包入apk
        //这个是有默认值得 merges = [] 这样会把默默认值去掉  所以我们用下面这种方式 在默认值后添加
        merge 'META-INF/LICENSE'

        //这个是在同时使用butterknife、dagger2做的一个处理。同理,遇到类似的问题,只要根据gradle的提示,做类似处理即可。
        exclude 'META-INF/services/javax.annotation.processing.Processor'
    }

    productFlavors {
        wandoujia {}
        xiaomi {}
        _360 {}
    }

    productFlavors.all {
            //批量修改,类似一个循序遍历
        flavor -> flavor.manifestPlaceholders = [IFLYTEK_CHANNEL: name]
    }

    //程序在编译的时候会检查lint,有任何错误提示会停止build,我们可以关闭这个开关
    lintOptions {
        abortOnError false
        //即使报错也不会停止打包
        checkReleaseBuilds false
        //打包release版本的时候进行检测
    }

}

dependencies {
    //项目的依赖关系
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    //本地jar包依赖
    implementation 'com.android.support:appcompat-v7:27.1.1'
    //远程依赖
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    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'
}

6.Android的APK编译流程

APK的构建过程可以根据官方提供的流程图如下图所示

这个APK构建的过程主要分为以下几步:
1. 通过AAPT(Android Asset Packaging Tool)打包res资源文件,比如AndroidManifest.xml、xml布局文件等,并将这些xml文件编译为二进制,其中assets和raw文件夹的文件不会被编译为二进制,最终会生成R.java和resources.arsc文件。
2. AIDL工具会将所有的aidl接口转化为对应的Java接口。
3. 所有的Java代码,包括R.java和Java接口都会被Java编译器编译成.class文件。
4. Dex工具会将上一步生成的.class文件、第三库和其他.class文件编译成.dex文件。
5. 上一步编译生成的.dex文件、编译过的资源、无需编译的资源(如图片等)会被ApkBuilder工具打包成APK文件。
6. 使用Debug Keystore或者Release Keystore对上一步生成的APK文件进行签名。
7. 如果是对APK正式签名,还需要使用zipalign工具对APK进行对齐操作,这样应用运行时会减少内存的开销。

从以上步骤可以看出,APK的构建过程是比较繁琐的,而且这个构建过程又是时常重复的,如果没有构建工具,手动去完成构建工作,无疑对于开发人员是个折磨,也会产生诸多的问题,导致项目开发周期变长。

7.认识下几个命令

上面提到了,假设我们没有 IDE ,只有类似 Sublime、Atom、Vim这种轻量编辑器怎么办?那我们就没法开发 Android 了么?然而只要有构建工具,不需要 IDE 我们一样有办法开发,这个时候我们就需要用到几个有用的 Gradle 命令了:

./gradlew -v 版本号

./gradlew clean 清除9GAG/app目录下的build文件夹

./gradlew build 检查依赖并编译打包

这里注意的是 ./gradlew build 命令把 debug、release 环境的包都打出来,如果正式发布只需要打 Release 的包,该怎么办呢,下面介绍一个很有用的命令 assemble , 如

./gradlew assembleDebug 编译并打Debug包

./gradlew assembleRelease 编译并打Release的包

值得注意的是,以上所有命令都是在终端里执行,并且必须要切换到所在项目的根目录下执行,win系统直接执行 gradlew 。

参考:

史上最全Android build.gradle配置详解_林伟茂的博客-CSDN博客

Android SourceSet 使用 参考 示例_TDC的专栏-CSDN博客

给 Android 初学者的 Gradle 知识普及 - 知乎

Android Gradle是什么?_xuwei_net的专栏-CSDN博客_android gradle

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>