編輯:關於Android編程
第一次寫,寫的不好請見諒
物理鍵盤映射過程:
手機/system/usr/keylayout/*.kl :內核將keyCode映射成有含義的字符串
KeycodeLabels.h : framework 將字符串映射成keyEvent的keyCode
frameworks/…/res/values/attrs.xml
一、問題描述:
當平板連接上藍牙掃描槍(外接物理鍵盤)時候,不能彈出軟鍵盤輸入,需要打開系統的輸入法選擇界面關閉硬件物理鍵盤後才能調用彈出系統軟鍵盤;
理想效果:
在平板連接上藍牙掃描槍後仍可以調用系統軟鍵盤輸入,將系統的物理鍵盤默認設置為關閉狀態,或不需要開啟關閉物理鍵盤,
1.首先:你要知道AndroidManifest.xml文件。這裡這裡有的信息對於理解程序又很大的意義。
2.學會使用grep命令。修改系統的源代碼時候這個很重要,
3.當想修改一個程序時,先找到這個程序的位置,大部分只要修改framework 和package 兩個文件夾下的內容
4.關鍵字,例如要修改statuBars。先使用hierarchyviewer查看statuBar屬於那個部分。
5.根據圖標,使用grep在framework中查找對應的位置。
6.然後就是修改程序了。
android版本源碼
frameworks/base/services/Java/com/android/server/wm/WindowManagerService.java
關鍵代碼:行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,則可以實現軟鍵盤與物理鍵盤的同時使用,
但此舉修改影響范圍很大,不推薦。
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); } } }
當插入物理鍵盤後通知欄會彈出相應的選擇鍵盤布局通知,對於該通知可以選擇隱藏:
根據字符串查找到是在 frameworks\base\services\core\java\com\android\server\input\InputManagerService.java 中調用顯示該通知的,
進一步分析代碼發現是在 deliverInputDevicesChanged 方法中控制通知的顯示。
InputManagerService.java
private void deliverInputDevicesChanged(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 begin if (keyboardMissingLayout != null && !keyboardMissingLayout.getName().equals("XXXX-vinput-keypad")) { showMissingKeyboardLayoutNotification(keyboardMissingLayout); } // Modify by Janning end } } } else if (mKeyboardLayoutNotificationShown) { hideMissingKeyboardLayoutNotification(); } } mTempFullKeyboards.clear(); }
大連東軟信息學院鏡像服務器地址:– http://mirrors.neusoft.edu.cn 端口:80北京化工大學鏡像服務器地址:– IPv4
這是從Philippe Breault的系列文章《Android Studio Tips Of the Day》中提取出來的自認為精華的部分。這些技巧在實際應用中能夠非常
今天這篇文章教給大家解決這幾個問題:1、如何通過AndroidStudio的git上傳項目到github2、如何通過AndroidStudio的git將存在的項目增加的類
說到handler大家都很熟悉,自己也用了很久,再此總結一下 從handler的源碼角度看看handler是如何執行的。涉及到的內容:Loop Message Messa