Android - Gradle8.0.0+?从Gradle-DSL到Kotlin-DSL

升级总是伴随着痛苦,总是因为一些类的变动,查无此类、此方法、此属性,让人真是头大。不经一番彻骨寒,哪有梅花扑鼻香?下面是我升级中遇到的一些问题,我在这里做个简单的记录。如果不巧你也正在因为此事犯疑惑,那请看看以下内容是否能够帮到你?

升级中的变更说明如下:

  • settings.gradle.kts

      @file:Suppress("DEPRECATION", "UnstableApiUsage")
      pluginManagement {
          repositories {
              google()
              mavenLocal()
              mavenCentral()
              gradlePluginPortal()
              maven("https://jitpack.io")
          }
      }
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              //noinspection JcenterRepositoryObsolete
              jcenter()
              mavenLocal()
              mavenCentral()
              maven("https://jitpack.io")
          }
      }
      rootProject.name = "KtsDemo"
      include(":app")
    
  • 根目录 build.gradle.kts

      import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
      buildscript {
          val objectboxVersion by extra("3.6.0") //ext { ... } 的替代内容
          dependencies {
              classpath("io.objectbox:objectbox-gradle-plugin:$objectboxVersion")
          }
      }
    
      // 增加一下配置,防止出现错误:task (current target is 1.8) and 'kaptGenerateStubsUatDebugKotlin' task (current target is 17)
      allprojects {
          tasks.withType(KotlinCompile::class.java) {
              kotlinOptions {
                  jvmTarget = "1.8"
              }
          }
      }
    
      // 新式插件引入样式,注意ksp的引入需要与kotlin版本匹配,不然会报错
      plugins {
          id("com.android.application") version "8.0.0" apply false
          id("com.android.library") version "8.0.0" apply false
          id("org.jetbrains.kotlin.android") version "1.8.20" apply false
          id("com.google.devtools.ksp") version "1.8.20-1.0.11" apply false
      }
    
      apply(from = "本地的gradle.kts") //如果是导入第三方,使用apply(plugin="plugin名称")
    
    • 附言:
      如果项目中引入了外部的 Gradle.kts 文件,那么 Gradle.kts 中声明配置可如下:
          val appRootConfig by extra(mutableMapOf(
              "namespace" to "com.kts.demo",
              "appName" to "Demo",
              "applicationId" to "com.kts.demo"
          ))
      
  • 子模块 build.gradle.kts

      // 引入Plugin
      plugins {
          id("com.android.application")
          id("org.jetbrains.kotlin.android")
          id("kotlin-kapt") //kapt可与ksp并存,因为有些第三方的还未切换到ksp
          id("kotlin-parcelize")
          id("com.google.devtools.ksp") //引入ksp
      }
    
      // 引入根目录引入的外部gradle.kts的相关配置
      val appRootConfig by extra(rootProject.extra["appRootConfig"] as Map<String, *>)
    
      android {
    
          // 签名的导入
          signingConfigs {
              // 因为dev不存在,因此使用create方法
              create("dev") {
                  keyAlias = "Test"
                  keyPassword = "123456"
                  storePassword = "123456"
                  storeFile = file("./docs/sign-test.jks") //定位jsk签名文件位置
              }
          }
    
          namespace = appRootConfig["namespace"] as String //使用全局的配置属性
          compileSdk = 33
          buildToolsVersion = "33.0.0"
    
          defaultConfig {
              applicationId = appRootConfig["applicationId"] as String
              minSdk = 21
              targetSdk = 33
              versionCode = 1
              versionName = "1.0.0"
    
              testInstrumentationRunner = "..." //此处省略
    
              // 声明BuildConfig变量,需配置buildFeatures { buildConfig = true }
              buildConfigField("String", "APP_ENV_MODE", "\"DEBUG\"")
    
              // 如果有cpp相关的编译
              externalNativeBuild {
                  cmake {
                      cppFlags("")
                      abiFilters.add("armeabi-v7a") //add或者addAll
                  }
              }
    
              // 如果配置有NDK
              ndk { abiFilters.addAll(listOf("armeabi-v7a", "x86")) }
    
              // 如果有默认签名
              signingConfig = signingConfigs.getByName("dev")
          }
    
          buildFeatures {
              viewBinding = true
              buildConfig = true // 增加该属性,项目才能生成BuildConfig类
          }
    
          sourceSets {
              // 又创建了一个渠道:google,并引入它的清单文件
              create("google") {
                  manifest.srcFile("src/google/AndroidManifest.xml")
              }
          }
    
          kotlinOptions { jvmTarget = "1.8" } //指定使用Java8编译
          compileOptions {
              encoding = "UTF-8"
              sourceCompatibility = JavaVersion.VERSION_1_8
              targetCompatibility = JavaVersion.VERSION_1_8
          }
          packaging {
              resources {
                  merges.addAll(listOf("**/LICENSE.txt", "**/NOTICE.txt"))
                  excludes.addAll(listOf("/META-INF/{AL2.0,LGPL2.1}", "DebugProbesKt.bin"))
              }
          }
          flavorDimensions.addAll(listOf("prod")) //原来写法是:flavorDimensions = ["a", "b"]
              productFlavors {
                  // 创建一个“风味”名称
                  create("google") {
                      dimension = "prod"
                      versionCode = 1
                      versionName = "1.0.0"
                      applicationId = "com.demo.kts"
                      buildConfigField("String", "APP_CHANNEL_NAME", "\"Google\"")
                  }
              }
          }
    
          buildTypes {
              // debug { signingConfig signingConfigs.dev }
              release {
                  isDebuggable = true
                  isJniDebuggable = true
                  isMinifyEnabled = true
                  isShrinkResources = true
                  signingConfig = signingConfigs.getByName("dev")
                  //noinspection ChromeOsAbiSupport
                  ndk { abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86_64")) }
                  proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
              }
          }
    
          dependencies {
              implementation("androidx.core:core-ktx:1.10.1")
              implementation("androidx.activity:activity-ktx:1.7.2")
              implementation("androidx.fragment:fragment-ktx:1.6.0")
              implementation("androidx.appcompat:appcompat:1.6.1")
              implementation("com.google.android.material:material:1.9.0")
              implementation("androidx.constraintlayout:constraintlayout:2.1.4")
              //... 省略许多,许多
              api(project(":common")) //引入其他模块
              implementation(project(":test")) //引入其他模块
          }
      }
    
    • 其他需要注意的事项
      因为项目使用的Gradle8.0.0+,所以R8模式是默认全开的,会导致一些类在经过混淆后出现问题,特别典型的是:Gson库,请看:ISSUE。通过尝试,需要设置如下规则:

      Gson混淆规则:

          ##---------------Begin: proguard configuration for Gson ----------
          # Gson uses generic type information stored in a class file when working with fields. Proguard
          # removes such information by default, so configure it to keep all of it.
          # Gson specific classes
          # -keep class sun.misc.Unsafe { *; }
          # Gson uses generic type information stored in a class file when working with
          # fields. Proguard removes such information by default, keep it.
          # -keepattributes Signature
          # This is also needed for R8 in compat mode since multiple
          # optimizations will remove the generic signature such as class
          # merging and argument removal. See:
          # https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md#troubleshooting-gson-gson
          -keep class com.google.gson.reflect.TypeToken { *; }
          -keep class * extends com.google.gson.reflect.TypeToken
          # Optional. For using GSON @Expose annotation
          -keepattributes AnnotationDefault,RuntimeVisibleAnnotations
          -keepclassmembers class * {
          !transient <fields>;
          }
          -if class *
          -keepclasseswithmembers class <1> {
              <init>(...);
              @com.google.gson.annotations.SerializedName <fields>;
          }
          ##---------------End: proguard configuration for Gson ----------
      

      Retrofit也需要做如下混淆:

          -if interface * { @retrofit2.http.* public *** *(...); }
          -keep,allowoptimization,allowshrinking,allowobfuscation class <3>
      
          # Platform calls Class.forName on types which do not exist on Android to determine platform.
          -dontnote retrofit2.Platform
      

      针对协程相关的混淆:

          # -keepattributes Signature
          -keep class kotlin.coroutines.Continuation
      

      ** 如果在升级kotlin-dsl出现Parcelable报错等问题,试试读取使用方法BundleCompat.getParcelable*(args) **

  • 一步一个脚印,总算是解决了升级的问题。如果觉得有帮助,麻烦动动您发财的小手给点个赞!原创内容,转载请注明作者和出处,谢谢!

对了,这里在增加一个WARING! 虽然上面的内容都正常运转了,我还是遇到了一个新问题,就是打包时,如何用kts给APK重命名,使其打包出来就是我们想要的名字,因为原来的 output.setOutputFileName 已经无法使用,暂未找到解决方案,正在探索中。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容