Detect soft navigation bar availability in android device progmatically?

拥有回忆 提交于 2019-11-27 00:53:52

问题


I am trying to determine soft navigation bar through the android program. I didn't find straight way to determine. Is there anyway to find the navigation bar availability.

Soft Navigation bar image is here.


回答1:


Following method worked for me and tested in many devices.

public boolean hasNavBar (Resources resources)
    {
        int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
        return id > 0 && resources.getBoolean(id);
    }

Note: Verified this method in real device




回答2:


As i know you can detect it by

boolean hasSoftKey = ViewConfiguration.get(context).hasPermanentMenuKey();

But it required APIs 14+


If above solution doesn't work for you then try below method

public boolean isNavigationBarAvailable(){

        boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
        boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);

        return (!(hasBackKey && hasHomeKey));
    }



回答3:


Its a hack but it works fine. Try it.

public static boolean hasSoftKeys(WindowManager windowManager){
  Display d = windowManager.getDefaultDisplay();

  DisplayMetrics realDisplayMetrics = new DisplayMetrics();
  d.getRealMetrics(realDisplayMetrics);  

  int realHeight = realDisplayMetrics.heightPixels;
  int realWidth = realDisplayMetrics.widthPixels;

  DisplayMetrics displayMetrics = new DisplayMetrics();
  d.getMetrics(displayMetrics);

  int displayHeight = displayMetrics.heightPixels;
  int displayWidth = displayMetrics.widthPixels;

  return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
}



回答4:


The accepted answer should work fine on most real devices, but it doesn't work in the emulators.

However, in Android 4.0 and above, there's an internal API that also works on the emulators: IWindowManager.hasNavigationBar(). You can access it using reflection:

/**
 * Returns {@code null} if this couldn't be determined.
 */
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@SuppressLint("PrivateApi")
public static Boolean hasNavigationBar() {
    try {
        Class<?> serviceManager = Class.forName("android.os.ServiceManager");
        IBinder serviceBinder = (IBinder)serviceManager.getMethod("getService", String.class).invoke(serviceManager, "window");
        Class<?> stub = Class.forName("android.view.IWindowManager$Stub");
        Object windowManagerService = stub.getMethod("asInterface", IBinder.class).invoke(stub, serviceBinder);
        Method hasNavigationBar = windowManagerService.getClass().getMethod("hasNavigationBar");
        return (boolean)hasNavigationBar.invoke(windowManagerService);
    } catch (ClassNotFoundException | ClassCastException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        Log.w("YOUR_TAG_HERE", "Couldn't determine whether the device has a navigation bar", e);
        return null;
    }
}



回答5:


Try this method,in this way you can detect if the navigation bar exist.

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public boolean hasNavBar(Context context) {
    Point realSize = new Point();
    Point screenSize = new Point();
    boolean hasNavBar = false;
    DisplayMetrics metrics = new DisplayMetrics();
    this.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
    realSize.x = metrics.widthPixels;
    realSize.y = metrics.heightPixels;
    getWindowManager().getDefaultDisplay().getSize(screenSize);
    if (realSize.y != screenSize.y) {
        int difference = realSize.y - screenSize.y;
        int navBarHeight = 0;
        Resources resources = context.getResources();
        int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            navBarHeight = resources.getDimensionPixelSize(resourceId);
        }
        if (navBarHeight != 0) {
            if (difference == navBarHeight) {
                hasNavBar = true;
            }
        }

    }
    return hasNavBar;

}



回答6:


Other answers don't help me. But it's quite useful to know if navigation bar is shown, especially after Android P/Q, where user can swipe it out of screen. I've encounter this article https://blog.stylingandroid.com/gesture-navigation-window-insets/ and made such method

fun hasNavBar(activity: Activity): Boolean {
    val temporaryHidden = activity.window.decorView.visibility and View.SYSTEM_UI_FLAG_HIDE_NAVIGATION != 0
    if (temporaryHidden) return false
    val decorView = activity.window.decorView
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        decorView.rootWindowInsets?.let{
            return it.stableInsetBottom != 0
        }
    }
    return true
}



回答7:


Right answer and other are not actual now.
There are exist some options like 'Full Screen Display -> Full Screen Gestures' where navigation bar is hidden but all this methods returns that he is present.

I suggest you to use this way to check size of system views. In onCreate method:

ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content), 
  (v, insets) -> { 
      int navigationBarHeight = insets.getSystemWindowInsetBottom();
      return insets;
  });


来源:https://stackoverflow.com/questions/28983621/detect-soft-navigation-bar-availability-in-android-device-progmatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!