Is there any update about this issue?
I think I’m having the same issue? (I shortened the width of the image)
It affects the Camera aspect ratio because the bar lessens the pixel height; I have a Lenovo Tab P11 Plus (using Android 12) with pixel dimensions of 2000x1200 leading to an aspect ratio of 1.666…, and with the bar at the top the dimensions become 2000x1164 for an aspect ratio of 1.718…
I’ll make do for now, but it is annoying as I’m doing some UI placement based on max aspect ratio, so for the Lenovo Tab P11 Plus main menu UI arrangement, I have to set my max aspect ratio (for comparison) to 1.72 (slightly greater than 1.718) instead of 1.7 (slightly greater than 1.666).
using UnityEngine;
public sealed class AndroidImmersiveBars : MonoBehaviour
{
[SerializeField] private bool hideStatusBar = true;
[SerializeField] private bool hideNavigationBar = true;
// Run early and survive scene loads.
private void Awake()
{
DontDestroyOnLoad(gameObject);
Apply();
}
private void OnApplicationFocus(bool hasFocus)
{
if (hasFocus) Apply(); // Re-apply when returning from background.
}
private void Apply()
{
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
using var unityPlayer = new AndroidJavaClass(“com.unity3d.player.UnityPlayer”);
using var activity = unityPlayer.GetStatic(“currentActivity”);
if (activity == null) return;
activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
using var window = activity.Call<AndroidJavaObject>("getWindow");
using var decorView = window.Call<AndroidJavaObject>("getDecorView");
// SDK_INT
using var version = new AndroidJavaClass("android.os.Build$VERSION");
int sdkInt = version.GetStatic<int>("SDK_INT");
if (sdkInt >= 30)
{
// WindowInsetsController path (Android 11+)
using var controller = decorView.Call<AndroidJavaObject>("getWindowInsetsController");
if (controller == null) return;
using var typeClass = new AndroidJavaClass("android.view.WindowInsets$Type");
int types = 0;
if (hideStatusBar) types |= typeClass.CallStatic<int>("statusBars");
if (hideNavigationBar) types |= typeClass.CallStatic<int>("navigationBars");
using var controllerClass = new AndroidJavaClass("android.view.WindowInsetsController");
int behavior = controllerClass.GetStatic<int>("BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE");
controller.Call("setSystemBarsBehavior", behavior);
controller.Call("hide", types);
}
else
{
// Legacy immersive flags (pre-Android 11)
using var viewClass = new AndroidJavaClass("android.view.View");
int flags =
viewClass.GetStatic<int>("SYSTEM_UI_FLAG_LAYOUT_STABLE") |
viewClass.GetStatic<int>("SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN") |
viewClass.GetStatic<int>("SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION") |
viewClass.GetStatic<int>("SYSTEM_UI_FLAG_IMMERSIVE_STICKY");
if (hideStatusBar) flags |= viewClass.GetStatic<int>("SYSTEM_UI_FLAG_FULLSCREEN");
if (hideNavigationBar) flags |= viewClass.GetStatic<int>("SYSTEM_UI_FLAG_HIDE_NAVIGATION");
decorView.Call("setSystemUiVisibility", flags);
}
}));
}
catch
{
// Swallow exceptions: if OEM/ROM blocks it, don't crash the game.
}
#endif
}
}
Put This in Bootsrap Scene, Solved The Issue On 6.3
Thank you for this. Fixed the issue that appeared when upgrading from 6.000.34 to 6.000.3.11.
Only thing I had to change was to set the type when getting the activity (in between the two code snippets):
using var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
I updated to Unity version 6000.4.0f1 and I’m having the same problem. Has anyone solved it in that version?
Where did you add this?
using var activity = unityPlayer.GetStatic(“currentActivity”);
Easier to just put the whole code snippet here.
Reminder, code is not mine but aouni9999’s.
Put this in an empty gameobject in the first scene that loads your game (and ideally is only visited once)
public sealed class AndroidImmersiveBarsFix : MonoBehaviour
{
[SerializeField] private bool hideStatusBar = true;
[SerializeField] private bool hideNavigationBar = true;
// Run early and survive scene loads.
private void Awake()
{
DontDestroyOnLoad(gameObject);
Apply();
}
private void OnApplicationFocus(bool hasFocus)
{
if (hasFocus) Apply(); // Re-apply when returning from background.
}
private void Apply()
{
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
using var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
using var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
if (activity == null) return;
activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
using var window = activity.Call<AndroidJavaObject>("getWindow");
using var decorView = window.Call<AndroidJavaObject>("getDecorView");
// SDK_INT
using var version = new AndroidJavaClass("android.os.Build$VERSION");
int sdkInt = version.GetStatic<int>("SDK_INT");
if (sdkInt >= 30)
{
// WindowInsetsController path (Android 11+)
using var controller = decorView.Call<AndroidJavaObject>("getWindowInsetsController");
if (controller == null) return;
using var typeClass = new AndroidJavaClass("android.view.WindowInsets$Type");
int types = 0;
if (hideStatusBar) types |= typeClass.CallStatic<int>("statusBars");
if (hideNavigationBar) types |= typeClass.CallStatic<int>("navigationBars");
using var controllerClass = new AndroidJavaClass("android.view.WindowInsetsController");
int behavior = controllerClass.GetStatic<int>("BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE");
controller.Call("setSystemBarsBehavior", behavior);
controller.Call("hide", types);
}
else
{
// Legacy immersive flags (pre-Android 11)
using var viewClass = new AndroidJavaClass("android.view.View");
int flags =
viewClass.GetStatic<int>("SYSTEM_UI_FLAG_LAYOUT_STABLE") |
viewClass.GetStatic<int>("SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN") |
viewClass.GetStatic<int>("SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION") |
viewClass.GetStatic<int>("SYSTEM_UI_FLAG_IMMERSIVE_STICKY");
if (hideStatusBar) flags |= viewClass.GetStatic<int>("SYSTEM_UI_FLAG_FULLSCREEN");
if (hideNavigationBar) flags |= viewClass.GetStatic<int>("SYSTEM_UI_FLAG_HIDE_NAVIGATION");
decorView.Call("setSystemUiVisibility", flags);
}
}));
}
catch
{
// Swallow exceptions: if OEM/ROM blocks it, don't crash the game.
}
#endif
}
}
