I found a way to fix this.
As you may know, Android 15 enforces edge-to-edge by default. This should only affect apps targeting Android 15. However, for some reason, it also affects apps that are not targeting Android 15 but are running on Android 15 when built with Unity. It seems to be related to windowLayoutInDisplayCutoutMode not being properly set or interpreted, I’m not entirely sure.
So, when targetSdkVersion < 15 (I’m targeting 14 in my case, but this should work for others as well), add a GameObject to your first loaded scene and attach the following code:
using UnityEngine;
[DefaultExecutionOrder(-1000)]
public class CutoutFix : MonoBehaviour
{
void Awake()
{
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
{
int sdkInt = version.GetStatic<int>("SDK_INT");
if (sdkInt >= 35)
{
activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
using (var window = activity.Call<AndroidJavaObject>("getWindow"))
{
using (var layoutParams = window.Call<AndroidJavaObject>("getAttributes"))
{
int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2;
layoutParams.Set("layoutInDisplayCutoutMode", LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER);
window.Call("setAttributes", layoutParams);
}
}
}));
}
}
}
}
catch (System.Exception e)
{
Debug.LogWarning("AndroidCutoutFix failed: " + e);
}
#endif
}
}
And that’s it. This sets layoutInDisplayCutoutMode to LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER. In my case, I needed LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER, but you can adapt the code to suit your needs.
Now, if you’re targeting Android 15, there’s one more thing you need to handle. Android 15 gives you a final opportunity to opt out of their edge-to-edge enforcement. After that, once you target Android 16, none of these workarounds will function anymore, and you’ll need to properly adapt your game to support edge-to-edge layouts.
To opt out of edge-to-edge, there appear to be several ways to do it. I tried many of them and will share the method that worked for me. Maybe I overcomplicated things a bit, but you’ll get the idea.
First, check which theme your game is using. I originally started my project in Unity 5 (2015), so things might be different now. Look for android:theme in your AndroidManifest.xml. In my case, it was:
android:theme="@style/UnityThemeSelector"
I decompiled my APK using apktool to inspect the styles.xml files inside the res/values folders. The highest versioned folder I found was values-v28, which means that this file is used for SDK >= 28 since no folder with a higher version exists. I copied this folder to create a new one called values-v35.
Inside styles.xml, I located the BaseUnityTheme (which is the parent of UnityThemeSelector) and added the following line:
<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
I then created an .aar module in Android Studio, containing only the values-v35 folder, and added it to my project under Assets\Plugins\Android.
Additional information for windowOptOutEdgeToEdgeEnforcement :
https://stackoverflow.com/questions/78832459/how-to-preserve-the-space-of-the-status-bar-android-15