Android devices hide the virtual keyboard by default after a USB or Bluetooth physical keyboard is connected. This behavior is common on education tablets, large-screen devices, and industrial terminals. This article traces the control flow behind
SHOW_IME_WITH_HARD_KEYBOARDand provides Framework source analysis, adb verification steps, and a system default fix strategy. Keywords: Android IME, physical keyboard, virtual keyboard.
Technical specifications are summarized here
| Parameter | Description |
|---|---|
| Tech stack | Android Framework / SettingsProvider / ADB |
| Languages | Java, XML, Bash |
| Key protocols/interfaces | Settings.Secure, InputMethodService, dumpsys |
| Star count | Original data not provided |
| Core dependencies | InputMethodManagerService, SettingsProvider, DatabaseHelper |
This behavior is the default Android IME policy, not an app-layer bug
When no physical keyboard is connected, tapping an input field usually brings up the soft keyboard. After a USB or Bluetooth keyboard is attached, the system assumes the user already has a hardware input device, so it suppresses the virtual keyboard by default.
This behavior is explicitly designed in AOSP and fits phone scenarios well. However, on education terminals, POS devices, industrial control panels, and large touchscreen all-in-one devices, it directly affects Chinese input and touch interaction.
You can confirm the issue quickly with four signals
- Without a physical keyboard, tapping an input field shows the virtual keyboard normally.
- After a physical keyboard is connected, the virtual keyboard no longer appears.
- After disconnecting the keyboard, the behavior returns to normal.
- System Settings often include a Show virtual keyboard toggle, and it is usually off by default.
# Query the current control value
adb shell settings get secure show_ime_with_hard_keyboard
# A result of 0 or empty usually means the soft keyboard is hidden when a physical keyboard is connected
Use this command to quickly determine whether the issue comes from a system setting rather than input field logic.
The root cause comes from a combined check of Configuration and Secure Settings
Android does not check only whether a keyboard exists. It also combines Configuration.keyboard and Configuration.hardKeyboardHidden to determine whether a physical keyboard is currently available.
After the system detects an external keyboard, the configuration is typically updated to indicate that a physical keyboard exists and is not hidden. If the secure setting is not enabled at that point, the input framework decides not to show the soft keyboard.
// Typical state after a physical keyboard is connected
Configuration config = getResources().getConfiguration();
int keyboard = config.keyboard; // Current keyboard type
int hardKeyboardHidden = config.hardKeyboardHidden; // Whether the physical keyboard is hidden
boolean hasHardKeyboard = keyboard != Configuration.KEYBOARD_NOKEYS;
boolean hardKeyboardVisible =
hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
This code shows that both physical keyboard presence and visibility are the foundation of the system soft-keyboard policy.
InputMethodManagerService reads the global switch before allowing IME display
The key Framework-side value is Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD. Its default value is usually , which means Android hides the virtual keyboard when a physical keyboard is connected.
final boolean showImeWithHardKeyboard = Settings.Secure.getInt(
mContext.getContentResolver(),
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
0 // Default value is 0, which means do not show the soft keyboard alongside a physical keyboard
) != 0;
if (!showImeWithHardKeyboard) {
// When a hardware keyboard is connected, the system tends not to show the virtual keyboard
}
This logic reveals the real root cause: the input field is not broken. The system policy simply disables IME display by default in hard-keyboard scenarios.
The input method service layer may evaluate input view visibility again
Even if the service layer allows display, the specific IME can still perform a second check inside InputMethodService.onEvaluateInputViewShown(). If the IME implementation follows the system setting, it reads the same switch again.
@Override
public boolean onEvaluateInputViewShown() {
Configuration config = getResources().getConfiguration();
boolean hasHardKeyboard = config.keyboard != Configuration.KEYBOARD_NOKEYS;
boolean hardKeyboardVisible =
config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
if (hasHardKeyboard && hardKeyboardVisible) {
// If a hardware keyboard is present and currently visible, continue by reading the system switch
if (!mSettingsObserver.shouldShowImeWithHardKeyboard()) {
return false; // Explicitly do not show the soft keyboard
}
}
return true;
}
This means the system has at least two constraints: InputMethodManagerService and the IME’s own display policy. In troubleshooting, changing your understanding in only one place is often not enough.
The default value actually comes from SettingsProvider initialization
Many developers only notice the runtime switch and overlook where the default comes from. On first boot or after a factory reset, SettingsProvider loads a boolean from defaults.xml into the Settings.Secure database.
<!-- Common AOSP default: do not show the virtual keyboard when a physical keyboard is connected -->
<bool name="def_show_ime_with_hard_keyboard">false</bool>
// Load the default secure setting during DatabaseHelper initialization
loadBooleanSetting(
stmt,
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
R.bool.def_show_ime_with_hard_keyboard
);
This pair of snippets explains why modifying Framework code may affect new devices while older devices remain unchanged: the old value has already been persisted in the database.
The recommended fix is to change the default value and verify it with adb
If you maintain a ROM, a custom tablet, or an industry device, the most reliable fix is to change the default value to true so that physical and virtual keyboards can coexist on first boot.
<!-- Before -->
<bool name="def_show_ime_with_hard_keyboard">false</bool>
<!-- After -->
<bool name="def_show_ime_with_hard_keyboard">true</bool>
This change works well as a product-level default, but it takes effect only during first-time initialization or after a factory reset reloads the database.
Use adb first for immediate validation during debugging
# Enable: still show the virtual keyboard when a physical keyboard is connected
adb shell settings put secure show_ime_with_hard_keyboard 1
# Disable: restore the default behavior that hides the keyboard
adb shell settings put secure show_ime_with_hard_keyboard 0
# View the current value
adb shell settings get secure show_ime_with_hard_keyboard
These commands let you validate the fix path directly without rebuilding the system. In most cases, the change takes effect immediately and does not require a reboot.
Deeper troubleshooting requires checking Settings UI, IME implementation, and device detection
Some systems expose a Show virtual keyboard entry in Settings, while others remove it in custom builds. If the entry is missing, check whether PhysicalKeyboardFragment has been removed or disabled.
If the setting is already 1 but the soft keyboard still does not appear, the issue most likely shifts to the third-party IME. Some IMEs override onEvaluateInputViewShown() and do not follow the system setting.
# Check the secure switch
adb shell settings get secure show_ime_with_hard_keyboard
# Check IME-related state
adb shell dumpsys input_method
# Filter input devices and confirm whether the device is recognized as an external keyboard
adb shell dumpsys input | grep -E "(Device [0-9-]+:|IsExternal:|Sources:|KeyboardType:)"
These commands verify the setting value, IME state, and input device detection result at the same time. They form the most practical three-step troubleshooting method.
Peripheral detection determines whether Android enters the hard-keyboard policy path
When dumpsys input shows IsExternal: true and Sources: KEYBOARD, the system has usually classified the device as a hardware keyboard. If the device is only a mouse, it shows Sources: MOUSE instead and does not trigger the same IME policy.
AI Visual Insight: This image appears to be a runtime or status indicator UI element. It highlights an interaction entry related to code execution or IME debugging guidance, rather than conveying a concrete framework architecture diagram.
The conclusion is straightforward: the fix point is small, but you must separate defaults from runtime values
Only one setting truly controls this issue: show_ime_with_hard_keyboard. But it spans four layers: default resources, database initialization, Framework service decisions, and IME display policy.
For production devices, modify defaults.xml first. For live debugging, use adb first. For abnormal device models, check whether a third-party IME overrides system logic. This is far more effective than repeatedly calling showSoftInput() at the application layer.
FAQ
1. Why does the keyboard still not appear even if I force showSoftInput() in my app?
Because the system layer has already determined that a physical keyboard exists and blocks display through SHOW_IME_WITH_HARD_KEYBOARD. Application-layer calls may be intercepted by the Framework or the input method service.
2. Why do older devices not change after I modify defaults.xml?
Because this value is written into Settings.Secure only on first boot or after a factory reset. Older devices already have the old value stored in the database, so you must override it with adb, an upgrade script, or a database reset.
3. Why does a third-party IME still not show even after I set the value to 1?
That usually means the IME has customized onEvaluateInputViewShown() or its internal display policy and does not follow the system setting. In that case, inspect the IME app implementation directly.
Core summary: This article starts from Android Framework source code and breaks down why the soft keyboard does not appear after a USB or Bluetooth keyboard is connected. It identifies the interaction among InputMethodManagerService, InputMethodService, and SettingsProvider, and provides adb verification steps, a default-value fix, and a practical troubleshooting path.