Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Fullscreen Galaxy Nexus; how to disable the system navigation softkeys

Discussion in 'Android' started by Tynkerror, Feb 23, 2012.

  1. Tynkerror

    Tynkerror

    Joined:
    Feb 23, 2012
    Posts:
    4
    Hi, has anyone tried to get their Unity app to go fullscreen on the Galaxy Nexus (running Android Ice Cream Sandwich)? The navigation bar takes up screen space and reduces the resolution to 1196 by 720. I wrote a C# script that uses the code below to access the Android "View" object, but the line viewInstance.Call("setSystemUiVisibility", 2); causes the app to crash as soon as it starts up.

    Code (csharp):
    1.  
    2.         if (Application.platform == RuntimePlatform.Android)
    3.         {
    4.             using (AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    5.             {
    6.                 using (AndroidJavaObject activityInstance = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity"))
    7.                 {
    8.                     using (AndroidJavaObject windowInstance = activityInstance.Call<AndroidJavaObject>("getWindow"))
    9.                     {
    10.                         using (AndroidJavaObject viewInstance = windowInstance.Call<AndroidJavaObject>("getDecorView"))
    11.                         {
    12.                             viewInstance.Call("setSystemUiVisibility", 2);
    13.                         }
    14.                     }
    15.  
    16.                 }
    17.             }
    18.         }
    19.  
    The value of 2 in that line of code corresponds to this constant: http://developer.android.com/reference/android/view/View.html#SYSTEM_UI_FLAG_HIDE_NAVIGATION
     
    Last edited: Feb 23, 2012
  2. Tseng

    Tseng

    Joined:
    Nov 29, 2010
    Posts:
    1,217
    It's a threading issue. You can access/change UI elements only from the thread which created it, and that's the main thread. Unity3D player itself runs in a seperate thread.

    You must call "setSystemUiVisibility" inside of a runOnUiThread method.

    Java Code:
    Code (csharp):
    1.  
    2.         final Activity currentActivity = (Activity)UnityPlayer.currentActivity;
    3.         currentActivity.runOnUiThread(new Runnable() {
    4.            
    5.             @Override
    6.             public void run() {
    7.                 setSystemUiVisibility(2);
    8.             }
    9.         });
    10.  
    Then the code will be executed in the proper thread.
     
  3. Tynkerror

    Tynkerror

    Joined:
    Feb 23, 2012
    Posts:
    4
    So I tried implementing that in C# with the following, but I guess this isn't enough to do it:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class DisableSystemUI
    5. {
    6.     static AndroidJavaObject activityInstance;
    7.     static AndroidJavaObject windowInstance;
    8.     static AndroidJavaObject viewInstance;
    9.  
    10.     public delegate void RunPtr();
    11.  
    12.     public static void Run()
    13.     {
    14.         if (viewInstance != null) {
    15.             viewInstance.Call("setSystemUiVisibility", 2);
    16.         }
    17.     }
    18.  
    19.     static DisableSystemUI()
    20.     {
    21.         if (Application.platform != RuntimePlatform.Android)
    22.             return;
    23.         DisableNavUI();
    24.     }
    25.  
    26.     static void DisableNavUI()
    27.     {
    28.         if (Application.platform != RuntimePlatform.Android)
    29.             return;
    30.        
    31.         using (AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    32.         {
    33.             activityInstance = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
    34.             windowInstance = activityInstance.Call<AndroidJavaObject>("getWindow");
    35.             viewInstance = windowInstance.Call<AndroidJavaObject>("getDecorView");
    36.  
    37.             AndroidJavaRunnable RunThis;
    38.             RunThis = new AndroidJavaRunnable(new RunPtr(Run));
    39.             activityInstance.Call("runOnUiThread", AndroidJNIHelper.CreateJavaRunnable(RunThis));
    40.         }
    41.     }
    42. }
    43.  
     
  4. eriQue

    eriQue

    Unity Technologies

    Joined:
    May 25, 2010
    Posts:
    595
    You should not call AndroidJNIHelper.CreateJavaRunnable here - just pass the RunThis delegate as a parameter.
     
  5. StephanK

    StephanK

    Joined:
    Jul 10, 2012
    Posts:
    47
    Did you get this to work somehow? I tried the code posted above with Erique's addition but the soft keys don't disappear. The delegate is called correctly though.
     
  6. Agent_007

    Agent_007

    Joined:
    Dec 18, 2011
    Posts:
    899
  7. StephanK

    StephanK

    Joined:
    Jul 10, 2012
    Posts:
    47
    Yes, but I don't want to hide them, i want to be able to use that screen space. So instead of setting the LOW_PROFILE flag i would like to be able to set the SYSTEM_UI_FLAG_HIDE_NAVIGATION or SYSTEM_UI_FLAG_IMMERSIVE.
     
  8. vitaly

    vitaly

    Joined:
    Oct 12, 2012
    Posts:
    10
    So this is my final variant which works and initializes the immersive sticky mode. I call DisableSystemUI.DisableNavUI() in OnApplicationFocus. But the problem is when you change volume or use a virtual keyboard the immersive mode switches off and you need to call the function DisableNavUI again. But how to know from unity when to reinitialize the immersive mode?

    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class DisableSystemUI
    5. {
    6. #if UNITY_ANDROID
    7.     static AndroidJavaObject activityInstance;
    8.     static AndroidJavaObject windowInstance;
    9.     static AndroidJavaObject viewInstance;
    10.  
    11.     const int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2;
    12.     const int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256;
    13.     const int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512;
    14.     const int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024;
    15.     const int SYSTEM_UI_FLAG_IMMERSIVE = 2048;
    16.     const int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096;
    17.     const int SYSTEM_UI_FLAG_FULLSCREEN = 4;
    18.  
    19.     public delegate void RunPtr();
    20.  
    21.     public static void Run()
    22.     {
    23.         if (viewInstance != null) {
    24.             viewInstance.Call("setSystemUiVisibility",
    25.                               SYSTEM_UI_FLAG_LAYOUT_STABLE
    26.                               | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    27.                               | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    28.                               | SYSTEM_UI_FLAG_HIDE_NAVIGATION
    29.                               | SYSTEM_UI_FLAG_FULLSCREEN
    30.                               | SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    31.         }
    32.  
    33.     }
    34. #endif  
    35.     public static void DisableNavUI()
    36.     {
    37.         if (Application.platform != RuntimePlatform.Android)
    38.             return;
    39. #if UNITY_ANDROID
    40.         using (AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    41.         {
    42.             activityInstance = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
    43.             windowInstance = activityInstance.Call<AndroidJavaObject>("getWindow");
    44.             viewInstance = windowInstance.Call<AndroidJavaObject>("getDecorView");
    45.  
    46.             AndroidJavaRunnable RunThis;
    47.             RunThis = new AndroidJavaRunnable(new RunPtr(Run));
    48.             activityInstance.Call("runOnUiThread", RunThis);
    49.         }
    50. #endif
    51.     }
    52.  
    53. }
    54.  
     
  9. akasurreal

    akasurreal

    Joined:
    Jul 17, 2009
    Posts:
    441
    Thanks for sharing Vitaly, does work, but having same issues as you. Unity needs to add this as native option so it works right. As a hack, I wonder if you could just call this once a second or something to fix itself.
     
  10. Marzoa

    Marzoa

    Joined:
    Dec 2, 2012
    Posts:
    50
    Any news on this?
     
  11. PieThief

    PieThief

    Joined:
    Sep 17, 2015
    Posts:
    2
    I was also curious about this, and whether anyone else found a more fool-proof way to get rid of the bars. We're having some issues with some integrated plugins that have native pop-ups causing the bar to appear, and then get stuck. Our QA guy noticed if he opened up one of OUR input dialogs though, the bar would go away. Lo and behold, I found a very similar call to what Vitaly has above in our code when our dialog goes away. So I'm thinking of just brute forcing that in the game's update loop or something. We can't seem to make it work 100% with event handlers unfortunately.