这一篇主要是说下gradle的一些常见使用,主要是几点配置:
目录
配置生成jar包(包含新版(studio 4.1.1)如何生成jar)
-
配置库工程的路径
include ':app', ':netlib',':emptylib'
settings.project(':emptylib').projectDir = file('empty/library')
在settings.gradle这样配置后,是什么意思呢?可以理解为就是将empty/library下的库工程取名为emptylib,在这样配置并build后,再来看下工程的目录结构有什么变化:
-
定义gradle额外变量
对于一个工程来说,可能会包含多个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 = 19
targetSdkVersionPro = 27
versionCodePro = 1
versionNamePro = 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"
}
}
看下输出:
19
27
1
1.0
对于有些属性定义在gradle.properties中是会包异常的,比如定义compileSdkVersion这个属性,使用的时候就会包异常,至于什么原因,暂时还不知道。所以这个用起来会比较简单,但是可能有一些坑要填。
再来说最后一种定义.gradle文件的属性,不过这种定义方式只是在当前文件中有效,但是没什么坑:
def compileSdkVersionPro = 27
android {
...
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这个文件,只不过我这里使用的想对路径,当然你也可以使用绝对路径,这里在贴下我放置这个文件的位置:
好了,签名文件就说到这里了。
-
配置apk输出文件名:
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.apk
outputFileName = app-debug.apk
modify outputFileName = debug_20180926_1.0
outputFile = E:\AndroidWorkProject\NetRequest\app\build\outputs\apk\release\app-release.apk
outputFileName = app-release.apk
modify outputFileName = release_20180926_1.0
这里有个需要注意的地方,这里只能配置outputFileName这个属性,不能配置outputFile,配置了这个会报异常,如下:
Cannot set the value of read-only property 'outputFile',意思就是说这个属性是一个只读属性,getTime()获取的是当前时间。
-
配置清单文件(AndroiodMenifest)占位符
比如在在清单文件有如下配置:
<meta-data android:name="zzq"
android:value="${zzq_name}"/>
可以看到这里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版本,那么效果如下:
<meta-data
android:name="zzq"
android:value="tangedegushi_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类,这个类里面全是静态的,看下这个文件的所在位置,如下图:
-
在字符串的xml文件中添加新值
比如:
debug {
resValue('string','my_name','android')
}
接下来就可以在代码中使用了:
String appName = getResources().getString(R.string.my_name);
这里需要注意,如果这里只是在debug版本中添加了,那么只有在编译debug版本中才能用,编译的其他版本是没有这个属性的。上面讲的这些属性同样需要注意这点,不过在正常开发中,一般不会再在一个版本中配置,通常都是所有版本中都会配置。
-
配置生成jar包(包含新版(studio 4.1.1)如何生成jar)
这里我把他分为两步,一是配置自己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包混淆(Android studio)
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包指定路径,执行任务时会报错
-
全局解决依赖冲突
在模块目录的build.gradle如下配置:
configurations {
// 移除指定模块
// implementation.exclude group:'com.android.support',module:'appcompat-v7'
all {
resolutionStrategy {
// 强制使用指定版本
// force 'com.android.support:appcompat-v7:25.2.0'
// force "com.github.bumptech.glide:glide:4.9.0"
eachDependency {
DependencyResolveDetails details ->
println "app group = ${details.requested.group}"
// if (details.requested.group == 'com.github.bumptech.glide' && details.requested.name == 'glide') {
// details.useVersion '3.6.0'
// }
}
}
}
}