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
Android Setonclicklistener Method - How Does It Work
Android Broadcast Receiver Bluetooth Events Catching
How to Add to My Android Application a Button Than Do Like to a Facebook Page
Android Spanned, Spannedstring, Spannable, Spannablestring and Charsequence
How to Determine If One of My Activities Is in the Foreground
How to Shrink the Drawable on a Button
Compile with Proguard Gives Simexception: "Local Variable Type Mismatch"
How to Achieve Gapless Audio Looping So Far on Android
Save Image to Sdcard from Drawable Resource on Android
Error:Execution Failed For Task ':App:Transformclasseswithjarmergingfordebug'
Visual Studio (2015) Emulator for Android Not Working - Xde.Exe - Exit Code 3
How to Create a Custom Notification Layout in Android
Activity Declaration in Androidmanifest.Xml
How to Use Adb in Android Studio to View an SQLite Db
How to Block a Mobile Number Call and Message Receiving in Android Application Development
Move Markers in Google Map V2 Android