Android: Programmatically Detect If Device Has Hardware Menu Button

Android: Programmatically detect if device has hardware menu button

ViewConfiguration.get(context).hasPermanentMenuKey()

See ViewConfiguration#hasPermanentMenuKey() for more information. Note that this is only available for API level 14+ (Android 4.0 Ice Cream Sandwich or newer).

Check if Android device has software or hardware navigation buttons

See this answer. You can get the real height of the display in pixels, and then get the height available to your app, and figure out if the device has an on-screen navigation bar with these values.

How to check if a phone has hardware menu button in Android 2.1?

Every compatible 2.1 android device had a menu key as it was part of the CDD:

http://source.android.com/compatibility/2.1/android-2.1-cdd.pdf

See section 8.7:

"The Home, Menu and Back functions are essential to the Android navigation paradigm. Device implementations MUST make these functions available to the user at all times, regardless of application state."

Therefore, if the device is running android 2.1 it's safe to assume it has a menu key. If it's running a later version you can use the API you found.

Check if an Android device has a certain hardware button in code

You can use PackageManager.hasSystemFeature().

Example:

boolean hasCamera = 
getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);

You can also get some of the features which are not testable by the PackageManager via the Configuration, e.g. the DPAD.

Configuration c = getResources().getConfiguration();
if(c.navigation == Configuration.NAVIGATION_DPAD)
hasDpad = true;

The only exception is the search button. There was a question here a few days ago, asking basically the same. I don't remember any answer and I don't know a way to detect the search button, since it's not in the list of features. (Edit: There you go, possible duplicate thread is the one i mentioned here)

Android ICS : How to detect that a device have on screen Back/Home button (Like Galaxy Nexus)

From your Activity you can run the following command:

boolean hasNavigationBar = false;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
{
hasNavigationBar = !ViewConfiguration.get(context).hasPermanentMenuKey();
}
else
{
hasNavigationBar = false;
}

How to find out if an android device has back and menu button as part of screen

Menu button was removed in Honeycomb. You can check API version and blindly assume if it is Honeycomb, then Menu button is not there by default (it will be added when using legacy application though). You can check API version that way:

if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
// no menu button by default..
}

These control buttons (home, back and recent apps) are always part of the screen, even in full screen (it can be dimmed, but not removed)

EDIT: however on-screen "Menu" key is not present in Honecomb by default, when you launch legacy application that is not build with targetSdk=11 (or above) then Android will show you that button (otherwise user would not be able to use the app fully). In general - if your app does NOT need menu button at all, then set targetSdk to Honeycomb and up. If you need it, set targetSdk to lower value and Android will take care of this case

Determine whether hardware buttons are drawn on screen in React Native

It appears to be easy using Java to determine whether an Android device has a physical button, so to access that in React Native I would make a Native Module wrapper to return the result of ViewConfiguration.get(context).hasPermanentMenuKey().

You can open the /android directory of your React Native project in Android Studio, then within the /app/src/main/java/<com.companyname.appname>/ folder, at the same level where you see MainActivity and MainApplication files, create a new Android resource directory called detecthardware (or any other appropriate name). Within that create DetectHardwareModule.java and include this:

package com.companyname.appname.detecthardware;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactMethod;

import java.util.List;

public class DetectHardwareModule extends ReactContextBaseJavaModule {

public DetectHardwareModule(ReactApplicationContext reactContext) {
super(reactContext);
}

@Override
public String getName() {
return "DetectHardware";
}

@ReactMethod
public void hasHardwareButtons(final Callback callback) {
callback.invoke(ViewConfiguration.get(getReactApplicationContext()).hasPermanentMenuKey());
}
}

Then create DetectHardwarePackage.java and include this:

package com.companyname.appname.detecthardware;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class DetectHardwarePackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new DetectHardwareModule(reactContext));
return modules;
}

@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}

Inside your MainApplication.java you'll need to include a getPackages
method so the JavaScript code can access it:

@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new DetectHardwarePackage()
);
}

Now within your React Native component, make sure you import NativeModules from react-native, as well as Platform so that you only run the function when on Android. In componentDidMount:

componentDidMount() {
if (Platform.OS === 'android') {
NativeModules.DetectHardware.hasHardwareButtons(function(result) {
this.setState({hasHardwareButtons: result})
}.bind(this));
}
}

And finally within your render function, calculate the bottom amount to be 0 if the platform is android and hasHardwareButtons is true, otherwise 45:

var bottom = (Platform.OS === 'android' && this.state.hasHardwareButtons) ? 0 : 45


Related Topics



Leave a reply



Submit