Gradle在Android的使用一

Gradle在Android的使用

本文是基于Gradle Android Plugin中文手册总结,以及自己本人测试所写。

Gradle的目录结构

Gradle遵循约定优先于配置的概念,在尽可能的情况下提供默认的配置参数。最基本的项目有两个”source set”组件,他们是:
1. src/main
2. src/androidTest
在里面,每个存在的文件夹对应相对应的源组件,比如对应java plugin和Android plugin来说,他们的java代码和资源路径如下:
java/
resources/

但是对于Android plugin来说,它还拥有一下特有的文件夹结构:
1. AndroidManifest.xml
2. res/
3. assets/
4. aild
5. rs
6. jni
7. jniLibs

这就意味着在Android plugin下,*.java的文件的目录是src/main/java,对于AndroidManifest.xml的目录是src/main/AndroidManifest.xml

配置目录结构

有一些时候我们使用一些别的项目的代码,或者是把一些不属于Android项目的资源之类的引入进来,可以通过如下配置,在build.gradle中引入即可,可以引入的资源和方法:

android{
    main{
           manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resorces.sreDirs = ['src']
            aidl.srcDirs=['src']
            renderscript.srcDirs=['src]
            res.srcDirs=['res']
            assets.srcDirs=[assets] 
   }

 androidTest.setRoot('tests')
}

其中,在Android特有的sourceSets在Java sourceSets中不起作用。假如是多个,比如java.srcDirs包含多个,可以使用”,”分割开来,比如 java.srcDirs=[‘src-gen’,’src-test’]。setRoot的作用就是把另外一个可以是作为独立的测试的代码资源的文件夹安装main的格式合并进来,作为某一个builtType特有的资源。可以用作是测试,或者是dev或者是release等,在builtType中再去详细介绍。
例子:比如我们现在有一个使用greendao产生的src-gen的java代码,根目录就是src-gen,里面包好了greendao帮助我们产生的关于数据库的代码,我们再不适用copy进入项目而是可以直接使用的方式是:把src-gen目录拷贝到跟build.gradle同级目录,然后在build.gradle中的android节点下面,加入:

sourceSets{
    main{
        java.srcDirs=['src-gen']
   }
}

这样子之后,我们就可以在我们的项目中引入和使用这些代码了。

配通用task

在添加了java或者的Android插件之后,gradle会自动的带有以下task
1. assemble 组合项目的所有输出
2. check 执行所有的检查任务
3. build 执行assemble和check两个task的所有工作
4. clean 清空项目的输出,也就是build文件夹会被删除
实际上,assemble,Check,build这三个task不做任何事情,他只是一个Task的标志,用来告诉plugin添加实际需要执行的task去完成这些工作。
task的依赖关系:当一个task依赖于另外一个task的时候,当task被调用的时候,被依赖的task会先调用,比如check task依赖于一个新task,那么当check运行的时候,新的task会先运行。
获取更改级别的task

gradle tasks

查看所有的task列表以及他们之间的依赖关系

gradle tasks --all

java的task

  1. assemble jar,输出jar
  2. check test 运行测试

常用的task有assemble
build

buildDependents
buildNeeded
classes
clean
jar
testClasses

documentation

javadoc

help

buildEnvironment
components
dependencies
dependencyInsight
help
model
projects
properties
tasks

other

compileJava
compileTestJava
processResources
processTestResources

verification

check
test

可以看到,assemble需要jar task,jar需要classes task,classes 是用于编译java生成clazz文件的task。可以使用jar或者是assemble或者是build命令去生成jar。
check依赖于test,task,test task依赖于classes和testClasses,也就是需要运行java获取字节码,同时运行测试

android的task

  1. assemble 输出apk文件
  2. check 执行所有的检查
  3. connectedCheck 在一个连接的设备或者是模拟器上面执行检查,他们可以在所有连接的设备上面并行的执行检查
  4. deviceCheck 通过APIs连接远程设备来执行检查,主要用于CI(持续集成)服务上
  5. build 执行assemble和check的所有工作
  6. clean 情况项目的输出
    这些标志性的的task是必须的,以保证能够在没有设备连接的情况下执行定期检查,注意build task不依赖于device Check
    一个Android项目至少拥有两个输出:debug和release,他们有各自的标志构建
assembbleDebug
assembleRerlease

其中,单独的assemble会依赖于上面的两个task,会构建出两个apk文件。
注意:Gradle在命令行上支持驼峰命名的task简称,比如

gradle aR

等同于

gradle assembleRelease

aD等同于assembleDebug

check task的依赖:
check 依赖 lint
connectedCheck 依赖connectedAndroidTest
deviceCheck 进行测试时才会触发。
只要可被安装,也就是使用了”com.android.application”gradle插件的项目,就可以被安装。使用

installDebug //安装debug版本
installRelease//安装release版本
uninstallAll //卸载
uninstallDebug //卸载debug版本
uninstallRelease  //卸载正式版本
uninstallDebugAndroidTest // 卸载测试

Android的常用task有:
android task

androidDependencies
signingReport
sourceSets

build task

assemble
assembleAndroidTest
assembleDebug
assembleRelease
build
buildDependents
buildNeeded
classes
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources
compileRetrolambda
extractDebugAnnotations
extractReleaseAnnotations
jar
mockableAndroidJar
testClasses

build setup task

init
wrapper

documentation task

javadoc

help task

buildEnvironment
components
dependencies
dependencyInsight
help
model
projects
properties
tasks

install task

installDebug
installDebugAndroidTest
uninstallAll
uninstallDebug
uninstallDebugAndroidTest
uninstallRelease

other task,这个比较多,可以在AS的gradle视图查看

assembleDebugAndroidTest
assembleDebugUnitTest
assembleDefault
assembleReleaseUnitTest
bundleDebug
bundleRelease
.....

verification task

check
connectedAndroidTest
connectedCheck
connectedDebugAndroidTest
deviceAndroidTest
deviceCheck
lint
lintDebug
lintRelease
test
testDebugUnitTest
testReleaseUnitTest

DSL定义Manifest属性

minSdkVersion //app运行的最多版本
tagetSdkVersion  //使用的sdk版本
versionCode    //app版本code
versionName    //app版本name
applicationId    //包名
testApplicationId    //测试包名
testInstrumentationRunner 

这些属性都是使用AS的android的gradle插件提供的,需要使用插件的某一个,然后在android节点下面定义。比如

android{
    compileSdkVersion 23
    buildToolsVersion "23.0.1"' 

    defaultConfig{
        versionCode 100
        versionName "1.0.0"
        minSdkVersion 14
        targetSdkVersion 23
        applicationId "com.test.gradle"
    }

}

构建类型

通过android 节点下面的buildType节点可以构建不同的类型的apk。目前只是针对一个产品,针对多个产品的可以使用 productFlavors,这个之后再做解析。
使用buildType节点,默认的,AS会为我们添加debug和release这两个构建类型。例如:

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

这两种类型。
其中,minifyEnabled 是是否混淆,signingConfig 是签名,proguardFiles是混淆的文件。我们一般在开发的时候需要使用这两个版本的apk,方便我们调试。
假如,我们需要其他的包名,或者是签名的,可以继续添加构建类型,比如:

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

这样子我们就可以构建了另一个一个dev的类型的apk,他的报名时原来的defaultConfig的applicationId+”.dev”,这是他的心新报名,我们允许的时候,可以在AS的左下角,build Variants选择运行类型,或者是在右边的选择对应的task去build或者是install apk都是可以的,因为定义了对应的buildType之后,gradle会生成对应的task,比如这里的会生成assembleDev,可以使用aD进行快速的构建。
使用buildType的另外一个好处就是可以对不同的类型使用不同的代码或者是资源,他同样是支持sourceSets的,可以为他自己设置不同的代码,不同的资源,通过

sourceSets.buildType.setRoot('path')

其中path就是对应的目录,比如是dev的就是把dev所在的目录,相当于完整的另一个的目录设置进去,就可以作为devbuild时候的资源了。
注意:
1. manifest 将被合并到 app 的 manifest
2. 代码只是换了一个源文件夹
3. 资源将叠加到 main 的资源中,并替换已存在的资源。
也就是dev这个builtType会合并main文件夹的代码和资源,合并的方式就是上面的方式。
但是实际上,建议使用的是产品定制化,也就是使用productFlavors去实现,关于productFlavors实现不同的产品定制化,在后续给大家分享。

签名

设置签名是位于android节点下面的signingConfigs节点下面,例如:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.example.user.testproject"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }

 signingConfigs {
        debug {
            storeFile file("C:\\Users\\liweijie\\Desktop\\liweijie.jks")
            storePassword "liweijie123"
            keyAlias "liweijie"
            keyPassword "liweijie123"
        }
        release {
            storeFile file("C:\\Users\\liweijie\\Desktop\\liweijie.jks")
            storePassword "liweijie123"
            keyAlias "liweijie"
            keyPassword "liweijie123"
        }
dev{
            storeFile file("C:\\Users\\liweijie\\Desktop\\liweijie.jks")
            storePassword "liweijie123"
            keyAlias "liweijie"
            keyPassword "liweijie123"
   }
    }

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

    }
    compileOptions {
        sourceCompatibility JavaVersion. VERSION_1_8
        targetCompatibility JavaVersion. VERSION_1_8
    }
    sourceSets.dev.setRoot('src/dev')

}

这里设置了debug和release签名都是同一个,你也可以设置为不同的签名。
其中:
storeFile file() 指定签名的路径,可以使用相对路径,把对应的签名放在项目跟对应的build同级目录下去引用
storePassword 签名的密码
keyAlias 签名的别名
keyPassword 别名对应的密码
我们可以定义多个签名给不同的buildType,不同对应不同的签名,但是建议不需要太多,太多的话运行的时候回懵逼,特别是我们通过判断签名是否是正式的签名来判断代码是否是debug状态的时候。

依赖管理

使用dependencies节点,该节点是跟android节点同级的.
1、 引用本地的依赖,比如我们的jar,通过

dependencies{
 compile fileTree(dir: 'libs', include: ['*.jar'])
}

他会把跟src同级的libs目录下面的jar文件作为依赖引入进来,当你存放在其他地方的时候,也可以手动的引入进来,比如我们存放在src/lib目录下面,可以通过

dependencies {
       compile files('src/lib/test.jar')
}

这一个方式引入进来。
2、 引用远程的依赖
我们有时候会使用一些github的开源库,或者是自己公司私有的maven库或者是一些其他公司提供的仓库,使用到他们的jar。当然我们可以把他们下载下来存放到libs目录下面进行依赖,但是这样子不是很方便,因为有时候版本变更的比较频繁的时候,我们就需要经常去下载,使用远程依赖我们就是只是需要升级一下版本号,clean一下项目就ok了。
使用方式:

dependencies {
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile 'com.android.support:design:23.1.0'
    compile 'io.reactivex:rxandroid:1.2.1'
    compile 'io.reactivex:rxjava:1.1.6'
}

这里我们引入rx的依赖和v7已以及support:design依赖。依赖的引入时跟maven左边的那种
groupId:artifactId:version
比如上面的io.reactivex就是groupId,rxJava就是artifactId,1.1.6就是version
需要使用这些依赖,同时我们需要申明仓库地址,比如常用的maven仓库,jcenter仓库,我们在整个project的根目录(也就是声明gradle插件的地方)的build.gradle中申明。比如:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.1'
        classpath 'me.tatarka:gradle-retrolambda:3.2.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

3、引用lib依赖
我们开发的时候,常常会考虑模块化,多人开发,功能分类等,常常有lib的抽取,同时这个lib有时候也会作为一个公用库,做成arr给别的项目依赖,当我们需要多个lib分开整个app的模块或者是测试我们做成的aar的lib的时候,我们就需要使用模块依赖。
我们新建一个android lib,android插件类型是

apply plugin: 'com.android.library'

然后需要使用到的app可运行或者是其他的lib,使用

dependencies {
        compile project(':lib')
}

其中lib就是你的lib项目。

lib module

lib是可以输出一个arr别的lib或者是可运行的app module使用。
lib使用的android插件是com.android.library
lib包含的内容有源代码,资源文件,清单文件,lib本身的相关依赖(so文件或者是其他的arr,jar文件)。他被依赖到别的项目的时候,资源文件和清单会被合并,当有重复命名的时候,比如同样有两个string的name为app_name的,那么lib的将会被覆盖。java代码就是不会被合并,当存在两个包名相同,类名相同的java文件的时候回报多个字节码文件的错误。
当一个lib或者是app module依赖多个子lib的时候,假如子lib之间存在着资源冲突,也会发生某某资源已经定义的错误。
我们发布被依赖的lib版本的时候,可以通过buildType或者productFlavors去实现,同样可以通过

android {
    defaultPublishConfig "flavor"
}

其中,flavor在没有其他定义的产品渠道的时候,是debug或者是release,一般我们使用的是release版本,假如我们需要发布多个arr,包括debug,release或者是其他flavor或者是buildType的时候,可以通过

android {
    publishNonDefault true
}

每一个arr都是独立的,包含自己的资源和代码,相对应的sourceSets等。
下一篇文章分析如何构建变种apk和测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值