unity-android和gradle升级

Posted 蝶泳奈何桥.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity-android和gradle升级相关的知识,希望对你有一定的参考价值。


title: unity-android和gradle升级
categories: Unity3d
tags: [unity, android, gradle, 升级]
date: 2022-01-23 15:33:10
comments: false
mathjax: true
toc: true

unity-android和gradle升级, 使用的 unity 版本是 2018.4.36f1 (LTS)


前篇

适配 android 11,12 的需要


sdk 升级到 最新版本后 unity 打包问题

报错无法识别的属性名模块: unrecognized Attribute name MODULE

  • 完整报错

    CommandInvokationFailure: Gradle build failed. 
    D:\\unity2018.4.36f1\\Editor\\Data\\PlaybackEngines\\AndroidPlayer/Tools\\OpenJDK\\Windows\\bin\\java.exe -classpath "D:\\unity2018.4.36f1\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Tools\\gradle\\lib\\gradle-launcher-5.1.1.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
    
    stderr[
    编译器 (1.8.0-adoptopenjdk) 中出现异常错误。如果在 Bug Database (http://bugs.java.com) 中没有找到该错误, 请通过 Java Bug 报告页 (http://bugreport.java.com) 建立该 Java 编译器 Bug。请在报告中附上您的程序和以下诊断信息。谢谢。
    java.lang.AssertionError: annotationType(): unrecognized Attribute name MODULE (class com.sun.tools.javac.util.UnsharedNameTable$NameImpl)
        at com.sun.tools.javac.util.Assert.error(Assert.java:133)
        at com.sun.tools.javac.code.TypeAnnotations.annotationType(TypeAnnotations.java:231)
        at com.sun.tools.javac.code.TypeAnnotations$TypeAnnotationPositions.separateAnnotationsKinds(TypeAnnotations.java:294)
        at com.sun.tools.javac.code.TypeAnnotations$TypeAnnotationPositions.visitVarDef(TypeAnnotations.java:1164)
        at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:852)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
    
  • 原因

    使用的自定义 gradle (mainTemplate.gradle) 中使用的 tool (4.0.0) 版本高于 unity 自带的 gradle 版本 (5.1.1)

    buildscript 
        dependencies 
            classpath 'com.android.tools.build:gradle:4.0.0' # 对应的 gradle 版本是 6.1.1
    **BUILD_SCRIPT_DEPS**
    
    

    gradle tool 版本对应关系 - https://developer.android.com/studio/releases/gradle-plugin?hl=zh-cn#updating-gradle

  • 解决办法: [gradle 升级](#gradle 升级)


android 升级

升级到 32

  1. 下载 android-studio-2020.3.1.26-windows.zip

    新版 as 编辑器默认不显示 gradle 任务, 需要手动打开

    settings -> experimental, 取消勾选 do not build gradle task list during…

  2. 更新 sdk,tools

  3. 修改 build-tools

    1. %ANDROID_SDK%\\build-tools\\32.0.0 目录下的 d8.bat 改成 dx.bat
    2. %ANDROID_SDK%\\build-tools\\32.0.0\\lib 目录下的 d8.jar 改成 dx.jar

模块升级

  1. 将每个模块的 gradle 构建版本都改成新版本

    android 
        compileSdkVersion 32
        buildToolsVersion '32.0.0'
        defaultConfig 
            targetSdkVersion 32
        
    
    
  2. 如果有引入 androidx.test 单元测试 , 也将版本升级一下

    单元测试最新版本: https://developer.android.com/jetpack/androidx/releases/test?hl=zh-cn

    androidTestImplementation 'androidx.test:core:1.4.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test:runner:1.4.0'
    androidTestImplementation 'androidx.test:rules:1.4.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    
    • 不然可能出现 构建 app 正常, 执行单元测试用例却失败的情况, 报错: processdebugandroidtestmanifest manifest merger failed

    • 也可以在 gui 中升级


踩坑

gradle tool 升级报错已损坏

报错: Installed Build Tools revision 32.0.0 is corrupted. Remove and install again using the SDK Manager. 错误

gradle 配置的是 32.0.0

android 
    compileSdkVersion 32
    buildToolsVersion '32.0.0'
    defaultConfig 
        minSdkVersion 19
        targetSdkVersion 32
    

改成 31.0.0 也报类似的错误

原因是:

The main problem is the two files missing in SDK build tool 31 that are:

  1. dx.bat
  2. dx.jar

解决办法:

  1. %ANDROID_SDK%\\build-tools\\32.0.0 目录下的 d8.bat 改成 dx.bat
  2. %ANDROID_SDK%\\build-tools\\32.0.0\\lib 目录下的 d8.jar 改成 dx.jar

参考: https://stackoverflow.com/questions/68387270/android-studio-error-installed-build-tools-revision-31-0-0-is-corrupted


gradle 升级

  • 各版本 gradle 下载地址 - https://services.gradle.org/distributions/
  • gradle tool 版本对应关系 - https://developer.android.com/studio/releases/gradle-plugin?hl=zh-cn#updating-gradle
  1. 下载 tool 对应的 gradle 版本, 比如: tool 4.0.1 对应的 gradle 是 6.1.1

  2. 将 unity 安装目录下的 UNITY_ROOT\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Tools\\gradle 的 lib 删了, 然后从 gradle-6.1.1-all.zip 文件中解压 lib 丢到该目录下


踩坑

unity 默认版本 低于 tools 版本
  • 自定义配置 tools 版本是 4.0.1, 需要对应的 gradle 版本是 6.1.1, 而 unity 默认版本是 5.1.1

    classpath 'com.android.tools.build:gradle:4.0.1'
    
  • 报错

    CommandInvokationFailure: Gradle build failed. 
    D:\\unity2018.4.36f1\\Editor\\Data\\PlaybackEngines\\AndroidPlayer/Tools\\OpenJDK\\Windows\\bin\\java.exe -classpath "D:\\unity2018.4.36f1\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Tools\\gradle\\lib\\gradle-launcher-5.1.1.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
    
    stderr[
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred evaluating root project 'gradleOut'.
    > Failed to apply plugin [id 'com.android.internal.version-check']
       > Minimum supported Gradle version is 6.1.1. Current version is 5.1.1. If using the gradle wrapper, try editing the distributionUrl in E:\\its\\tdmj_itc\\Temp\\gradleOut\\gradle\\wrapper\\gradle-wrapper.properties to gradle-6.1.1-all.zip
    
  • 解决办法

    将 unity 默认的 gradle 升级到 6.1.1


aaptOptions.noCompress 数组超出限制

aaptOptions.noCompress 数组的容量限制是 255

  • 对应的 tools 版本是 4.0.1, 对应的 gradle 版本是 6.1.1

    classpath 'com.android.tools.build:gradle:4.0.1'
    
  • 报错

    CommandInvokationFailure: Gradle build failed. 
    D:/unity_kit/Java/jdk1.8.0_144\\bin\\java.exe -classpath "D:\\unity2018.4.36f1\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Tools\\gradle\\lib\\gradle-launcher-6.1.1.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
    
    stderr[
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':processReleaseResources'.
    > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
       > AAPT2 aapt2-4.0.1-6197926-windows Daemon #0: Unexpected error during link, attempting to stop daemon.
         This should not happen under normal circumstances, please file an issue if it does.
    
  • 原因

    streamingAssets 下项目下文件数量过多引起的, 导致 unity 默认配置中的 **STREAMING_ASSETS** 这个占位符在 gradle 构建时会全部展开为所有文件

    aaptOptions 
        noCompress = ['.unity3d', '.ress', '.resource', '.obb'**STREAMING_ASSETS**]
    **SIGN**
    
    • 构建失败后, 可以查看 UNITY_PROJ\\Temp\\gradleOut\\build.gradle

  • 解决办法

    直接去掉 **STREAMING_ASSETS**, 变为

    aaptOptions 
        noCompress = ['.unity3d', '.ress', '.resource', '.obb']
    **SIGN**
    
  • 参考

    • https://answers.unity.com/questions/1875624/cant-build-on-android-aapt2-unexpected-error-durin.html
    • https://stackoverflow.com/questions/69924552/unity-failed-to-package-after-upgrading-gradle-plug-in-version-to-4-1-0
    • Unity3D使用gradle打Android包遇到的aaptOptions.noCompress越界问题及解决方案 - https://www.jianshu.com/p/402d28da05de

aaptOptions.noCompress 配置技巧

aapt官方文档以及网上查到的一些资料都说aaptOptions.noCompress配置的是不压缩资源文件的后缀名,但是使用后缀名来配置有一定的局限性,比如有些文件后缀名相同,但是如果只想将其中几个文件(而不是全部)配成不压缩,再比如有的文件没有后缀名怎么办?

经过实践发现aaptOptions.noCompress机制并不是检查文件后缀名,而是判断文件路径是否以某个字符串结尾,另外一个需要注意的地方是,在做string.EndWith判断之前会将文件路径全部转换为小写,所以aaptOptions.noCompress中的配置项也必须全为小写


android 12 需要明确指定 android:exported
  • 对应的 tools 版本是 4.2.0, 版本 6.7.1

    classpath 'com.android.tools.build:gradle:4.2.0'
    
  • 报错

    CommandInvokationFailure: Gradle build failed. 
    D:/unity_kit/Java/jdk1.8.0_144\\bin\\java.exe -classpath "D:\\unity2018.4.36f1\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\Tools\\gradle\\lib\\gradle-launcher-6.7.1.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
    
    stderr[
    E:\\its\\tdmj_itc\\Temp\\gradleOut\\src\\main\\AndroidManifest.xml Error:
        Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':processReleaseMainManifest'.
    > Manifest merger failed with multiple errors, see logs
    
  • 解决办法: 所有包含 intent-filterservice/receiver/activity 都加上 android:exported="true"android:exported="false"


unity android 配置修改

  1. 修改自定义 gradle

    1. tools 版本, 使用的自定义 gradle (mainTemplate.gradle) 中使用的 tool (4.0.0)

      buildscript 
          dependencies 
              classpath 'com.android.tools.build:gradle:4.0.0' # 对应的 gradle 版本是 6.1.1
      **BUILD_SCRIPT_DEPS**
      
      
    2. 增加后置任务.

      升级 unity 内置 gradle (4.0.1版本) 生成的 aab 文件名为 gradleOut-release.aab, 而 unity 回去找的文件是 gradleOut.aab, 所以会

      报错: FileNotFoundException: Temp\\gradleOut\\build\\outputs\\bundle\\release\\gradleOut.aab does not exist

      添加个重命名的任务即可

      defaultConfig 
          // rename aab for unity
          tasks.whenTaskAdded  task ->
              if (task.name.startsWith("bundle")) 
                  def renameTaskName = "rename$task.name.capitalize()Aab"
                  def flavor = task.name.substring("bundle".length()).uncapitalize()
                  tasks.create(renameTaskName, Copy) 
                      def path = "$buildDir/outputs/bundle/$flavor/"
                      from(path)
                      include "gradleOut-release.aab"
                      destinationDir file("$buildDir/outputs/bundle/$flavor/")
                      rename "gradleOut-release.aab", "gradleOut.aab"
                  
                  task.finalizedBy(renameTaskName)
              
          
      
      
      • 参考: https://stackoverflow.com/questions/66997991/filenotfoundexception-temp-gradleout-build-outputs-bundle-release-gradleout-aab?rq=1
  2. 修改自定义 AndroidManifest

    所有包含 intent-filterservice/receiver/activity 都加上 android:exported="true"android:exported="false"

    <activity
        android:name="$ps_pkg_path.MainActivity"
        android:label="@string/app_name" android:exported="true">
        <intent-filter>
        ...
        </intent-filter>
    </activity>
    

Android 12 启动异常

异常行为可能是 闪退 或者 卡住

unity 社区大多都是报闪退的错误, 参考: https://forum.unity.com/threads/android-12-crash-on-startup.1230936/

原因可能是因为升级了 gradle 导致的 (不升级没办法, 要使用 Android 12 相关 api)

  1. 解决办法

    1. 简单粗暴升级 unity, 可以升级到 unity 2020.3.31, 这个版本实测过没问题, 过不有在线项目的慎重

    2. 经测试, 会卡住流程的是在 csharp 的协程里面的 yield return 语句, 如:

      public class GameMgr : MonoBehaviour 
          void Awake() 
              Debug.LogFormat("--- ccc 1");
              StartCoroutine(Init());
          
      
          IEnumerator Init() 
              Debug.LogFormat("--- ccc 2");
              yield return StartLuaMain();
          
      
          IEnumerator StartLuaMain() 
              Debug.LogFormat("--- ccc 2-1");
              yield return 1; // 这里卡住, 不往下走了
              Debug.LogFormat("--- ccc 3");
          
      
      

      解决办法是需要 Android 的 电话权限, 而且还不能动态申请, 一定要跳转到 app 信息里面手动把 电话权限 打开. 可以在 app 启动 onCreate 的下一帧提示一下去打开 (onCreate 里面不能做一些 ui 操作, 即使在 ui 线程中)

      @Override
      protected void onCreate(Bundle savedInstanceState) 
          super.onCreate(savedInstanceState);
          ...
          // 跳一帧, 检测 Android 12 电话权限
          new Handler(Looper.getMainLooper()).post(() -> Tools.adr12CallPermCheck());
      
      
      
      
      

以上是关于unity-android和gradle升级的主要内容,如果未能解决你的问题,请参考以下文章

Unity-Android(安卓)支持androidx(兼容andoridx)

Android Studio apk体积突然变大(升级gradle后)

gradle tool升级到3.0注意事项

AndroidStudio升级后出现Refresh gradle project和connection timed out的原因和解决方法

如何升级gradle plugin

将 Android Studio 的 Gradle 插件升级到 3.0.1 和 Gradle 到 4.1 后无法复制配置依赖项