本文共 9944 字,大约阅读时间需要 33 分钟。
在Android Studio中有一个不可或缺的构建工具,就是gradle,我们所有的打包等操作都是需要使用gradle来进行的,往往在做android开发的时候我们都知道有个工具是叫gradle,那gradle是什么?为什么要有这样一个gradle工具?以及我们应该怎么去使用这样一个gradle呢?可能多数的程序员对这一块相对来说都是比较陌生的,只知道使用,但是却往往很多时候忽略了它的真正含义。在这里我就简单说一下我自己的理解。不喜勿喷!!!
1:首先是gradle的相关概念:
什么是gradle???
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。面向Java应用为主。当前其支持的语言限于Java、Groovy和Scala,计划未来将支持更多的语言。(简单总结下来也就是gradle就是一款相比以前来说更加智能一点的构建工具,其的诞生是基于jvm构建工具,解决的是繁琐的配置文件),那什么是构建????如果你需要盖一间房子,你是不是需要把砖,瓦,水泥,钢筋都需要准备好,然后请一个工人来,然后工人给你盖房子。我们也就可以把这一整个流程看做是一个构建的流程,首先你需要将一个完整的设计图纸和材料(整个项目),然后工人通过将材料组合,形成你图纸上想要的房子,但是如果工人出现偏差(参数修改),盖出来的房子就会改变,如果是材料或者图纸有点改变。那工人所盖的房子可能也会有一些偏差。可以简单的理解下,这是否就是一个完整的构建流程。其实在15年初使用android studio的时候,那个时候gradle有时候都是需要自己去下载,配置的,而与现在的更加智能的android studio2.2版本相比,在install的时候,已经会自动默认去更新一些gradle版本了
2:先来看一下在android studio中安装的默认gradle的位置吧。当然也可以进行别的配置:
这是我android studio目录下,最新的gradle的相关位置
当然,还有在window下gradle的相关配置参数之类的,这个主要是在Administrator文件夹下的,后续下载的所有gradle版本貌似都在这个文件夹下面,有兴趣的可以自己去找一下
3:跟着我来查看android studio项目中的gradle脚本
从图上可以看到,在整个项目中有这样的几块都是与gradle相关的,当然每一个都是很重要的
先来说说项目的app/build.gradle吧:
//声明是android 应用程序,同样做java的同学也可以声明为java相关的apply plugin: 'com.android.application'//定义release版本的打包时间def releaseTime() { return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))}android { //编译的sdk的版本 compileSdkVersion 25 //build tools的版本 buildToolsVersion "25.0.1" //默认相关的配置 defaultConfig { //包名 applicationId "com.zzf.camera.helloworld" //最小的sdk(向下兼容) minSdkVersion 22 //目标sdk targetSdkVersion 25 // dex突破65535的限制 multiDexEnabled true //版本号 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }//签名工具signingConfigs { debug { // No debug config } release { storeFile file("../yourapp.keystore") storePassword "your password" keyAlias "your alias" keyPassword "your password" }}// java版本compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8}//对应用原始编译出来的apk进行名称的修改(默认编译出来的是app-debug.apk和app-release-unsigned.apk,此处都是未进行签名的)android.applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile def fileName if (outputFile != null && outputFile.name.endsWith('.apk')) { if (variant.buildType.name.equals('release')) { fileName = "Hello.apk" } else if (variant.buildType.name.equals('debug')) { fileName = "Hello.apk" } output.outputFile = new File(outputFile.parent, fileName) } }}// 移除lint检查的errorlintOptions { abortOnError false}//构建的类型,是debug版本还是release版本 buildTypes { //debug版本的参数配置 debug{ signingConfig signingConfigs.debug } //release版本相关的版本配置 release { //是否进行混淆 minifyEnabled false //混淆相关的文件的位置 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } }}//新建的工程,所以依赖的都是基础jardependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support.constraint:constraint-layout:1.0.2' testCompile 'junit:junit:4.12'}
以上就是关于文件的比较基本的相关配置
先来说说项目的gradle/wrap/目录吧:
gradle-wrapper.jar: 当前此project的所有构建工作主要就是依赖这样的一个jar包,后面会展示一下相关这个jar的具体内容。
gradle-wrapper.properties:类似于脚本配置文件,在引用的时候,需要给gradle-wrapper.jar提供相关的引用路径,一般情况下这个都是在项目建立的时候,整个gradle-wrapper.jar相关的调用路径等都是已经默认生成好了,所以是不需要再进行修改的#Sat Apr 22 12:50:57 CST 2017distributionBase=GRADLE_USER_HOMEdistributionPath=wrapper/distszipStoreBase=GRADLE_USER_HOMEzipStorePath=wrapper/distsdistributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
整个工程构建部分的gradle
对应的是整个project目录下的,包括了所有的sub_project和modules都试用
// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript { //仓库 repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }}allprojects { repositories { jcenter() }}task clean(type: Delete) { delete rootProject.buildDir}
内容主要包含了两个方面:一个是声明仓库的源,这里可以看到是指明的jcenter(), 之前版本则是mavenCentral(), jcenter可以理解成是一个新的中央远程仓库,兼容maven中心仓库,而且性能更优。另一个是声明了android gradle plugin的版本
整个工程构建部分的Setting.gradle(系统自动更新,一般情况下不需要我们进行修改)
没有依赖module项目的操作include ':app'
依赖了包名为com.zzf.device.mediacodec项目之后
include ':app', ':com.zzf.device.mediacodec'
整个工程构建部分的可执行的gradlew.bat
所有的gradle相关的执行全靠这个可执行命令,所有在整个构建的过程中,我们既可以去依赖android studio去帮我们构建,同时也可以使用gradlew.bat这样一个执行脚本,去构建
瞧一瞧,看一看,这个脚本都写了些什么??
@if "%DEBUG%" == "" @echo off@rem ##########################################################################@rem@rem Gradle startup script for Windows@rem@rem ##########################################################################@rem Set local scope for the variables with windows NT shellif "%OS%"=="Windows_NT" setlocal@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.set DEFAULT_JVM_OPTS=set DIRNAME=%~dp0if "%DIRNAME%" == "" set DIRNAME=.set APP_BASE_NAME=%~n0set APP_HOME=%DIRNAME%@rem Find java.exeif defined JAVA_HOME goto findJavaFromJavaHomeset JAVA_EXE=java.exe%JAVA_EXE% -version >NUL 2>&1if "%ERRORLEVEL%" == "0" goto initecho.echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.echo.echo Please set the JAVA_HOME variable in your environment to match theecho location of your Java installation.goto fail:findJavaFromJavaHomeset JAVA_HOME=%JAVA_HOME:"=%set JAVA_EXE=%JAVA_HOME%/bin/java.exeif exist "%JAVA_EXE%" goto initecho.echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%echo.echo Please set the JAVA_HOME variable in your environment to match theecho location of your Java installation.goto fail:init@rem Get command-line arguments, handling Windowz variantsif not "%OS%" == "Windows_NT" goto win9xME_argsif "%@eval[2+2]" == "4" goto 4NT_args:win9xME_args@rem Slurp the command line arguments.set CMD_LINE_ARGS=set _SKIP=2:win9xME_args_slurpif "x%~1" == "x" goto executeset CMD_LINE_ARGS=%*goto execute:4NT_args@rem Get arguments from the 4NT Shell from JP Softwareset CMD_LINE_ARGS=%$:execute@rem Setup the command lineset CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar@rem Execute Gradle"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%:end@rem End local scope for the variables with windows NT shellif "%ERRORLEVEL%"=="0" goto mainEnd:failrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead ofrem the _cmd.exe /c_ return code!if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1exit /b 1:mainEndif "%OS%"=="Windows_NT" endlocal:omega
里面有几个比较重要的代码:
1://设置java.exe set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if “%ERRORLEVEL%” == “0” goto init:2://设置gradle-wrapper的目录
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar所以就可以看出来了,其实这个脚本大概的意思是
java -jar gradle-wrapper.jar//事实上就是去执行这个jar简单了解gradle-wrapper.jar包源码:
整个jar包的Main函数是从GradleWrapperMain.class这里开始的,它会去从整个执行列表中去获取参数,然后在进行switch的过程,具体的代码不会在这里进行详细介绍。
public static void main(String[] args) throws Exception { File wrapperJar = wrapperJar(); File propertiesFile = wrapperProperties(wrapperJar); File rootDir = rootDir(wrapperJar); CommandLineParser parser = new CommandLineParser(); parser.allowUnknownOptions(); parser.option(new String[] { "g", "gradle-user-home" }).hasArgument(); parser.option(new String[] { "q", "quiet" }); SystemPropertiesCommandLineConverter converter = new SystemPropertiesCommandLineConverter(); converter.configure(parser); ParsedCommandLine options = parser.parse(args); Properties systemProperties = System.getProperties(); systemProperties.putAll(converter.convert(options, new HashMap())); File gradleUserHome = gradleUserHome(options); addSystemProperties(gradleUserHome, rootDir); Logger logger = logger(options); WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile, logger); wrapperExecutor.execute(args, new Install(logger, new Download(logger, "gradlew", wrapperVersion()), new PathAssembler(gradleUserHome)), new BootstrapMainStarter()); }
先进入这个文件所在的目录下吧
执行可执行命令
传入的参数都是传入到jar中去执行的。
命令 | 执行意义 |
---|---|
-v | 版本号 |
clean | 清除app/目录下的build文件夹 |
build | 检查依赖并编译打包 |
assembleDebug | 编译并打Debug包 |
assembleRelease | 编译并打Release的包 |
installRelease | Release模式打包并安装 |
uninstallRelease | 卸载Release模式包 |
installDebug | Debug模式打包并安装 |
uninstallDebug | 卸载Debug模式包 |
具体的执行就不在这里执行了
第一步 在AndroidManifest.xml里配置PlaceHolder
第二步 在build.gradle设置productFlavors
android { productFlavors { xiaomi { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"] } _360 { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "_360"] } baidu { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"] } }}或者android { productFlavors { xiaomi {} _360 {} baidu {} wandoujia {} } productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] }}
第三步:执行命令
直接执行 ./gradlew assembleRelease 进行全部打包的过程直接执行./gradlew assembleBaidujia,进行单个渠道的打包直接执行./gradlew assembleBaiduRelease进行豌豆荚release版本的渠道打包
以上就是对gradle的一些简单的了解