super1 发表于 2022-12-5 13:49

Unity Googleplay Android版升级到31,Unity闪屏之后卡死

当前海外版本有硬性要求:Target API level必须升级到31,升级之后在Android 12机型上启动游戏,Unity闪屏之后卡死,其他Android版本正常。

查了一下这个问题,是因为TelephonyManager的listen函数在Android 12过期了,如果没有授权READ_PHONE_STATE权限,此函数会抛出一个SecurityException。
而Unity在启用了自带的音频系统的情况下,恰巧在启动时机会去调用这个方法以实现“在用户接电话时游戏静音”的功能,抛出的异常影响了后续的流程导致卡死。

论坛上有人遇到了类似的问题,但是表现为崩溃:
https://forum.unity.com/threads/android-12-telephony-crash.1287986/
项目能升级引擎的话,可以试试这里提到的修复的版本:
https://issuetracker.unity3d.com/issues/android-player-crashing-in-fmod-when-targetting-sdk-level-31

如果项目不能升级引擎,也有一个解决办法:
重新写一个android的启动类, 将这个问题绕过去
package com.xx.xxximport android.content.Context;import android.os.Build;import com.unity3d.player.UnityPlayer;public class UnityPlayerNewextends UnityPlayer{    public UnityPlayerNew(Context context)   {      super(context);    }    @Override    protected void addPhoneCallListener()    {      if (Build.VERSION.SDK_INT >= 31)      {            return;      }      super.addPhoneCallListener();    }}package com.xx.xxx;import com.unity3d.player.*;import android.app.Activity;import android.content.Intent;import android.content.res.Configuration;import android.graphics.PixelFormat;import android.os.Bundle;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.View;import android.view.Window;import android.view.WindowManager;public class UnityPlayerActivity extends Activity{    protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code    protected String updateUnityCommandLineArguments(String cmdLine)    {      return cmdLine;    }    // Setup activity layout    @Override protected void onCreate(Bundle savedInstanceState)    {      requestWindowFeature(Window.FEATURE_NO_TITLE);      super.onCreate(savedInstanceState);      String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));      getIntent().putExtra("unity", cmdLine);      mUnityPlayer = new UnityPlayerNew(this);      setContentView(mUnityPlayer);      mUnityPlayer.requestFocus();    }    @Override protected void onNewIntent(Intent intent)    {      // To support deep linking, we need to make sure that the client can get access to      // the last sent intent. The clients access this through a JNI api that allows them      // to get the intent set on launch. To update that after launch we have to manually      // replace the intent with the one caught here.      setIntent(intent);    }    // Quit Unity    @Override protected void onDestroy ()    {      mUnityPlayer.destroy();      super.onDestroy();    }    // Pause Unity    @Override protected void onPause()    {      super.onPause();      mUnityPlayer.pause();    }    // Resume Unity    @Override protected void onResume()    {      super.onResume();      mUnityPlayer.resume();    }    @Override protected void onStart()    {      super.onStart();      mUnityPlayer.start();    }    @Override protected void onStop()    {      super.onStop();      mUnityPlayer.stop();    }    // Low Memory Unity    @Override public void onLowMemory()    {      super.onLowMemory();      mUnityPlayer.lowMemory();    }    // Trim Memory Unity    @Override public void onTrimMemory(int level)    {      super.onTrimMemory(level);      if (level == TRIM_MEMORY_RUNNING_CRITICAL)      {            mUnityPlayer.lowMemory();      }    }    // This ensures the layout will be correct.    @Override public void onConfigurationChanged(Configuration newConfig)    {      super.onConfigurationChanged(newConfig);      mUnityPlayer.configurationChanged(newConfig);    }    // Notify Unity of the focus change.    @Override public void onWindowFocusChanged(boolean hasFocus)    {      super.onWindowFocusChanged(hasFocus);      mUnityPlayer.windowFocusChanged(hasFocus);    }    // For some reason the multiple keyevent type is not supported by the ndk.// Force event injection by overriding dispatchKeyEvent().@Override public boolean dispatchKeyEvent(KeyEvent event){if (event.getAction() == KeyEvent.ACTION_MULTIPLE)return mUnityPlayer.injectEvent(event);return super.dispatchKeyEvent(event);}// Pass any events not handled by (unfocused) views straight to UnityPlayer@Override public boolean onKeyUp(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }@Override public boolean onKeyDown(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }@Override public boolean onTouchEvent(MotionEvent event)          { return mUnityPlayer.injectEvent(event); }/*API12*/ public boolean onGenericMotionEvent(MotionEvent event){ return mUnityPlayer.injectEvent(event); }}<activity android:name="com.xx.xxx.UnityPlayerActivity" android:screenOrientation="landscape" android:exported="true" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"><intent-filter>    <action android:name="android.intent.action.MAIN" />    <category android:name="android.intent.category.LAUNCHER" />    <category android:name="android.intent.category.LEANBACK_LAUNCHER" /></intent-filter></activity>
页: [1]
查看完整版本: Unity Googleplay Android版升级到31,Unity闪屏之后卡死