-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.gradle
441 lines (392 loc) · 17.6 KB
/
build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
plugins {
id 'com.android.application'
// id 'kotlin-android'
// id 'kotlin-kapt'
// id 'com.yl.login'
}
//抽离Task脚本
//apply from: '../taskcode.gradle'
//局部定义变量
def compileSdkNum = 31
//实现versionName自增
def autoVersionName() {
def branch = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD'
standardOutput = branch
}
def cmd = 'git describe --tags'
def version = cmd.execute().text.trim()
println '版本号:' + version
return branch.toString().trim() == "master" ? version :
version.split('-')[0] + '-' + branch.toString().trim() // v1.0.1-dev
}
//实现versionCode自增
def autoVersionCode() {
def cmd = 'git tag --list'
def code = cmd.execute().text.trim()
println 'code1:' + code
return code.toString().split("\n").size()
}
//签名
Properties props = new Properties()
File f = file(rootProject.file("signing.properties"))
// 如果这个签名文件存在则用,如果不存在就从gradle.properties中取
if (!f.exists()) {
f = file(rootProject.file("gradle.properties"))
}
props.load(new FileInputStream(f))
//gradle基本知识:https://www.jianshu.com/p/47cbbb4eab13、https://www.jianshu.com/p/ffcb7bba21a2
android {
signingConfigs {
debug {
storeFile file(props['STORE_FILE_PATH'])
storePassword props['STORE_PASSWORD']
keyAlias props['KEY_ALIAS']
keyPassword props['KEY_PASSWORD']
}
release {
storeFile file(props['STORE_FILE_PATH'])
storePassword props['STORE_PASSWORD']
keyAlias props['KEY_ALIAS']
keyPassword props['KEY_PASSWORD']
}
}
//编译时的SDK版本号
// 告诉gradle用那个Android SDK的版本编译你的应用,修改它不会改变运行时的行为,因为它不会被包含进入最终的APK中;因此,推荐使用最新的SDK编译;如果使用Suppport Library,那么compileSdkVersion必须要大于等于它的大版本号
compileSdk compileSdkNum
//编译时指定的buildtools版本
// buildToolsVersion "31.0.0"
defaultConfig {
manifestPlaceholders TYPE: 1
manifestPlaceholders APP_NAME: '测试专用'
// applicationId "com.example.testapp"
//修改app包名
applicationId 'com.yl.test'
// 应用最低可运行的要求;它必须要大于等于你所依赖的库的minSdkVersion
minSdk rootProject.ext.minSdkVersion
// Android提供向前兼容的重要依据
// 因为随着Android系统的升级,某个api或者模块的行为有可能发生改变,但是为了保证老APK的行为和以前兼容,只要APK的targetSdkVersion不变,那么即使这个APK安装在新的Android系统上,那么行为还是保持老的系统上的行为。
// 系统在调用某个api或者模块的时候,会先检查调用的APK的targetSdkVersion,来决定执行什么行为。
targetSdk rootProject.ext.targetSdkVersion
versionCode autoVersionCode()
versionName autoVersionName()
//包名后缀
// applicationIdSuffix 'xy'
//执行单元测试时指定的Runner,在正式打包时并不会使用到
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//版本号后缀
versionNameSuffix '.yl'
//签名方式
signingConfig signingConfigs.debug
//混淆文件
proguardFiles 'proguard-rules.pro'
//是否分包,解决方法数大于65k的问题
multiDexEnabled true
// resourceConfigurations += ['COMMON_COLOR']
// String中的引号记得加转义符
buildConfigField 'String', 'API_URL', '"http://www.kale.com/api"'
buildConfigField "boolean", "IS_FOR_TEST", "true"
buildConfigField "String", "LAST_COMMIT", "\"" + revision() + "\""
resValue "string", "build_host", hostName()
//声明一个或多个维度
flavorDimensions "test"
// flavorDimensions "test","test2" // 按照先后进行排序
// 过滤,对于国际化支持只打包中文资源,和"xxhdpi"
// 注意如果在这里指定了dpi,则flavor中不能指定的dpi与这里必须一致否则会报错
resConfigs "zh-rCN", "xhdpi"
}
buildTypes {
debug {
//可以调试
debuggable true
//jni可调试
jniDebuggable true
//渲染脚本可调试
renderscriptDebuggable true
//minifyEnabled表示代码是否可以压缩,裁剪优化,需要配合其他的工具一起使用,如proguard
//添加代码混淆,注意添加混淆时,必须将minifyEnabled 置为true,否则混淆不生效
//同样如果没有使用代码混淆必须置为false,否则编译失败
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
release {
//压缩对齐,提高运行时的效率,也可以使用zipAlignEnabled true
zipAlignEnabled true
minifyEnabled true //是否混淆
// 当我们需要动态加载资源时,需要在不要使用该优化,否则可能会出现运行时报错或者显示效果不正确的问题
shrinkResources true // 是否去除无效的资源文件 https://developer.android.google.cn/build/shrink-code?hl=zh-cn
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
//添加一个字符资源到values/strings.xml文件中,目前无法指定资源的语言类别
resValue "string", "custom_name", "测试用户"
}
rtm.initWith(buildTypes.release) // 继承release的配置
rtm {
zipAlignEnabled false // 覆盖release中的一些配置
}
}
//在打包时,移除一些许可,注意文档
packagingOptions {
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
}
lintOptions {
//关闭编译release版本的lint检查
checkReleaseBuilds false
//关闭link检查报错中断编译选项
abortOnError false
}
//module是支持到Java8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
// 动态生成所有渠道的APK
android.applicationVariants.all { variant ->
variant.outputs.all { output ->
if (variant.buildType.name == 'release' || variant.buildType.name == 'debug') {
// 为发布版本定义一个通用的命名模式
def fileName = "${variant.flavorName}-${variant.buildType.name}_${releaseTime()}.apk"
outputFileName = fileName
}
//1、对于某些不想打包的Flavor或者维度,我们可以利用variantFilter进行操作,
//下面的代码会将“minApi21”和“demo”的类型直接跳过:
// def names = variant.flavors*.name
// // To check for a build type instead, use variant.buildType.name == "buildType"
// if (names.contains("minApi21") && names.contains("demo")) {
// // Gradle ignores any variants that satisfy the conditions above.
// setIgnore(true)
// }
//2、改名
// def outputFile = output.outputFile
// print '原始包名:' + outputFile.name + "\n"
// if (outputFile != null && outputFile.name.endsWith('.apk')) {
// def fileName = outputFile.name.replace("app",
// "${variant.flavorName}_${variant.buildType.name}_${releaseTime()}")
// outputFileName = fileName
// }
}
//3、自动打开apk的目录
//下面的脚本通过applicationVariants来监听apk生成的时机,如果是Rlease版本就打开文件管理器:
variant.assemble.doLast {
//If this is a 'release' build, reveal the compiled apk in finder/explorer
if (variant.buildType.name.contains('release')) {
def path = null
variant.outputs.each { output ->
path = output.outputFile
}
println "apk路径:" + path
if (path != null) {
if (System.properties['os.name'].toLowerCase().contains('mac os x')) {
['open', '-R', path].execute()
} else if (System.properties['os.name'].toLowerCase().contains('windows')) {
['explorer', '/select,', path].execute()
}
}
}
}
}
//适配所有Flavor的
productFlavors.all { flavor ->
manifestPlaceholders.put("UMENG_CHANNEL", name)
}
// 定义所有渠道列表
productFlavors {
flavor1 {
// 渠道特定的配置
versionNameSuffix "-flavor1"
// applicationIdSuffix ".flavor1"
buildConfigField 'String', 'API_URL', '"http://www.kale.com/api1"'
dimension "test"
}
flavor2 {
// 渠道特定的配置
// applicationId "x.y.z"
versionNameSuffix "-flavor2"
applicationIdSuffix ".flavor2"
buildConfigField 'String', 'API_URL', '"http://www.kale.com/api2"'
dimension "test"
}
// ... 更多渠道 ...
}
// 根据flavor和build type设置不同的源码和资源目录
sourceSets {
// srcDir和srcDirs的区别,当使用srcDir指定文件目录时,不允许将要合并的源集的同一目录下有一样名称的资源,提示重复资源异常,而srcDirs则会根据前面所说的优先级进行覆盖。
// 替换res资源采用的是合并的原则,即最终的资源是所有进行合并的资源的并集,出现资源ID重复的资源,采用优先级最高的那个
// 注意,layout资源是以整个文件覆盖的方式合并的。
// assets目录中的文件是以整个文件覆盖的方式进行合并的。
flavor1 {
java.srcDirs = ['src/main']
res.srcDirs += 'src/main/res'
//指定一个新的jnilibs为根目录下的jnilibs
// jniLibs.srcDirs=[rootProject.projectDir.absolutePath + '/jnilibs']
//指定一个新的assets为根目录下的skyTestAssets目录
// assets.srcDirs = [rootProject.projectDir.absolutePath + '/assets/skyTestAssets']
//意图过滤掉`src/main/assets/mainIngoreTest.txt`文件
// assets.exclude (project.projectDir.absolutePath + "\\src\\main\\assets\\mainIngoreTest.txt")
//或者采用闭包
assets.exclude{
File ff = it.file
println ff.absolutePath
ff.absolutePath.endsWith("mainIngoreTest.txt")
}
}
flavor2 {
java.srcDirs = ['src/flavor2']
res.srcDirs += 'src/flavor2/res'
}
}
// 4、强制版本号
configurations.all {
// 指定某个库的版本
resolutionStrategy.force "androidx.appcompat:appcompat:1.3.0"
// 一次指定多个库的版本
resolutionStrategy {
force 'com.android.support.test.espresso:espresso-core:3.4.0',
"androidx.appcompat:appcompat:1.3.0"
}
}
}
//打包的时间
static def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
static def hostName() {
def userName = System.getProperty("user.name")
def hostName = InetAddress.localHost.hostName
print 'user.name:' + userName + ',hostName:' + hostName + '\n'
return System.getProperty("user.name") + "@" + InetAddress.localHost.hostName
}
//最新提交版本号
def revision() {
def code = new ByteArrayOutputStream()
exec {
// 执行:git rev-parse --short HEAD
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = code
}
print 'code2:' + code
return code.toString().substring(0, code.size() - 1) // 去掉最后的\n
}
ext.PLUGIN = true
ext.isPlugin = {
try {
if (PLUGIN.toBoolean()) {
return true
}
} catch (Exception ignore) {
}
return false
}
dependencies {
implementation "androidx.appcompat:appcompat:$appcompat"
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
// implementation 'com.github.LittleYellowFish:CommonPro:1.0'
implementation fileTree(dir: '../libs', include: '*.aar')
implementation fileTree(dir: '../libs', include: '*.jar')
// 1、api 编译时依赖和运行时依赖
// implementation 基础依赖方式,运行时依赖,对于依赖结构做了优化
// compileOnly 类似于provided,仅仅在编译时进行依赖,不会将依赖打包到app中
// runtimeOnly 类似于apk,它仅仅将依赖打包到apk中,在编译时无法获得依赖的类
// annotationProcessor 类似于apt,是注解处理器的依赖
// testImplementation Java测试库的依赖,仅仅在测试环境生效
// androidTestImplementation Android测试库的依赖,仅仅在测试环境生效
// [Flavor]Api 针对于某个Flavor的依赖,写法是Flavor的名称+依赖方式
// buildTypes是debug的时候才能被依赖
// debugImplementation 'com.github.nekocode.ResourceInspector:resinspector:0.5.3'
// 编写时无法访问lib中的资源,lib会被打包到apk中
// runtimeOnly project(':lib')
// 编译时进行依赖,不会将依赖打包到app中
// compileOnly 'com.baoyz.treasure:treasure:0.7.4'
// BuildTypes为test的 依赖项junit
// testCompile 'junit:junit:4.12'
// BuildTypes为debug的添加含有源码的模块依赖
// debugCompile project(":mylibrary")
// flavor为sky的指定jar库,且不使用`okhttp-3.2.0.jar`库,使用skyCommon目录下的okhttp-3.3.1.jar
// skyCompile fileTree(include: ['*.jar'], dir: 'jar/sky', excludes: ['okhttp-3.2.0.jar'])
// 构建变体依赖项指定
// skyCommonClientCustomCompile fileTree(include: ['*.jar'], dir: 'jar/skyCommonClientCustom')
// 2、组合依赖,有相关性的
implementation([
'io.reactivex.rxjava2:rxjava:2.1.3',
'io.reactivex.rxjava2:rxandroid:2.0.1'
])
// 3、依赖传递
// @符号的作用是仅仅下载文件本身,不下载它自身的依赖,等于关闭了以来传递。如果你要支持依赖传递,那么就必须要写transitive = true
implementation("androidx.appcompat:appcompat:1.3.0@aar") {
transitive = true
}
// 4、强制版本号
// 们还可以通过force来强制指定某个库的版本号:
implementation group: 'androidx.appcompat', name: 'appcompat', version: '1.3.0', force: true
// 5.1exclude关键字
// implementation('com.android.support:appcompat-v7:23.2.0') {
// exclude group: 'com.android.support', module: 'support-annotations' // 写全称
// exclude group: 'com.android.support', module: 'support-compat'
// exclude group: 'com.android.support', module: 'support-v4'
// exclude group: 'com.android.support', module: 'support-vector-drawable'
// }
// 5.2剔除整个组织的库(一下子剔除所有support库):
// implementation('com.facebook.fresco:animated-webp:0.13.0') {
// exclude group: 'com.android.support' // 仅仅写组织名称
// }
// 5.3全局剔除某个库
// configurations {
// all*.exclude group: 'org.hamcrest', module: 'hamcrest-core'
// }
// 6、优化依赖
// ext.libs =
// ['com.baoyz.treasure:treasure:0.7.4',
// 'com.squareup.okhttp3:okhttp:3.9.0',
// 'io.reactivex.rxjava2:rxjava:2.1.3']
//
// if (isPlugin()) {
// compileOnly(libs) // 不将依赖打入App中
// } else {
// implementation(libs)
// }
//
// if (isPlugin()) {
// implementation project(':releaselib')
// } else {
// implementation project(':debuglib')
// }
// 7、优化配置
// 并不定义PLUGIN这个变量
//ext.PLUGIN = true
// ext.isPlugin = {
// try {
// if (PLUGIN.toBoolean()) {
// return true
// }
// } catch (Exception ignore) {
// }
// return false
// }
// 执行命令行时可进行修改:
// gradlew clean -P PLUGIN=true installInnertestDevDebug
// 8、依赖module:
// implementation project(':lib')
// 如果的module在多级目录中,那么首先要在settings.gradle中进行配置:
// include ':app', ':lib', ':libraries:lib01', ':libraries:lib02'
// implementation project(':libraries:lib01')
// implementation project(':libraries:lib02')
// 依赖当前module的libs目录下的所有jar
// implementation fileTree(dir: 'libs', include: ['*.jar'])
// 依赖外部目录,librarymodule中libs目录下的所有jar
// implementation fileTree(dir: '../somedir/libstore', include: '*.jar')
}