android5.0 物理键盘与软键盘同时使用修改
来源:互联网 发布:c 游戏编程入门教程 编辑:程序博客网 时间:2024/05/16 16:21
最近工作中遇到在android 5.0 系统插入硬件盘物理设备后,软键盘无法弹出的问题,在网上查找了相关资料:
参考:http://blog.csdn.net/DrakeBlue/article/details/39049495
http://blog.csdn.net/hclydao/article/details/44240799
http://blog.csdn.net/jdsjlzx/article/details/39495319
物理键盘映射过程:
手机/system/usr/keylayout/*.kl :内核将keyCode映射成有含义的字符串
KeycodeLabels.h : framework 将字符串映射成keyEvent的keyCode
frameworks/.../res/values/attrs.xml
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
关键代码:行6618 computeScreenConfigurationLocked()方法中
- boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
- if (hardKeyboardAvailable != mHardKeyboardAvailable) {
- mHardKeyboardAvailable = hardKeyboardAvailable;
- mHardKeyboardEnabled = !hardKeyboardAvailable;
- mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- }
- if (!mHardKeyboardEnabled) {
- config.keyboard = Configuration.KEYBOARD_NOKEYS;
- }
这样改软键盘是能用但是物理键盘是用不了的
最后研究代码frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
如果把updateShowImeWithHardKeyboard方法中的showImeWithHardKeyboard变量直接置为true,则可以实现软键盘与物理键盘的同时使用,
但此举修改影响范围很大,不推荐。
public void updateShowImeWithHardKeyboard() {
//modified by Janning for enble the HardKeyboard start
final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
mCurrentUserId) == 1;
//final boolean showImeWithHardKeyboard = true;
//modified by Janning for enble the HardKeyboard end
synchronized (mWindowMap) {
if (mShowImeWithHardKeyboard != showImeWithHardKeyboard) {
mShowImeWithHardKeyboard = showImeWithHardKeyboard;
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
}
后续继续研究代码发现在WindowManagerService.java的computeScreenConfigurationLocked方法中有通过判断当前物理键盘类型来控制是否同时启用软件盘的处理逻辑:
boolean computeScreenConfigurationLocked(Configuration config) { if (!mDisplayReady) { return false; } // TODO(multidisplay): For now, apply Configuration to main screen only. final DisplayContent displayContent = getDefaultDisplayContentLocked(); // Use the effective "visual" dimensions based on current rotation final boolean rotated = (mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270); final int realdw = rotated ? displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; final int realdh = rotated ? displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; int dw = realdw; int dh = realdh; if (mAltOrientation) { if (realdw > realdh) { // Turn landscape into portrait. int maxw = (int)(realdh/1.3f); if (maxw < realdw) { dw = maxw; } } else { // Turn portrait into landscape. int maxh = (int)(realdw/1.3f); if (maxh < realdh) { dh = maxh; } } } if (config != null) { config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; } // Update application display metrics. final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); final DisplayInfo displayInfo = displayContent.getDisplayInfo(); synchronized(displayContent.mDisplaySizeLock) { displayInfo.rotation = mRotation; displayInfo.logicalWidth = dw; displayInfo.logicalHeight = dh; displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; displayInfo.appWidth = appWidth; displayInfo.appHeight = appHeight; displayInfo.getLogicalMetrics(mRealDisplayMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); displayInfo.getAppMetrics(mDisplayMetrics); mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( displayContent.getDisplayId(), displayInfo); } if (false) { Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); } final DisplayMetrics dm = mDisplayMetrics; mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, mCompatDisplayMetrics); if (config != null) { config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) / dm.density); config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) / dm.density); computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); config.densityDpi = displayContent.mBaseDisplayDensity; // Update the configuration based on available input devices, lid switch, // and platform configuration. config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; config.keyboard = Configuration.KEYBOARD_NOKEYS; config.navigation = Configuration.NAVIGATION_NONAV; int keyboardPresence = 0; int navigationPresence = 0; final InputDevice[] devices = mInputManager.getInputDevices(); final int len = devices.length; for (int i = 0; i < len; i++) { InputDevice device = devices[i]; if (!device.isVirtual()) { final int sources = device.getSources(); final int presenceFlag = device.isExternal() ? WindowManagerPolicy.PRESENCE_EXTERNAL : WindowManagerPolicy.PRESENCE_INTERNAL; if (mIsTouchDevice) { if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) { config.touchscreen = Configuration.TOUCHSCREEN_FINGER; } } else { config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; } if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { config.navigation = Configuration.NAVIGATION_TRACKBALL; navigationPresence |= presenceFlag; } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD && config.navigation == Configuration.NAVIGATION_NONAV) { config.navigation = Configuration.NAVIGATION_DPAD; navigationPresence |= presenceFlag; } // 判断该物理设备的类型, InputDevice.KEYBOARD_TYPE_ALPHABETIC 是表示物理键盘设备 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { config.keyboard = Configuration.KEYBOARD_QWERTY; keyboardPresence |= presenceFlag; } // 获取物理设备名称,判断是否是指定的名称,如果是则把 config.keyboard // 的属性置为 Configuration.KEYBOARD_NOKEYS ,如此则可以同时兼容软键盘 // 物理键盘与软键盘可以同时启用 // Add by Janning start // for show IME with HardKeyboard if (device.getName().equals("XXX-vinput-keypad")) { Slog.w("SLCODE", "the hard device name is: " + device.getName()); config.keyboard = Configuration.KEYBOARD_NOKEYS; } // Add by Janning end } } if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) { config.navigation = Configuration.NAVIGATION_DPAD; navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; } // Determine whether a hard keyboard is available and enabled. boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; if (hardKeyboardAvailable != mHardKeyboardAvailable) { mHardKeyboardAvailable = hardKeyboardAvailable; mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); } if (mShowImeWithHardKeyboard) { config.keyboard = Configuration.KEYBOARD_NOKEYS; } // Let the policy update hidden states. config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); } return true; } public boolean isHardKeyboardAvailable() { synchronized (mWindowMap) { return mHardKeyboardAvailable; } } public void updateShowImeWithHardKeyboard() { // 此处修改也可以实现物理键盘与软键盘的同时启用,即把showImeWithHardKeyboard 直接置为 true, // 但此方法影响太大,不推荐该方案,建议根据设备名称判断 修改config.keyboard 属性值(代码见上文) //changed by Janning start //modified by Janning for enble the HardKeyboard start final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser( mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mCurrentUserId) == 1; //final boolean showImeWithHardKeyboard = true; //modified by Janning for enble the HardKeyboard end //changed by Janning end synchronized (mWindowMap) { if (mShowImeWithHardKeyboard != showImeWithHardKeyboard) { mShowImeWithHardKeyboard = showImeWithHardKeyboard; mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); } } }
经过测试以上修改可以实现物理键盘与软键盘的同时启用,完美解决问题。
二、插入物理键盘后通知栏不想弹出键盘布局通知的问题修改
a>
// Must be called on handler. private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) { // Scan for changes. int numFullKeyboardsAdded = 0; mTempInputDevicesChangedListenersToNotify.clear(); mTempFullKeyboards.clear(); final int numListeners; final int[] deviceIdAndGeneration; synchronized (mInputDevicesLock) { if (!mInputDevicesChangedPending) { return; } mInputDevicesChangedPending = false; numListeners = mInputDevicesChangedListeners.size(); for (int i = 0; i < numListeners; i++) { mTempInputDevicesChangedListenersToNotify.add( mInputDevicesChangedListeners.valueAt(i)); } final int numDevices = mInputDevices.length; deviceIdAndGeneration = new int[numDevices * 2]; for (int i = 0; i < numDevices; i++) { final InputDevice inputDevice = mInputDevices[i]; deviceIdAndGeneration[i * 2] = inputDevice.getId(); deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration(); if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) { if (!containsInputDeviceWithDescriptor(oldInputDevices, inputDevice.getDescriptor())) { mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice); } else { mTempFullKeyboards.add(inputDevice); } } } } // Notify listeners. for (int i = 0; i < numListeners; i++) { mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged( deviceIdAndGeneration); } mTempInputDevicesChangedListenersToNotify.clear(); // Check for missing keyboard layouts. if (mNotificationManager != null) { final int numFullKeyboards = mTempFullKeyboards.size(); boolean missingLayoutForExternalKeyboard = false; boolean missingLayoutForExternalKeyboardAdded = false; boolean multipleMissingLayoutsForExternalKeyboardsAdded = false; InputDevice keyboardMissingLayout = null; synchronized (mDataStore) { for (int i = 0; i < numFullKeyboards; i++) { final InputDevice inputDevice = mTempFullKeyboards.get(i); final String layout = getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier()); if (layout == null) { missingLayoutForExternalKeyboard = true; if (i < numFullKeyboardsAdded) { missingLayoutForExternalKeyboardAdded = true; if (keyboardMissingLayout == null) { keyboardMissingLayout = inputDevice; } else { multipleMissingLayoutsForExternalKeyboardsAdded = true; } } } } } if (missingLayoutForExternalKeyboard) { if (missingLayoutForExternalKeyboardAdded) { if (multipleMissingLayoutsForExternalKeyboardsAdded) { // We have more than one keyboard missing a layout, so drop the // user at the generic input methods page so they can pick which // one to set. showMissingKeyboardLayoutNotification(null); } else { // 当前只插入一个物理键盘时,获取该设备名称判断是否是指定的物理键盘名, // 如果是,则不显示键盘布局通知,否则显示通知 // Modify by Janning begin if (keyboardMissingLayout != null && !keyboardMissingLayout.getName().equals("XXXX-vinput-keypad")) { showMissingKeyboardLayoutNotification(keyboardMissingLayout); } // Modify by Janning end } } } else if (mKeyboardLayoutNotificationShown) { hideMissingKeyboardLayoutNotification(); } } mTempFullKeyboards.clear(); }
InputManagerService.java
if (missingLayoutForExternalKeyboardAdded) {
if (multipleMissingLayoutsForExternalKeyboardsAdded) {
// We have more than one keyboard missing a layout, so drop the
// user at the generic input methods page so they can pick which
// one to set.
showMissingKeyboardLayoutNotification(null);
} else {
// Modify by Janning begin
if (keyboardMissingLayout != null
&& !keyboardMissingLayout.getName().equals("XXXX-vinput-keypad")) {
showMissingKeyboardLayoutNotification(keyboardMissingLayout);
}
// Modify by Janning end
}
}
} else if (mKeyboardLayoutNotificationShown) {
hideMissingKeyboardLayoutNotification();
}
}
mTempFullKeyboards.clear();
}
- android5.0 物理键盘与软键盘同时使用修改
- android5.0 物理键盘与软键盘同时使用修改
- android4.0 物理键盘与软键盘同时使用修改
- 通过settings.db自定义Android系统默认设置:SHOW_IME_WITH_HARD_KEYBOARD 默认物理键盘与软键盘同时使用
- 解决Android 5.1物理键盘与软键盘的同时使用
- 解决Android 5.1物理键盘与软键盘的同时使用
- Android插入物理键盘的同时显示软键盘
- Android物理键盘与虚拟键盘同时使用
- QT 软键盘,物理键盘的完美实现
- QT 软键盘,物理键盘的完美实现
- Android在外接物理键盘时,如何强制调用系统软键盘
- Android 如何在插入外接物理键盘时还能显示软键盘
- android中AlertDialog包含EditText时弹出键盘(dia和软键盘同时弹出)
- Android 禁止使用物理键盘
- Android 物理键盘的启用修改
- 屏幕软键盘/触摸屏 键盘
- 屏幕软键盘/触摸屏 键盘
- Android5.0 CheckBox颜色修改
- java基础学习总结——监听当数据发生变化时要做的操作
- 松果体——人体第三只眼研究
- c++音频播放,wav格式的
- Java 接口
- 友盟推送获取简单的deviceToken
- android5.0 物理键盘与软键盘同时使用修改
- mysql中varchar(10)中定义的长度到底是字符长度还是字节长度
- 【Qt开发】QT中显示图像数据
- 1010. Radix (25)
- php调用sphinx
- java 集合1--接口及父类介绍
- 自动适配标签显示
- tomcat运行springmvc项目:m2e-wtp error: <path>/target/m2e-wtp/web-resources/META-INF/MANIFEST.MF (No such
- java基础学习总结——关于Java中的paint,repaint,update三个方法的关系