These two ways are restricted by non-SDK interfaces restrictions(*reflection required*):
if you call PackageManager#getInstalledApplications, you'll see some applications' package name contains "systemui.navbar", they belongs to Runtime Resource Overlay(RRO) packages which their isResourceOverlay() returns true. System use android.content.om.OverlayManager to manage overlay packages and android.content.om.OverlayInfo to get enable state.
use getResources().getInteger() with com.android.internal.R$integer#config_navBarInteractionMode to get
value android.view.WindowManagerPolicyConstants#NAV_BAR_MODE_*
so...
after several tries...
(Java)
gesture navigation maybe smaller than or equals to status bar normally, so if it's larger, i think it's 2/3-button.
based on API level 29, see WindowInsets or compat.
//...
import android.graphics.Color;
import android.graphics.Insets;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowInsets$Type;
import android.os.Build;
//...
private boolean isAndroidR = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
view.setOnApplyWindowInsetsListener((View v, WindowInsets i) -> {
Insets inset = isAndroidR
//or getInsetsIgnoringVisibility
? i.getInsets(
Type.statusBars() | Type.navigationBars()
)
//or getStableInsets
: i.getSystemWindowInsets();
//some devices' height maybe 0
int status, navigation;
//the height difference of gesture navigation and notification bar is small
boolean isGestureNavigation =
//maybe 0 if hidden, use getInsetsIgnoringVisibility/getStableInsets
(status = inset.top) != 0 &&
//some system may provide an option to always hide gesture navigation, so always 0
(navigation = inset.bottom) != 0 &&
status >= navigation;
//do something
getWindow().setNavigationBarColor(
isGestureNavigation ? Color.TRANSPARENT : Color.BLUE
);
return i;//isAndroidR ? WindowInsets.CONSUMED : i.consumeSystemWindowInsets()
});
//...