本文共 9265 字,大约阅读时间需要 30 分钟。
这一篇主要是说下gradle的一些常见使用,主要是几点配置:
目录
include ':app', ':netlib',':emptylib'settings.project(':emptylib').projectDir = file('empty/library')
在settings.gradle这样配置后,是什么意思呢?可以理解为就是将empty/library下的库工程取名为emptylib,在这样配置并build后,再来看下工程的目录结构有什么变化:
对于一个工程来说,可能会包含多个project,每个project可能会有一些相同的配置,这时就可以将这些相同的配置额外的提取出来 ,这里下来看个简单的例子:
先在settings.gradle中如下配置:
include ':app', ':netlib'gradle.ext.custom = 'custom'
然后在build.gradle中添加如下输出代码:
apply plugin: 'com.android.application'println gradle.ext.custom
输出结果就是上面配置custom,这个配置还可以在延伸一下,新建一个config.gradle文件,这个名字可以随便取,只要是以.gradle结尾就可以了,接下来就可以在这个文件中配置一下全局变量了:
ext { android = [ compileSdkVersion : 27, minSdkVersion : 19, targetSdkVersion : 27, versionCode : 1, versionName : "1.0" ] version = [ androidSupportSdkVersion : "27.1.1", retrofitSdkVersion : "2.4.0" ] dependencies = [ //surport "appcompat-v7" : "com.android.support:appcompat-v7:${version["androidSupportSdkVersion"]}", "design" : "com.android.support:design:${version["androidSupportSdkVersion"]}", "support-v4" : "com.android.support:support-v4:${version["androidSupportSdkVersion"]}", "cardview-v7" : "com.android.support:cardview-v7:${version["androidSupportSdkVersion"]}", "annotations" : "com.android.support:support-annotations:${version["androidSupportSdkVersion"]}", "recyclerview-v7" : "com.android.support:recyclerview-v7:${version["androidSupportSdkVersion"]}", ]}
这样配置完后,但还没有引入到gradle中,那要怎么引入呢?很简单,只需要rootProject的build.gradle中在添加一行代码就ok:
apply from: 'config.gradle'
这样配置完后,就可以在其他的build.gradle中去引用了,比如:
android { compileSdkVersion rootProject.ext.android['compileSdkVersion'] defaultConfig { applicationId "com.example.zzq.urlrequest" minSdkVersion rootProject.ext.android['minSdkVersion'] targetSdkVersion rootProject.ext.android['targetSdkVersion'] versionCode rootProject.ext.android['versionCode'] versionName rootProject.ext.android['versionName'] testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }}
这样配置的好处是,当有多个project时,由于某些原因需要更改一些设置时,那就不用每个都去改了,直接在配置(config.gradle)文件中修改下就ok了。当然还有另一种方式,使用起来也更简单,接下来就来唠唠:
在工程文件下有个gradle.properties文件,这个文件有什么用呢?就是给.gradle文件添加属性,也就是说只要在gradle.properties中添加的属性,在.gradle文件中是可以直接使用,那就来看看怎么用了:
1、先在gradle.properties文件中做如下配置:
minSdkVersionPro = 19targetSdkVersionPro = 27versionCodePro = 1versionNamePro = 1.0
2、接下就是在.gradle文件中去使用了:
android { println minSdkVersionPro println targetSdkVersionPro println versionCodePro println versionNamePro compileSdkVersion 27 defaultConfig { applicationId "com.example.zzq.urlrequest" minSdkVersion minSdkVersionPro targetSdkVersion targetSdkVersionPro versionCode versionCodePro.toInteger() versionName versionNamePro testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }}
看下输出:
192711.0
对于有些属性定义在gradle.properties中是会包异常的,比如定义compileSdkVersion这个属性,使用的时候就会包异常,至于什么原因,暂时还不知道。所以这个用起来会比较简单,但是可能有一些坑要填。
再来说最后一种定义.gradle文件的属性,不过这种定义方式只是在当前文件中有效,但是没什么坑:
def compileSdkVersionPro = 27android { ... compileSdkVersion compileSdkVersionPro ...}
如果定义的属性只是当前文件有效,优先采用这种方式。
要配置签名文件首先得有签名文件,这个这里就不多说了,有了签名文件后就可以在app模块下的build.gradle文件下进行配置,这里采用的是图形界面作说明,那这个图形界面在哪呢?看下图:
或者使用快捷键:ctrl+alt+shift+s (这里使用的是android studio默认的快捷键)
出现的界面如下:
这样配置好后,点击确定就完成配置了,其实际上是在app模块下的build.gralde文件里生成代码,来看看生成的代码:
android { signingConfigs { config { keyAlias 'alias' keyPassword '123456' storeFile file('NetRequest.jks') storePassword '123456' } }}
如果你比较熟悉了,直接手写这段代码就可以了,至此签名文件配置就算完成了,这里应该还有一个疑惑,就是file(‘NetRequest.jks’)这个是什么意思,这里其实就是指向NetRequest.jks这个文件,只不过我这里使用的想对路径,当然你也可以使用绝对路径,这里在贴下我放置这个文件的位置:
好了,签名文件就说到这里了。
android studio 3.0之前和之后配置是不一样的,而且是兼容的,这里针对是3.0之后的版本:
android { applicationVariants.all { variant -> variant.outputs.all { println "outputFile = "+outputFile println "outputFileName = "+outputFileName outputFileName = "${variant.name}_${getTime()}_${variant.versionName}" println "modify outputFileName = "+outputFileName } }}def getTime(){ new Date().format('yyyMMdd',TimeZone.getTimeZone('UTC'))}
这里打印了两个东西,来看下输出:
outputFile = E:\AndroidWorkProject\NetRequest\app\build\outputs\apk\debug\app-debug.apkoutputFileName = app-debug.apkmodify outputFileName = debug_20180926_1.0outputFile = E:\AndroidWorkProject\NetRequest\app\build\outputs\apk\release\app-release.apkoutputFileName = app-release.apkmodify outputFileName = release_20180926_1.0
这里有个需要注意的地方,这里只能配置outputFileName这个属性,不能配置outputFile,配置了这个会报异常,如下:
Cannot set the value of read-only property 'outputFile',意思就是说这个属性是一个只读属性,getTime()获取的是当前时间。
比如在在清单文件有如下配置:
可以看到这里value还没有赋值,这时就可以在build.gradle中进行动态配置,这样的配置在多版本中配置的比较多。
看下在app模块下build.gradle中是如何配置:
buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' manifestPlaceholders = [zzq_name : 'tangedegushi_release'] } debug { manifestPlaceholders = [zzq_name : 'tangedegushi_debug'] } }
配置完成了,接下来就是来查看效果了,查看效果有两种方式,
1、是在代码中去获取值然后打印出来;
2、同步工程后在合并的清单文件中查看;
代码方式(这里以Application节点为例):
ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);String zzq = appInfo.metaData.getString("zzq");
清单文件中查看,首先得知道合并后的清单文件在哪,如下图:
上面红框中的清单文件就是合并后的清单文件,下面这个就是编译的版本(我是这么理解的,也可以说是变体),这里可以选择对应的版本,这里配置的只有两个,一是debug,二是release,选择其中一个,那么合并后的清单文件中就会产生对应的值。比如这里选的是debug版本,那么效果如下:
有时可能会遇到这样的问题,开发调试时一般安装的debug版本,但有时又需要安装release版本,这时可能会出现安装不了的情况,这问题就是由包名相同引起的,为了预防这样的问题,就可以在debug和release版本下配置不同的包名,如下:
debug { applicationIdSuffix '.debug' }
这样配置后就会在原包名后面添加.debug这个后缀,而release下面不配置,默认使用的就是原包名。
比如在应用开发的时候有网络请求,开发时的url和正式发布时的url可能就不一样,这时就可以在这里配置了。
release { buildConfigField('boolean','isDebug','false') buildConfigField('String','baseUrl','\"http://www.wanandroid.com/\"') } debug { buildConfigField('boolean','isDebug','true') buildConfigField('String','baseUrl','\"http://www.wanandroid.com/test/\"') }
url根据实际情况配置,这样配置好后,同步下工程,就会生成一个BuildConfig的java类,这个类里面全是静态的,看下这个文件的所在位置,如下图:
比如:
debug { resValue('string','my_name','android') }
接下来就可以在代码中使用了:
String appName = getResources().getString(R.string.my_name);
这里需要注意,如果这里只是在debug版本中添加了,那么只有在编译debug版本中才能用,编译的其他版本是没有这个属性的。上面讲的这些属性同样需要注意这点,不过在正常开发中,一般不会再在一个版本中配置,通常都是所有版本中都会配置。
这里我把他分为两步,一是配置自己jar的一些参数,二是配置生成jar的任务,这里就直接上代码了
1、配置参数,如果闲麻烦,可以直接在配置任务的地方去生成:
ext { JAR_VERSION = rootProject.ext.versions.versionName JAR_NAME = "cruzr-device-control" JAR_OUTPUT_DIR = 'build/libs' JAR_ORIGINAL_PATH = 'build/intermediates/packaged-classes/release/classes.jar'}
2、配置生成任务:
task makeJar(type: Jar) { from zipTree(file(JAR_ORIGINAL_PATH)) // 添加assets文件夹,如果不需要请删除该行 //from fileTree(dir: 'src/main', includes: ['assets/**']) baseName "${JAR_NAME}_${JAR_VERSION}_${releaseTime()}" destinationDir file(JAR_OUTPUT_DIR)}def static releaseTime() { return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))}
这样配置完成后,最后就只剩在控制台输入命令:gradlew makeJar(这里是方法的名字),这样就over了。
这里就先说到这,有什么不懂的欢迎一起讨论,下一篇再来说下版本差异化打包如何配置!
在新版的gradle中对这块有改动,以我目前studio 4.1.1的版本为例
task makejar(type:Jar,dependsOn: [':concurrent:assembleRelease',....]){ baseName("asyncTask") archiveVersion = "1.0" exclude('**/R.class') exclude('**/R$*.class') exclude('**/BuildConfig.class') exclude('**/BuildConfig$*.class') exclude('android/') from("../模块名/build/intermediates/javac/release/classes") from 'build/intermediates/javac/debug/classes'}
dependsOn:这个可有可没有,建议加上,如果不加上,每次在执行生产jar包命令时,都需要先build下,否则可能会有一些后面加的内容没有打进jar包或jar包中没有内容
baseName:生产jar包的名称,和archiveName有点像,不同的是archiveName需要加.jar的后缀,archiveName已经被废除,不推荐使用
archiveVersion:生成jar包的版本号
exclude:移除不需要的类
from:定义哪些类需要打进jar包中,如果没有定义,生成的jar包会没有内容
如果需要将资源文件打包进jar包,需要加上:
from fileTree(dir: 'src/main', includes: ['assets/**'])
from fileTree(dir: 'src/main', includes: ['res/**'])如果需要jar包打进jar包:
from(project.zipTree('libs/adapter.jar'))
jar包的混淆是基于已经生成jar的情况下,上面有说到jar包的生成,这里就继续接着往下说说混淆:
task proguardJar(type: proguard.gradle.ProGuardTask, dependsOn: "build") { //混淆配置 configuration 'proguard-rules.pro' // 未混淆的jar路径 injars 'build/libs/source.jar' // 混淆后的jar输出路径 outjars 'build/libs/proguard.jar'}
任务创建后,接着就是执行任务gradlew proguardJar
如果想让第二个任务基于第一个执行,可以添加
proguardJar.dependsOn(makejar)
这样,直接执行第二个任务的时候会先去执行第一个任务,也就是先执行makejar->proguardJar
关于混淆配置,可以先将一些常用配置添加进去,对于有其他jar包依赖的,需要加
-libraryjars 'C:\Users\Administrator\AppData\Local\Android\Sdk\platforms\android-29\android.jar'
-libraryjars '../speech/libs/adapter.jar' //后面这个是jar包路径
如果没有对依赖的jar包指定路径,执行任务时会报错