Skip to content

Commit 4917a73

Browse files
committed
Added support for getting the safe rendering area
1 parent 92a2b0b commit 4917a73

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

Assets/Scripts/AndroidSafeArea.cs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using UnityEngine;
2+
3+
public class WindowInsetsListener : AndroidJavaProxy
4+
{
5+
public struct Insets
6+
{
7+
public int left, top, right, bottom;
8+
}
9+
10+
private static Insets m_safeInset = new Insets();
11+
private static Object m_safeInsetLock = new Object();
12+
13+
public static Insets SafeInset
14+
{
15+
get
16+
{
17+
return m_safeInset;
18+
}
19+
}
20+
21+
public void InitInsets(AndroidJavaObject decorView)
22+
{
23+
onApplyWindowInsets(decorView, decorView.Call<AndroidJavaObject>("getRootWindowInsets"));
24+
}
25+
26+
public WindowInsetsListener() : base("android.view.View$OnApplyWindowInsetsListener") { }
27+
28+
private AndroidJavaObject onApplyWindowInsets(AndroidJavaObject view, AndroidJavaObject windowInsets)
29+
{
30+
using (var cutout = windowInsets.Call<AndroidJavaObject>("getDisplayCutout"))
31+
{
32+
if (cutout == null)
33+
{
34+
lock (m_safeInsetLock)
35+
{
36+
m_safeInset.left = 0;
37+
m_safeInset.top = 0;
38+
m_safeInset.right = 0;
39+
m_safeInset.bottom = 0;
40+
}
41+
}
42+
else
43+
{
44+
lock (m_safeInsetLock)
45+
{
46+
m_safeInset.left = cutout.Call<int>("getSafeInsetLeft");
47+
m_safeInset.top = cutout.Call<int>("getSafeInsetTop");
48+
m_safeInset.right = cutout.Call<int>("getSafeInsetRight");
49+
m_safeInset.bottom = cutout.Call<int>("getSafeInsetBottom");
50+
}
51+
}
52+
}
53+
54+
return view.Call<AndroidJavaObject>("onApplyWindowInsets", windowInsets);
55+
}
56+
}
57+
58+
public class AndroidSafeArea : MonoBehaviour
59+
{
60+
private static bool m_insetsListenerInstalled = false;
61+
62+
void Start()
63+
{
64+
if (m_insetsListenerInstalled)
65+
return;
66+
67+
using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
68+
{
69+
// Supported on Android 9 Pie (API 28) and later
70+
if (version.GetStatic<int>("SDK_INT") >= 28)
71+
{
72+
// Install the listener
73+
using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
74+
{
75+
using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
76+
{
77+
using (var window = activity.Call<AndroidJavaObject>("getWindow"))
78+
{
79+
using (var decorView = window.Call<AndroidJavaObject>("getDecorView"))
80+
{
81+
var windowInsetsListener = new WindowInsetsListener();
82+
windowInsetsListener.InitInsets(decorView);
83+
decorView.Call("setOnApplyWindowInsetsListener", windowInsetsListener);
84+
m_insetsListenerInstalled = true;
85+
}
86+
}
87+
}
88+
}
89+
}
90+
}
91+
}
92+
93+
public static Rect safeArea
94+
{
95+
get
96+
{
97+
if (!m_insetsListenerInstalled)
98+
return Screen.safeArea;
99+
100+
// Scale in case resolution doesn't match the native one
101+
float xScale = (float)Screen.width / Display.main.systemWidth;
102+
float yScale = (float)Screen.height / Display.main.systemHeight;
103+
104+
Rect safeArea = new Rect
105+
{
106+
x = Mathf.Round(WindowInsetsListener.SafeInset.left * xScale),
107+
width = Mathf.Round(Screen.width - (WindowInsetsListener.SafeInset.left + WindowInsetsListener.SafeInset.right) * xScale),
108+
y = Mathf.Round(WindowInsetsListener.SafeInset.bottom * yScale),
109+
height = Mathf.Round(Screen.height - (WindowInsetsListener.SafeInset.bottom + WindowInsetsListener.SafeInset.top) * yScale)
110+
};
111+
112+
return safeArea;
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)