前言
前文buildSrc使用,依赖统一管理。gradle版本一升级我就懵逼,经常在gradle和kts之间来回切,记录一下。
什么是Kotlin DSL
Android Studio是使用Gradle来编译,而默认的构建语言是Groovy,但是Gradle实际上是支持Kotlin来编写Gradle构建脚本的,常见的构建脚本是.gradle结尾,而Koltin语法编写的脚本则是.gradle.kts。
Gradle官网也是给出了Groovy迁移Kotlin的指导文章:Migrating build logic from Groovy to Kotlin
关于Gradle脚本改造
首先后缀从.gradle修改为 gradle.kts,有几个注意点
- Groovy字符串可以用单引号’string’或双引号引起来"string",而Kotlin需要双引号"string"。
- Groovy允许在调用函数时省略括号,而Kotlin始终需要括号。
- adle Groovy DSL允许=在分配属性时省略赋值运算符,而Kotlin始终需要赋值运算符。
- 部分设置字段变动了,部分以前能直接写的需要通过getByName获取了。
//示例
buildTypes {
//release变成了getByName("release")
getByName("release") {
//minifyEnabled变成了isMinifyEnabled
isMinifyEnabled = false
}
}
改造前
rootProject.name = "MyApplication"
include ':app'
include ':common'
改造后
rootProject.name = "MyApplication"
include(":app")
include(":common")
改造前
buildscript {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31"
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
改造后
buildscript {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
// maven { url=uri("https://maven.aliyun.com/repository/public") }
// maven { url=uri("https://maven.aliyun.com/repository/google/") }
// maven { url=uri("https://maven.aliyun.com/repository/gradle-plugin")}
}
dependencies {
classpath("com.android.tools.build:gradle:4.1.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31")
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
// maven { url = uri("https://maven.aliyun.com/repository/public") }
// maven { url=uri("https://maven.aliyun.com/repository/google/") }
// maven { url=uri("https://maven.aliyun.com/repository/gradle-plugin")}
}
}
tasks.register("clean", Delete::class) {
delete(rootProject.buildDir)
}
改造前
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-parcelize'
id 'kotlin-kapt'
}
android {
compileSdk 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.phz.myapplication"
minSdk 21
targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
修改后
plugins {
id("com.android.application")
kotlin("android")//id("kotlin-android")
kotlin("kapt")
id("kotlin-parcelize")
}
android {
compileSdk = BuildConfig.compileSdkVersion
defaultConfig {
applicationId = BuildConfig.applicationId
minSdk = BuildConfig.minSdkVersion
targetSdk = BuildConfig.targetSdkVersion
versionCode = BuildConfig.versionCode
versionName = BuildConfig.versionName
testInstrumentationRunner = BuildConfig.testInstrumentationRunner
multiDexEnabled = true
}
base{
//Android Studio 默认通过构建类型名称添加 versionNameSuffix
//输出包名示例:BlueToothHelper(1.0.0)-release
archivesBaseName = "BlueToothHelper(${BuildConfig.versionName})"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
versionNameSuffix ="-R"
}
lintOptions {
isCheckReleaseBuilds = false
isAbortOnError = false
}
}
packagingOptions {
resources.excludes += "META-INF/gradle/incremental.annotation.processors"
}
compileOptions {
// sourceCompatibility = JavaVersion.VERSION_11
// targetCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
// jvmTarget = 11
jvmTarget = "1.8"
}
buildFeatures {
dataBinding = true
viewBinding = true
}
}
dependencies {
implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
implementation(project(mapOf("path" to ":common")))
implementation(AndroidX.coreKtx)
implementation(AndroidX.appcompat)
testImplementation(Testing.junit)
androidTestImplementation(Testing.androidJunit)
androidTestImplementation(Testing.espresso)
//material包
implementation(Google.material)
}
问题记录
Unresolved reference
gradle Unresolved reference:outputFileName
其实这个问题挺常见的,首先随着gradle版本的升级,某些命令不支持了。然后是因为gradle变成了kts?(内心os:还是gradle懂得太少😅)
关于ndk模块修改
import kotlin.collections.*
android {
compileSdk = BuildConfig.compileSdkVersion
defaultConfig {
ndk {
abiFilters.addAll(arrayListOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64"))
}
}
}
设置不起作用
以前写的设置不起作用了,以一个修改打包名字的设置为例:
applicationVariants.all { variant ->
variant.outputs.all { output ->
def fileName = "yxx_${variant.versionName}.apk"
def outFile = output.outputFile
if (outFile != null && outFile.name.endsWith('.apk')) {
outputFileName = fileName
}
}
}
尝试转换成kotlin后:
applicationVariants.all { variant ->
variant.outputs.all { output ->
val fileName = "yxx_${variant.versionName}.apk"
val outFile = output.outputFile
if (outFile != null && outFile.name.endsWith(".apk")) {
val file=File(outFile.parent, fileName)
if (file.exists()){
file.delete()
}
outFile.renameTo(file)
}
true
}
true
}
尝试打包发现包名没有变化,不知道哪里出了问题,只好这样写了:
base{
archivesBaseName = "yxx(${BuildConfig.versionName})"
}
加餐
补充1:gradle3.0前后依赖配置项改变对比表
3.0之前 | 3.0之后 | 备忘 |
---|
compile | implementation | 其他模块只有在运行时才能使用该依赖项。(不具有传递性) | compile | api | 该方式依赖的库将会参与编译和打包。(依赖具有传递性) | provided | compileOnly | 编译时有效,不参与打包。(常用于依赖一些容易冲突的包) | apk | runtimeOnly | Gradle 只会将依赖项添加到构建输出,以便在运行时使用。 | compile | annotationProcessor | 将编译类路径与注释处理器类路径分开 |
补充2:gradle的几个实用小技巧
- gradle build --scan命令用于查看依赖树
详见gradle常见的问题记录,同一个库导了几个版本的包,如何查看依赖树并手动排除。 - gradle模块化
如果用过greendao之类的库,应该有所了解。
apply plugin: 'org.greenrobot.greendao'
greendao {
schemaVersion 1 //数据库版本号
//省略...
}
//省略...
其实我们可以新建一个greendao-config.gradle文件,把这块放进去。然后导入gradle。这样做的好处就是精简了gradle代码,而且遵循单一职责原则。
apply from '../greendao-config.gradle'
- 资源文件分包
string.xml太大不好找?colors.xml颜色太多?没关系,我们可以按照模块对res进行分包。
android {
sourceSets {
main {
res.srcDirs(
'src/main/res',
'src/main/res_core',
'src/main/res_seed',
)
}
}
}
然后就可以在res_core包下放资源了,值得注意的是,虽然是分包,但是资源还是可以相互拿的,只要不冲突。 4. buildSrc+kotlin可以提供全局复用的依赖管理。 5. 遍历方式依赖写法。 config.gradle
ext{
dependencies = [
// base
"appcompat": "androidx.appcompat:appcompat:1.3.0",
//省略其他...
]
}
//省略其他...
在build.gradle里引用
apply from config.gradle
def implementationDependencies = project.ext.dependencies
//省略其他...
dependencies{
implementationDependencies.each { k, v -> implementation v }
//当然除了implementation 还有其他的,比如kapt/annotationProcessor
}
|