# 排除 Kotlin 2 导致的 Android 构建失败

> 使用 Unity 2022 长期支持版本 或更高版本进行构建时，发现并修复由 LevelPlay 9.6.0 中引入的 Kotlin 2 依赖项关系导致的 Android 构建失败。

如果将 Unity 2022 长期支持版本 或更高版本与 LevelPlay SDK 9.6.0 结合使用，可能会遇到 Android 构建失败。本指南介绍如何识别和解决这些问题。

> **Note:**
>
> 此构建失败问题仅影响 Unity 2022 长期支持版本 或更高版本。Unity 6 及更高版本支持与较新的构建工具链兼容，不受影响。

## 症状##symptom

将 LevelPlay Unity 广告服务 Mediation) 软件包级到 9.6.0 后，Android 构构建会失败并显示以下报错：

```xml
注意：某些输入文件使用或覆盖已弃用的 API。
注意：有关详细信息，请使用 -Xlint:deprecation 重新编译。
报错：D8：com.android.tools.r8.kotlin.H

失败：构建完成，但 2 次失败。

1:任务失败，出现异常。
-----------
* 问题出在哪里：
  任务“:启动器:mergeExtDexRelease”的执行失败。
> 无法解析配置“:启动器:releaseRuntimeClasspath”的所有文件。
> 变换 kotlin-stdlib-2.1.21.jar (org.jetbrains.kotlin:kotlin-stdlib:2.1.21)
  匹配 {artifactType=android-dex, ...}。
> DexingWithClasspathTransform 的执行失败：
  .../transformed/jetified-kotlin-stdlib-2.1.21.jar.
> 取消激活时报错。

2:任务失败，出现异常。
-----------
* 问题出在哪里：
  java.lang.StackOverflowError（无报错消息）

构建失败
```

此报错消息中的两个指标确认这是 Kotlin 2 兼容性问题：

1. `ERROR:D8: com.android.tools.r8.kotlin.H` 行显示在输出中。
2. 失败的瑕疵是`kotlin-stdlib-2.1.21.jar`（或任何`Kotlin 2.x stdlib`）。

## 原因##causes

Android 构建失败可能出于以下原因：

* LevelPlay SDK 9.6.0（及其某些网络适配器）对 Kotlin 2.x 标准库（`kotlin-stdlib-2.1.21`）有依赖项。
* Unity 2022 长期支持版本 捆绑了早于 Kotlin 2 支持的 AGP/R8 版本。捆绑的 D8/R8 无法显示为`D8: com.android.tools.r8.kotlin.H`报错和辅助`StackOverflowError`的 Kotlin 2 stdlib 元数据。

## 解决方案##resolution

要解决此问题，请按照以下说明向`settingsTemplate.gradle`添加`buildscript`代码块来覆盖 R8：

1. 如果项目中还没有`settingsTemplate.gradle`文件，请在 Unity Editor 中通过执行以下操作启用该文件：
   a.选择 **File**（文件）> **Build Settings（构建设置**）。
   b.选择 **Android** 作为平台，然后选择 **玩家设置**。**项目设置**窗口打开。
   c.在 **Android Settings** 选项卡中，转到 **Publisher Settings**，然后启用 **Custom Gradle Settings 模板**。这样做可以使 Unity 在 中`ssets/Plugins/Android/settingsTemplate.gradle`使用 **ARTIFACTORYREPOSITORY** 和 **DIR\_UNITYPROJECT** 令牌创建文件。
2. Open `Assets/Plugins/Android/settingsTemplate.gradle`.open
3. 添加从 Google R8 版本 Maven 中提取 R8 8.5.35 的`buildscript`代码块。将其直接添加到现有`pluginManagement`代码块之后：

> **Note:**
>
> 建议的最佳做法是使用 R8 版本 8.5.35，因为它是 Unity 2022 长期支持版本 LevelPlay 9.6.0 的验证版本。但是，您可以使用比 8.5.35 更新的 R8 版本。具体而言，任何大于或等于 8.5.x 且支持 Kotlin 2 的 R8 版本都将正常工作。

```kotlin
pluginManagement {
    repositories {
        **ARTIFACTORYREPOSITORY**
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}

buildscript {
    repositories {
        maven {
            url "https://storage.googleapis.com/r8-releases/raw"
        }
    }
    dependencies {
        classpath 'com.android.tools:r8:8.5.35'
    }
}
```

> **Note:**
>
> 解决此问题不需要 Kotlin Gradle 插件升级。故障发生在 dex 管线中，而不是 Kotlin 编译中，因此只需要升级 R8。

以下代码行强制 Gradle 解析 R8 8.5.35（支持 `Kotlin 2 stdlib`），然后 Android Gradle 插件才能选择其捆绑的过时版本。然后，`mergeExtDexRelease`任务使用较新的 R8，构建成功完成。

```kotlin
buildscript { dependencies { classpath 'com.android.tools:r8:...' } }
```

> **Note:**
>
> 覆盖 R8 不会影响非 Kotlin 代码。这只会更改 Dexer/shrinker 版本，不会改变应用程序代码、AGP 版本或缩小规则。

## 验证分辨率##verify-the-resolution

1. 通过从项目根目录运行以下命令来关闭所有打开的 Gradle 守护程序：
   `./gradlew --stop.`或者，也可以通过运行以下命令删除 Gradle 变换： `~/.gradle/caches/transforms-3/`
2. 在 Unity 编辑器中，转到**文件** > **构建设置…** > **构建（发布配置）**。
3. 确认`:launcher:mergeExtDexRelease`任务完成并且 APK 或 AAB 构建时没有 D8 报错。

如果报错仍然存在，请尝试以下操作：

* 确认`buildscript`代码块处于`settingsTemplate.gradle`状态而不是处于`mainTemplate.gradle`或`baseProjectTemplate.gradle`状态。
* 确认没有其他模板正在重新引入较旧的 R8 类路径。
  0- 使用以下命令清除 Gradle 变换缓存，然后重新构建：`rm -rf ~/.gradle/caches/transforms-3/`
