4
\$\begingroup\$

I am making an Android/iOS mobile app in Unity. Currently, when I build it and install it (for example from APK to Android) it loads completely full screen covering up the top phone status bar which usually shows the time, network signal, wifi icons, etc.

For Android, I see an option in Project Settings > Player for "Hide Navigation Bar" - unchecking this I believe lets you see the bottom on-screen navigation buttons like home, back, etc. However, I see no option to show/hide the top status bar.

In iOS, I am told there is an option for "Status Bar Hidden" which I haven't tested yet but should hopefully do in iOS.

Is there some way to do this in Android?

For example, is there some way to "sense" from inside Unity how many pixels the height of the Android status bar is and then restrict the window to not cover it?

I see it possible to get the height of the status bar here but this is not Unity specific code and I'm not sure how to use it or limit the Unity window size according to this StackOverflow question.

I also just found this sample GitHub repo which looks like it was designed for this, but I don't understand what they mean about how to build it. I usually just build with the "Build" button from the Unity editor.

Thanks.

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

I wrote this for a project a few years ago. It should work fine, but I no longer maintain it. It shows the status bar in the color of your choice.

Usage:

#if UNITY_ANDROID && !UNITY_EDITOR
    Screen.fullScreen = false; //Should be unnecessary unless you changed it
    AndroidUtility.ShowStatusBar(Color.black);
#endif

Code:

#if UNITY_ANDROID && !UNITY_EDITOR
using System;
using UnityEngine;

namespace Evorlor.Common
{
    public static class AndroidUtility
    {
        private const int MinStatusBarColorApi = 21;
        private const int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;

        private static AndroidJavaObject activity;

        /// <summary>
        /// Shows the Android Status bar
        /// </summary>
        /// <param name="color">Color of status bar to be used</param>
        public static void ShowStatusBar(Color color)
        {
            int androidColor = ConvertColorToAndroidColor(color);
            RunOnUiThread(() =>
                {
                    using (var window = Window)
                    {
                        window.Call("clearFlags", SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
                        if (GetApi() >= MinStatusBarColorApi)
                        {
                            window.Call("setStatusBarColor", androidColor);
                        }
                        else
                        {
                            Debug.LogWarning("Changing the status bar color is not supported on Android API lower than Lollipop.");
                        }
                    }
                });
        }

        private static void RunOnUiThread(Action action)
        {
            Activity.Call("runOnUiThread", new AndroidJavaRunnable(action));
        }

        private static AndroidJavaObject Activity
        {
            get
            {
                if (activity == null)
                {
                    var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
                    activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
                }
                return activity;
            }
        }

        private static AndroidJavaObject Window
        {
            get
            {
                return Activity.Call<AndroidJavaObject>("getWindow");
            }
        }

        private static int GetApi()
        {
            using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
            {
                return version.GetStatic<int>("SDK_INT");
            }
        }

        private static int ConvertColorToAndroidColor(Color color)
        {
            Color32 color32 = color;
            int alpha = color32.a;
            int red = color32.r;
            int green = color32.g;
            int blue = color32.b;
            using (var colorClass = new AndroidJavaClass("android.graphics.Color"))
            {
                int androidColor = colorClass.CallStatic<int>("argb", alpha, red, green, blue);
                return androidColor;
            }
        }
    }
}
#endif
\$\endgroup\$
3
  • 2
    \$\begingroup\$ Thanks for your method Evorlor. It definitely works to show the status bar. However, it is also showing the navigation bar (bottom bar) which I don't want. I also tried the other method posted in the other reply which gives individual control over the two separately. But even with that script the same thing happens. Using that one, if I set ApplicationChrome.statusBarState = ApplicationChrome.States.Visible; ApplicationChrome.navigationBarState = ApplicationChrome.States.Hidden; it still shows both the status and nav bar. This is in Android Studio Emulator. Any ideas? Thanks. \$\endgroup\$
    – mike
    Dec 1, 2021 at 6:31
  • 1
    \$\begingroup\$ I tried by installing an APK to my Galaxy using your script (just to see if it would do the same) and it does - showing the status bar automatically forces the navigation bar just like in the Emulator and I can't separate the two ... I need the status but but NO navigation bar. Do you know of any solution? I appreciate any help. \$\endgroup\$
    – mike
    Dec 1, 2021 at 6:55
  • \$\begingroup\$ @mike Not off the top of my head. Do you have "Hide Navigation Bar" checked in the Android Player Settings? \$\endgroup\$
    – Evorlor
    Dec 6, 2021 at 23:51
2
\$\begingroup\$

You are supposed to integrate Over17's UnityShowAndroidStatusBar code after exporting a Unity game project to Android Studio rather than just building it. This way, you can add new features Unity doesn't provide out of the box. The Android export process is straightforward. You select Gradle as Build System, enable the Export Project checkbox, and click the Export button.

In this forum thread, Unity Technologies' user Yury-Habets mentions the same Over17's Java class to toggle status bar visibility, but the related repo hasn't been updated since 2018 and may be out of date as of today.

No need to export the project at all

On the other hand, user OJ3D refers to a script that runs right inside Unity without any additional effort. It is Zeh Fernando's ApplicationChrome.cs from the Unity Tidbits repository, whose author also describes in their blog.

The ApplicationChrome.cs script contains some Java code that Unity uses to talk to the low-level Android system APIs. It includes Android-only functions you can call from other scripts in your game to configure the appearance of your application.

Although the forum message dates back to 2016 (when Unity 5.2.3 was around) and the blog post dates back to 2015, the latest repo commit occurred in November 2019. This means the source is still being maintained. I tested the .apk demo from the blog post on an Android 9 (Pie) mobile device, and it still works.

Since Unity doesn't provide the status bar hide feature anymore, this seems a nice, working solution that requires neither writing additional code nor using external building tools.

Display the Status Bar only

Include the ApplicationChrome.cs script in your project. Its methods will be called once by a GameObject in your scene to set up the display mode:

void Start()
{
    ApplicationChrome.statusBarState = ApplicationChrome.States.Visible;
    ApplicationChrome.navigationBarState = ApplicationChrome.States.Hidden;
}

If you can still view the navigation bar, this is due to the script forcing non-fullscreen mode (at line 149). You can simply get away with it by adding a new line:

void Start()
{
    ApplicationChrome.statusBarState = ApplicationChrome.States.Visible;
    ApplicationChrome.navigationBarState = ApplicationChrome.States.Hidden;
    Screen.fullScreen = true;
}
\$\endgroup\$
6
  • \$\begingroup\$ I had issues using Over17's plugin, which is why I wrote the one in my answer. \$\endgroup\$
    – Evorlor
    Nov 30, 2021 at 16:51
  • 1
    \$\begingroup\$ It also requires context switching and may be daunting to many, one more reason not to endorse it. OTOH the second solution is more compact and only requires some function calls at startup. I re-formatted my answer to give that more focus. \$\endgroup\$
    – liggiorgio
    Nov 30, 2021 at 17:01
  • \$\begingroup\$ Thank you very much liggiorgio. The method you posted looks great. I tried it and it can definitely show the status bar. However, it also shows the navigation bar. While the blog post says both can be controlled separately this doesn't seem to work. If I set ApplicationChrome.statusBarState = ApplicationChrome.States.Visible; ApplicationChrome.navigationBarState = ApplicationChrome.States.Hidden; it still shows both the status and nav bar. This is in Android Studio Emulator using Pixel 3A that comes default with it. Any ideas? Thanks. \$\endgroup\$
    – mike
    Dec 1, 2021 at 6:32
  • \$\begingroup\$ I tried by installing an APK to my Galaxy using Evorlor's script (just to see if it would do the same) and it does - showing the status bar automatically forces the navigation bar just like in the Emulator and I can't separate the two ... I need the status but but NO navigation bar. I appreciate any help. \$\endgroup\$
    – mike
    Dec 1, 2021 at 6:54
  • \$\begingroup\$ @mike I updated my answer to include a working solution to your issues. \$\endgroup\$
    – liggiorgio
    Dec 5, 2021 at 15:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .