Android Question Immersive mode in Android 16

yo3ggx

Active Member
Licensed User
Longtime User
Hello,

I'm using the following code to set Immersive mode.
B4X:
Sub Activity_WindowFocusChanged(HasFocus As Boolean)
    If HasFocus Then
        HideMenuBar
    End If
End Sub

Sub HideMenuBar
    Dim jo As JavaObject
    jo.InitializeContext

'    Dim NativeMe As JavaObject
'    NativeMe.InitializeStatic("anywheresoftware.b4a.ImmersiveHelper")

    Dim window As JavaObject = jo.RunMethodJO("getWindow", Null)
    Dim decorView As JavaObject = window.RunMethodJO("getDecorView", Null)
    NativeMe.RunMethod("consumeInsets", Array(decorView))

    If SDKver >= 30 Then
        ' Android 11+ (including Android 16)
        NativeMe.RunMethod("setDecorFitsSystemWindows", Array(window, False))
        window.RunMethod("addFlags", Array(0x80000000)) ' FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
        window.RunMethod("setNavigationBarColor", Array(0)) ' Transparent

        Dim wic As JavaObject = NativeMe.RunMethodJO("getInsetsController", Array(window, decorView))
        If wic.IsInitialized Then
            wic.RunMethod("setSystemBarsBehavior", Array(2)) ' BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            Dim types As JavaObject = NativeMe.RunMethod("getSystemBarsType", Null)
            wic.RunMethod("hide", Array(types))
            decorView.RunMethod("setSystemUiVisibility", Array(5894)) ' HIDE_NAV + FULLSCREEN + IMMERSIVE_STICKY
        End If
    Else
        ' Android 5–10
        Dim immersiveFlags As Int = 5894 ' SYSTEM_UI_FLAG_HIDE_NAVIGATION + SYSTEM_UI_FLAG_FULLSCREEN + SYSTEM_UI_FLAG_IMMERSIVE_STICKY
        decorView.RunMethod("setSystemUiVisibility", Array(immersiveFlags))
    End If
End Sub
#If Java

import android.view.Window;
import android.view.View;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.OnApplyWindowInsetsListener;


    public static void setDecorFitsSystemWindows(Window window, boolean fits) {
        WindowCompat.setDecorFitsSystemWindows(window, fits);
    }

    public static WindowInsetsControllerCompat getInsetsController(Window window, View decorView) {
        return WindowCompat.getInsetsController(window, decorView);
    }

    public static int getSystemBarsType() {
        return WindowInsetsCompat.Type.systemBars();
    }

    public static void consumeInsets(View view) {
        ViewCompat.setOnApplyWindowInsetsListener(view, new OnApplyWindowInsetsListener() {
            @Override
            public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                return WindowInsetsCompat.CONSUMED;
            }
        });
    }
#End If

It works from Android 5 to 15, but don't work on Android 16.
Any suggestions?

Thank you
 

yo3ggx

Active Member
Licensed User
Longtime User
In fact my issue was in the GetRealSize routine, not in the one above. Tested the solution from the link you provided, but uses SystemUiVisibility which was deprecated in SDK 30 and replaced by WindowInsetsController .https://developer.android.com/reference/android/view/View#setSystemUiVisibility(int) My final working version is the following:
B4X:
Sub HideMenuBar
    Dim jo As JavaObject
    jo.InitializeContext

    Dim window As JavaObject = jo.RunMethodJO("getWindow", Null)
    Dim decorView As JavaObject = window.RunMethodJO("getDecorView", Null)
    NativeMe.RunMethod("consumeInsets", Array(decorView))

    If SDKver >= 30 Then
        NativeMe.RunMethod("setImmersiveMode", Array(window,True))
    Else
        ' Android 5–10
        Dim immersiveFlags As Int = 5894 ' SYSTEM_UI_FLAG_HIDE_NAVIGATION + SYSTEM_UI_FLAG_FULLSCREEN + SYSTEM_UI_FLAG_IMMERSIVE_STICKY
        decorView.RunMethod("setSystemUiVisibility", Array(immersiveFlags))
    End If
End Sub

#if JAVA
import android.view.Window;
import android.view.View;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import androidx.core.view.WindowInsetsCompat;
import android.app.Activity;

public static void setImmersiveMode(Window window, boolean enabled) {
    View decorView = window.getDecorView();
    
    // 1. Set the layout to be edge-to-edge (content extends behind system bars)
    WindowCompat.setDecorFitsSystemWindows(window, !enabled);

    WindowInsetsControllerCompat windowInsetsController = WindowCompat.getInsetsController(window, decorView);

    if (windowInsetsController == null) {
        return;
    }

    if (enabled) {
        // 2. Configure for "Sticky" Immersive Mode
        // BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE: Swipe shows bars temporarily, then they hide again.
        windowInsetsController.setSystemBarsBehavior(
            WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        );

        // 3. Hide all system bars (Status Bar and Navigation Bar)
        windowInsetsController.hide(WindowInsetsCompat.Type.systemBars());
    } else {
        // 4. Show the system bars (exit immersive mode)
        windowInsetsController.show(WindowInsetsCompat.Type.systemBars());
        
        // Optionally, set the default behavior back
        windowInsetsController.setSystemBarsBehavior(
            WindowInsetsControllerCompat.BEHAVIOR_DEFAULT
        );
    }
}
#End If
 
Upvote 0

yo3ggx

Active Member
Licensed User
Longtime User
With the example from the link, on a Samsung A52 with Android 14, if you set in Android system to keep camera area free, the whole screen is shifted down and cropped



 

Attachments

  • 1759661993083.png
    85.5 KB · Views: 2
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…