Unity老项目Android 13支持

Unity老项目Android 13支持


前言

Google官方要求新、老app在一定时间要求内需要面向Android 12、Android 13构建,不然不给app过审。我们之前是面向Android API 30构建的,现在需要支持面向Android API 33构建。

Unity老项目Android 13支持_第1张图片

https://developer.android.com/about/versions

https://support.google.com/googleplay/android-developer/answer/11926878

在支持Android 13的时候遇到了很多问题,在此做下记录,提供参考。

unity-android和gradle升级_蝶泳奈何桥.的博客-CSDN博客_unity升级gradle

修改总览

我们项目是基于Unity 2018.4.36f1开发的,以下修改和问题都基于该Unity版本,高版本Unity遇到的问题可能会有些许不一样。

打包机要修改的内容

  1. 下载Android SDK Build-Tools 33.0.0、Android SDK Platform-Tools 33.0.3、Android API 33。

Unity老项目Android 13支持_第2张图片
Unity老项目Android 13支持_第3张图片
Unity老项目Android 13支持_第4张图片

  1. 修改Unity打包时的Gradle Version为6.1.1,Gradle Plugin Version为4.0.1。

Gradle下载地址:https://gradle.org/releases/

下载完后在Unity的Preferences/External Tools中设置Unity打包时所用的Gradle Version。

Unity老项目Android 13支持_第5张图片

  1. 修改安卓SDK目录下的BuildTools-33.0.0部分文件名称。(详见问题三)

将 %ANDROID_SDK%\build-tools\33.0.0 目录下的 d8.bat 改成 dx.bat

将 %ANDROID_SDK%\build-tools\33.0.0\lib 目录下的 d8.jar 改成 dx.jar

Unity老项目Android 13支持_第6张图片
Unity老项目Android 13支持_第7张图片

项目工程要修改的内容

  1. 修改Unity工程中的mainTemplate.gradle,将Gradle Plugin Version改为4.0.1。

Unity老项目Android 13支持_第8张图片

  1. 设置对应Android工程的Gradle Version为6.1.1,Gradle Plugin Version为4.0.1。

修改Android工程中对应的compileSdkVersion和targetSdkVersion到33。

生成对应的jar或aar包(根据自己项目来定)

Unity老项目Android 13支持_第9张图片

  1. 去掉项目中跟multidex相关的代码。(详见问题二)

Unity老项目Android 13支持_第10张图片
Unity老项目Android 13支持_第11张图片
Unity老项目Android 13支持_第12张图片

  1. 在Unity工程中的mainTemplate.gradle下添加checkReleaseBuilds false。(详见问题四)

Unity老项目Android 13支持_第13张图片

如果需要构建aab,则需要在mainTemplate.gradle后添加task来处理生成的aab。(详见问题十一)

Unity老项目Android 13支持_第14张图片

  1. AndroidManifest中,所有包含 intent-filter 的 service、receiver、activity 都加上android:exported="true"或android:exported=“false”。(详见问题五)

  2. 修改项目中所有PendingIntent.getActivity和PendingIntent.getBroadcast方法。(详见问题六、问题八、问题九)

添加PendingIntent.FLAG_IMMUTABLE或PendingIntent.FLAG_MUTABLE。

PendingIntent pendingIntent = null;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)    pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);else    pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
  1. 在启动游戏时,请求一个AndroidManifest没有的权限。(详见问题七)

解决Unity在Android13只调用Awake不调用Start的问题。

Unity老项目Android 13支持_第15张图片

  1. 处理导致游戏崩溃报错的SDK。

如遇打包失败、游戏闪退崩溃、游戏报错等问题,请参考下面的记录。

具体问题

问题一 Gradle build failed unrecognized Attribute name MODULE

问题描述

Unity构建Android API 33时报错:

Exception:CommandInvokationFailure: Gradle build failed. @/Applications/Unity2018.4.36_inter/PlaybackEngines/AndroidPlayer/Tools/OpenJDK/MacOS/bin/java -classpath “/Applications/Unity2018.4.36_inter/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 N a m e I m p l ) @ a t c o m . s u n . t o o l s . j a v a c . u t i l . A s s e r t . e r r o r ( A s s e r t . j a v a : 133 ) @ a t c o m . s u n . t o o l s . j a v a c . c o d e . T y p e A n n o t a t i o n s . a n n o t a t i o n T y p e ( T y p e A n n o t a t i o n s . j a v a : 231 ) @ a t c o m . s u n . t o o l s . j a v a c . c o d e . T y p e A n n o t a t i o n s 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 NameImpl)@atcom.sun.tools.javac.util.Assert.error(Assert.java:133)@atcom.sun.tools.javac.code.TypeAnnotations.annotationType(TypeAnnotations.java:231)@atcom.sun.tools.javac.code.TypeAnnotationsTypeAnnotationPositions.separateAnnotationsKinds(TypeAnnotations.java:294)@…

解决方案

使用JDK11版本来构建可以解决该问题。但是我们目前使用的是Unity 2018.4.36f1,不支持使用JDK11版本构建。

记录下问题解决:annotationType(): unrecognized Attribute name MODULE (class com.sun.tools.javac.util.SharedN

Unity老项目Android 13支持_第16张图片

Unity官网说了,只有2020版本的unity才准备去支持JDK11,老版本一律不支持。

经过查询,发现需要修改Unity构建时的Gradle版本。

unrecognized Attribute name MODULE (class com.sun.tools.javac.util.SharedNameTable$NameImpl)

Unity老项目Android 13支持_第17张图片

Question - Must target API level 31

Resolved - Target API 31 Issues and Solutions

Unity老项目Android 13支持_第18张图片

https://developers.google.com/ar/develop/unity-arf/android-12-build

最终解决方案为:

修改Unity打包时的Gradle Version为6.1.1,Gradle Plugin Version为4.0.1。

Gradle下载地址:https://gradle.org/releases/

下载完后在Unity的Preferences/External Tools中设置Unity打包时所用的Gradle Version。

之后修改Unity工程中的mainTemplate.gradle,将Gradle Plugin Version改为4.0.1。

Unity老项目Android 13支持_第19张图片
Unity老项目Android 13支持_第20张图片

问题二 Build failed with an exception.dexBuilderDebug

问题描述

打包时报错:

FAILURE: Build failed with an exception.

  • Where:

Build file ‘C:\Project\PiggyGO\Temp\gradleOut\build.gradle’ line: 242

  • What went wrong:

A problem occurred configuring root project ‘gradleOut’.

Could not get unknown property ‘additionalParameters’ for task ‘:dexBuilderDebug’ of type com.android.build.gradle.internal.tasks.DexArchiveBuilderTask.

  • Try:

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

  • Get more help at https://help.gradle.org
解决方案

查到是multidex的问题。

Android Studio最全面编译构建优化!!!_Nbin_Newby的博客-程序员宝宝_android studio 多核编译 - 程序员宝宝

Unity老项目Android 13支持_第21张图片

最终解决方案为:

去掉第三方的multidex及其关联代码。

Unity老项目Android 13支持_第22张图片
Unity老项目Android 13支持_第23张图片

问题三 Build failed with an exception.:Installed Build Tools revision 33.0.0 is corrupted

问题描述

打包时报错:

FAILURE: Build failed with an exception.

  • What went wrong:

Could not determine the dependencies of task ‘:compileReleaseJavaWithJavac’.

Installed Build Tools revision 33.0.0 is corrupted. Remove and install again using the SDK Manager.

解决方案

修改安卓SDK目录下的BuildTools-33.0.0部分文件名称。

unity-android和gradle升级_蝶泳奈何桥.的博客-CSDN博客

Android Studio error “Installed Build Tools revision 31.0.0 is corrupted”

将 %ANDROID_SDK%\build-tools\33.0.0 目录下的 d8.bat 改成 dx.bat

将 %ANDROID_SDK%\build-tools\33.0.0\lib 目录下的 d8.jar 改成 dx.jar

Unity老项目Android 13支持_第24张图片
Unity老项目Android 13支持_第25张图片

问题四 Build failed :Execution failed for task ‘:lintVitalRelease’.

问题描述

打包时报错:

FAILURE: Build failed with an exception.

  • What went wrong:

Execution failed for task ‘:lintVitalRelease’.

Lint infrastructure error

Caused by: java.lang.reflect.InvocationTargetException

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at com.android.tools.lint.gradle.api.ReflectiveLintRunner.runLint(ReflectiveLintRunner.kt:38)

at com.android.build.gradle.tasks.LintBaseTask.runLint(LintBaseTask.java:114)

at

解决方案

在mainTemplate.gradle中添加 checkReleaseBuilds false。

Error: Execution failed for task ‘:app: lintVitalRelease’ any one can solve it?

Unity老项目Android 13支持_第26张图片

问题五 Targeting S+ (version 31 and above) requires

问题描述

安装时报错:

adb: failed to install C:\Project\PiggyGO\Build\PiggyTravel_Android_4.4.0.1.apk: Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/vmdl661069248.tmp/base.apk (at Binary XML file line #112): com.aladinfun.piggytravel.android.MainActivity: Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are present]

解决方案

Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined

https://developer.android.com/about/versions/12/behavior-changes-12#exported

Android 12 已来,你的 App 崩溃了吗? - 掘金

项目AndroidManifest中,所有包含 intent-filter 的 service、receiver、activity 都加上 android:exported=“true” 或 android:exported=“false”

上面加了自定义的是ok了,但是还有一个Unity隐藏的:

com.unity.androidnotifications.UnityNotificationRestartOnBootReceiver: Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are present

Mobile notifications are breaking android 12 builds

如果在装包时,出现上述报错,那么还需要在AndroidManifest中增加下述代码:

                                        

问题六 调用PendingIntent时报错

问题描述

进入后崩溃:

--------- beginning of crash

2022-10-11 11:59:03.874 17946-18035/com.aladinfun.piggytravel.android E/AndroidRuntime: FATAL EXCEPTION: pool-26-thread-1

Process: com.aladinfun.piggytravel.android, PID: 17946

java.lang.IllegalArgumentException: com.aladinfun.piggytravel.android: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

at android.app.PendingIntent.checkFlags(PendingIntent.java:401)

at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:671)

at android.app.PendingIntent.getBroadcast(PendingIntent.java:658)

at androidx.work.impl.utils.ForceStopRunnable.getPendingIntent(ForceStopRunnable.java:174)

at androidx.work.impl.utils.ForceStopRunnable.isForceStopped(ForceStopRunnable.java:108)

at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:86)

at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:75)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)

at java.lang.Thread.run(Thread.java:1012)

解决方案

在Android12后,调用PendingIntent时,需要显式地声明mutable或immutable。如果不显式地声明,就会抛出异常。

详见下面官方文档:

https://developer.android.com/about/versions/12/behavior-changes-12#pending-intent-mutability

修改方法就是在用到PendingIntent的地方加上FLAG_IMMUTABLE或者FLAG_MUTABLE。但是有一些SDK和框架的代码我们没法主动修改,这就需要查阅相关的更新文档了。

Bug - Android 12 App crashes on startup due to error with PendingIntent (Google Mobile Ads plugin us

How to resolve “Missing PendingIntent mutability flag” lint warning in android api 30+?

https://developer.android.com/jetpack/androidx/releases/work#groovy

通过别人的贴子发现,如果是库引起的问题,会报错在具体一行中,而我们的报错是androidx.work框架报出来的,那么这说明是安卓原生库有问题。

Unity老项目Android 13支持_第27张图片

查阅相关文档后,发现谷歌官方框架修复了这个问题:

https://android.googlesource.com/platform/frameworks/support/+/8656febfe4ffbd1de91299f9ae9b9c6147e723d6

Unity老项目Android 13支持_第28张图片

最终在依赖中添加下面两个库即可:

    // For apps targeting Android 12, add WorkManager dependency.    implementation "androidx.work:work-runtime:2.7.1"    implementation "androidx.work:work-runtime-ktx:2.7.1"

Unity老项目Android 13支持_第29张图片

问题七 游戏启动黑屏

问题描述

游戏启动后,卡在启动界面,C#脚本只调用Awake不调用Start。

Unity老项目Android 13支持_第30张图片

解决方案

在启动游戏时,请求一个AndroidManifest没有声明的权限即可。

Question - Android: targeting API level 31 makes the game freeze on Android 12

Unity老项目Android 13支持_第31张图片

上面的代码加上后,发现在绝大多数机型下可以正常运行,但在部分Android12及以上的三星设备上仍然黑屏。

问题八 FLAG_IMMUTABLE或者FLAG_MUTABLE

问题描述

同问题六,项目里用的本地推送插件没有兼容android12,在使用PendingIntent的时候没有添加FLAG_IMMUTABLE或者FLAG_MUTABLE,从而导致调用方法时报错。

java.lang.IllegalArgumentException: com.aladinfun.piggytravel.android: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

解决方案

查到这个作者插件原GitHub,阅读源码发现net.agasper.unitynotification.UnityNotificationManager里面的SetNotification没有兼容Android12。

https://github.com/Agasper/unity-android-notifications/blob/master/PluginSrc/app/src/main/java/net/agasper/unitynotification/UnityNotificationManager.java

Unity老项目Android 13支持_第32张图片

源码在此,作者没有做更新,没有兼容Android12。

Free Android local notifications plugin open source。这是这个作者宣传自己插件的帖子。

Unity老项目Android 13支持_第33张图片

最终down下了作者的源码,修改对应方法后重新生成jar包,扔到项目中,修改方法大致如下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)    am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayMs, rep, PendingIntent.getBroadcast(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));else    am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayMs, rep, PendingIntent.getBroadcast(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT));

问题九 Facebook SDK报错Targeting S+ (version 31 and above)

问题描述

同问题六,Facebook SDK报错:

Caused by: java.lang.IllegalArgumentException: com.aladinfun.piggytravel.android: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

at android.app.PendingIntent.checkFlags(PendingIntent.java:401)

at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:671)

at android.app.PendingIntent.getBroadcast(PendingIntent.java:658)

at com.facebook.AccessTokenManager.setTokenExpirationBroadcastAlarm(AccessTokenManager.kt:121)

at com.facebook.AccessTokenManager.setCurrentAccessToken(AccessTokenManager.kt:94)

at com.facebook.AccessTokenManager.setCurrentAccessToken(AccessTokenManager.kt:47)

at com.facebook.AccessToken$Companion.setCurrentAccessToken(AccessToken.kt:428)

at com.facebook.AccessToken.setCurrentAccessToken(Unknown Source:2)

at com.facebook.login.LoginManager.finishLogin(LoginManager.java:894)

at com.facebook.login.LoginManager.onActivityResult(LoginManager.java:247)

at com.facebook.login.LoginManager$1.onActivityResult(LoginManager.java:186)

at com.facebook.internal.CallbackManagerImpl.onActivityResult(CallbackManagerImpl.kt:44)

at com.facebook.unity.BaseActivity.onActivityResult(BaseActivity.java:51)

at android.app.Activity.dispatchActivityResult(Activity.java:8613)

at android.app.ActivityThread.deliverResults(ActivityThread.java:5340)

解决方案

官方说在Facebook SDK版本11.3.0解决了该问题。

Android facebook-login library 11.2.0 crashes Android 12 - Targeting S+ (version 31 and above) requi

https://github.com/facebook/facebook-android-sdk/issues/997#issuecomment-914691737

升级Facebook Unity SDK,并修改Dependences.xml,将对应Faceboook SDK升到12.2.0版本。

Unity老项目Android 13支持_第34张图片

问题十 Facebook分享成功但是分享回调中传来unknown error。

问题描述

Facebook分享成功但是分享回调中传来unknown error。

解决方案

官方回应Facebook Share SDK 12.3.0有问题,已在13.0.0版本修复,但是我们的Unity版本不支持更高级别的Facebook SDK版本了,所以只能降回12.2.0。

Share action is success but return UnknownError in facebook sdk 12.0.0+ · Issue #1043 · facebook/fac

需要将Facebook Share Sdk降级为12.2.0。

Unity老项目Android 13支持_第35张图片

问题十一 gradleOut.aab does not exist

问题描述

打aab包时报错:

FileNotFoundException: Temp/gradleOut/build/outputs/bundle/release/gradleOut.aab does not exist

解决方案

高版本gradle构建aab时,会生成gradleOut-release.aab,但Unity找的是gradleOut.aab,名字对不上了,打包自然就失败了。

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

注意:如果按照上面帖子的方法会产生下面的报错,找不到capitalize方法。需要做一些修改。详见下面的最终修改内容。

FAILURE: Build failed with an exception.

  • Where:
    Build file ‘/Volumes/build_workspace/piggygo_client/client_android/build_repo/Temp/gradleOut/build.gradle’ line: 200

  • What went wrong:
    A problem occurred configuring root project ‘gradleOut’.

    Failed to notify project evaluation listener.
    Could not create task ‘:bundleDebug’.
    No such property: capitalize for class: java.lang.String
    Android variants not detected.
    Please make sure you place the directive:
    apply plugin: ‘applovin’
    after you apply the Android plugin in your build.gradle file

在mainTemplate.gradle最后添加重命名task即可:

tasks.whenTaskAdded { task ->    if (task.name == "bundleRelease") {        def renameTaskName = "renameBundleReleaseAab"        def flavor = "release"        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)    }}

Unity老项目Android 13支持_第36张图片

问题十二 手机上运行没有声音

问题描述

在部分Android 12及以上的手机上运行没有声音,三星居多。

Unity老项目Android 13支持_第37张图片

解决方案

最新解决办法,反编译classes.jar,修改UnityPlayer类的addPhoneCallListener实现,判断if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) return;再编回classes.jar,注意打包机是Mac需要修改Mac安装目录下的Class

Android平台 Target API level 升级到 31,在Android 12上启动黑屏卡死 – UWA问答

Android平台 Target API level 升级到 31,在Android 12上启动黑屏卡死

你可能感兴趣的:(Unity3D技术分享,unity,android)