android外接键盘打汉字,Android在外接物理键盘时,如何强制调用系统软键盘
Android在外接物理鍵盤時,如何強制調(diào)用系統(tǒng)軟鍵盤?
第一次寫,寫的不好請見諒
參考:
物理鍵盤映射過程:
手機/system/usr/keylayout/*.kl :內(nèi)核將keyCode映射成有含義的字符串
KeycodeLabels.h : framework 將字符串映射成keyEvent的keyCode
frameworks/…/res/values/attrs.xml
一、問題描述:
當(dāng)平板連接上藍牙掃描槍(外接物理鍵盤)時候,不能彈出軟鍵盤輸入,需要打開系統(tǒng)的輸入法選擇界面關(guān)閉硬件物理鍵盤后才能調(diào)用彈出系統(tǒng)軟鍵盤;
理想效果:
在平板連接上藍牙掃描槍后仍可以調(diào)用系統(tǒng)軟鍵盤輸入,將系統(tǒng)的物理鍵盤默認(rèn)設(shè)置為關(guān)閉狀態(tài),或不需要開啟關(guān)閉物理鍵盤,
1.首先:你要知道AndroidManifest.xml文件。這里這里有的信息對于理解程序又很大的意義。
2.學(xué)會使用grep命令。修改系統(tǒng)的源代碼時候這個很重要,
3.當(dāng)想修改一個程序時,先找到這個程序的位置,大部分只要修改framework 和package 兩個文件夾下的內(nèi)容
4.關(guān)鍵字,例如要修改statuBars。先使用hierarchyviewer查看statuBar屬于那個部分。
5.根據(jù)圖標(biāo),使用grep在framework中查找對應(yīng)的位置。
6.然后就是修改程序了。
frameworks/base/services/Java/com/android/server/wm/WindowManagerService.java
關(guān)鍵代碼:行6618 computeScreenConfigurationLocked()方法中
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
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;}
將mHardKeyboardEnabled直接改成false
這樣改軟鍵盤是能用但是物理鍵盤是用不了的
最后研究代碼frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
如果把updateShowImeWithHardKeyboard方法中的showImeWithHardKeyboard變量直接置為true,則可以實現(xiàn)軟鍵盤與物理鍵盤的同時使用,
但此舉修改影響范圍很大,不推薦。
publicvoidupdateShowImeWithHardKeyboard() {//modified by Janning for enble the HardKeyboard startfinalbooleanshowImeWithHardKeyboard = 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 endsynchronized(mWindowMap) {if(mShowImeWithHardKeyboard != showImeWithHardKeyboard) {? ? ? ? ? ? ? ? mShowImeWithHardKeyboard = showImeWithHardKeyboard;? ? ? ? ? ? ? ? mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);? ? ? ? ? ? }? ? ? ? }? ? }
后續(xù)繼續(xù)研究代碼發(fā)現(xiàn)在WindowManagerService.java的computeScreenConfigurationLocked方法中有通過判斷當(dāng)前物理鍵盤類型來控制是否同時啟用軟件盤的處理邏輯:
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,? ? ? ? ? ? //andplatform 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;}? ? ? ? ? ? ? ? ? ? // 判斷該物理設(shè)備的類型, InputDevice.KEYBOARD_TYPE_ALPHABETIC 是表示物理鍵盤設(shè)備? ? ? ? ? ? ? ? ? ? if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {? ? ? ? ? ? ? ? ? ? ? ? config.keyboard= Configuration.KEYBOARD_QWERTY;keyboardPresence |= presenceFlag;}? ? ? ? ? ? ? ? ? ? // 獲取物理設(shè)備名稱,判斷是否是指定的名稱,如果是則把 config.keyboard// 的屬性置為 Configuration.KEYBOARD_NOKEYS ,如此則可以同時兼容軟鍵盤? ? ? ? ? ? ? ? ? ? // 物理鍵盤與軟鍵盤可以同時啟用? ? ? ? ? ? ? ? ? ? //Addby 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;}? ? ? ? ? ? ? ? ? ? //Addby Janning end? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? if (config.navigation== Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {? ? ? ? ? ? ? ? config.navigation= Configuration.NAVIGATION_DPAD;navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;}? ? ? ? ? ? // Determine whether a hard keyboard is availableandenabled.? ? ? ? ? ? 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() {? ? ? ? // 此處修改也可以實現(xiàn)物理鍵盤與軟鍵盤的同時啟用,即把showImeWithHardKeyboard 直接置為 true,? ? ? ? // 但此方法影響太大,不推薦該方案,建議根據(jù)設(shè)備名稱判斷 修改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);}? ? ? ? }? ? }
當(dāng)插入物理鍵盤后通知欄會彈出相應(yīng)的選擇鍵盤布局通知,對于該通知可以選擇隱藏:
根據(jù)字符串查找到是在 frameworks\base\services\core\java\com\android\server\input\InputManagerService.java 中調(diào)用顯示該通知的,
進一步分析代碼發(fā)現(xiàn)是在 deliverInputDevicesChanged 方法中控制通知的顯示。
InputManagerService.java
privatevoiddeliverInputDevicesChanged(InputDevice[] oldInputDevices) {? ? ? ? 。。。。。。。。。。。。。。。。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 beginif(keyboardMissingLayout !=null&& !keyboardMissingLayout.getName().equals("XXXX-vinput-keypad")) {? ? ? ? ? ? ? ? ? ? ? ? ? ? showMissingKeyboardLayoutNotification(keyboardMissingLayout);? ? ? ? ? ? ? ? ? ? ? ? }// Modify by Janning end}? ? ? ? ? ? ? ? }? ? ? ? ? ? }elseif(mKeyboardLayoutNotificationShown) {? ? ? ? ? ? ? ? hideMissingKeyboardLayoutNotification();? ? ? ? ? ? }? ? ? ? }? ? ? ? mTempFullKeyboards.clear();? ? }
操作步驟(不具體說明):
1.下載好ubuntu系統(tǒng)之后。
2.在找到sdk位置(就是你的SDK 找到你用的那個系統(tǒng),在到ubuntu修改)。
………………………..(做起來不是這么簡單)
3.再用ub系統(tǒng)上生成.jar,再放在SDK里面
有問題:
總結(jié)
以上是生活随笔為你收集整理的android外接键盘打汉字,Android在外接物理键盘时,如何强制调用系统软键盘的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dismiss ios pop效果_iO
- 下一篇: stm32按键输入实验c语言,stm32