中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android中怎么檢測外接鍵盤

發布時間:2021-08-07 15:18:16 來源:億速云 閱讀:147 作者:Leah 欄目:編程語言

這期內容當中小編將會給大家帶來有關Android中怎么檢測外接鍵盤,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

Configuration

Android系統中通過讀取Configuration中keyboard的值來判斷是否存在外接鍵盤。Configuration中關于鍵盤類型的定義如下,

public static final int KEYBOARD_UNDEFINED = 0; // 未定義的鍵盤  public static final int KEYBOARD_NOKEYS = 1; // 無鍵鍵盤,沒有外接鍵盤時為該類型  public static final int KEYBOARD_QWERTY = 2; // 標準外接鍵盤  public static final int KEYBOARD_12KEY = 3; // 12鍵小鍵盤

在最常見的情況下,外接鍵盤未連接時keyboard的值為KEYBOARD_NOKEYS,當檢測到鍵盤連接后會將keyboard的值更新為KEYBOARD_QWERTY 。應用就可以根據keyboard的值來判斷是否存在外接鍵盤,InputMethodService.java中有類似的判斷代碼。

// 軟件盤是否可以顯示  public boolean onEvaluateInputViewShown() {    Configuration config = getResources().getConfiguration();    return config.keyboard == Configuration.KEYBOARD_NOKEYS        || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;  }

現在的問題就轉向Configuration的keyboard是如何更新的。在WindowManagerService.java中,應用啟動時會更新Configuration,相關代碼如下。

boolean computeScreenConfigurationLocked(Configuration config) {    ......    if (config != null) {      // Update the configuration based on available input devices, lid switch,      // and platform configuration.      config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;      // 默認值為KEYBOARD_NOKEYS      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];        // 如果不是虛擬輸入設備,會根據輸入設備的flags來更新Configuration        if (!device.isVirtual()) {          ......          // 如果輸入設備的鍵盤類型為KEYBOARD_TYPE_ALPHABETIC,則將keyboard設置為KEYBOARD_QWERTY          if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {            config.keyboard = Configuration.KEYBOARD_QWERTY;            keyboardPresence |= presenceFlag;          }        }      }      ......      // 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);      }      // 如果Setting中SHOW_IME_WITH_HARD_KEYBOARD被設置,將keyboard設置為KEYBOARD_NOKEYS,讓軟件盤可以顯示      if (mShowImeWithHardKeyboard) {        config.keyboard = Configuration.KEYBOARD_NOKEYS;      }      ......    }

影響Configuration中keyboard的值有,

默認值為KEYBOARD_NOKEYS,表示沒有外接鍵盤。當輸入設備為KEYBOARD_TYPE_ALPHABETIC時,更新為KEYBOARD_QWERTY,一個標準鍵盤。當Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD為1時,設置為KEYBOARD_NOKEYS,目的是讓軟鍵盤可以顯示。

inputflinger

接下來需要關注輸入設備時何時被設置KEYBOARD_TYPE_ALPHABETIC的。搜索代碼可以看到,這個flag實在native代碼中設置的,代碼在inputflinger/InputReader.cpp中。native和java使用了同一定義值,如果修改定義時需要注意同時修改。native中的名字為AINPUT_KEYBOARD_TYPE_ALPHABETIC。

InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,    const InputDeviceIdentifier& identifier, uint32_t classes) {  InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),      controllerNumber, identifier, classes);  ......  if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {    keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;  }  ......  return device;}

InputReader在增加設備時,根據classes的flag來設置鍵盤類型。這個flag又是在EventHub.cpp中設置的。

status_t EventHub::openDeviceLocked(const char *devicePath) {  ......  // Configure the keyboard, gamepad or virtual keyboard.  if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {    // 'Q' key support = cheap test of whether this is an alpha-capable kbd    if (hasKeycodeLocked(device, AKEYCODE_Q)) {      device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;    }  ......}

看到這里就比較明確了,在EventHub加載設備時,如果輸入設備為鍵盤,并且帶有'Q'鍵,就認為這是一個標準的外接鍵盤。但為何判斷'Q'鍵還不是很清楚。

keylayout

上面說道通過'Q'鍵來判斷是否為外接鍵盤,這個'Q'鍵是Android的鍵值,鍵值是否存在是通過一個keylayout文件決定的。kl文件存儲在目標系統的/system/usr/keylayout/下,系統可以有多個kl文件,根據設備的ID來命名。當系統加載鍵盤設備時,就會根據設備的Vendor ID和Product ID在/system/usr/keylayout/下尋找kl文件。例如一個kl文件名為”Vendor_0c45_Product_1109.kl“,表明設備的Vendor ID為0c45,Product ID為1109。一個kl的內容示例如下,

key 1   BACKkey 28  DPAD_CENTERkey 102  HOMEkey 103  DPAD_UPkey 105  DPAD_LEFTkey 106  DPAD_RIGHTkey 108  DPAD_DOWNkey 113  VOLUME_MUTEkey 114  VOLUME_DOWNkey 115  VOLUME_UPkey 142  POWER

鍵值映射需要使用關鍵之”key“進行聲明,之后跟著的數字為Linux驅動中的鍵值定義,再后面的字符串是Android中按鍵的名稱。'Q'鍵是否存在完全取決于kl文件中是否有映射,而不是實際物理鍵是否存在。kl文件的查找也是有一個規則的,其查找順序如下,

/system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl/system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl/system/usr/keylayout/DEVICE_NAME.kl/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl/data/system/devices/keylayout/DEVICE_NAME.kl/system/usr/keylayout/Generic.kl/data/system/devices/keylayout/Generic.kl

同時支持軟硬鍵盤

有了上面的知識,就可以給出同時支持軟硬鍵盤的方案。

修改源碼邏輯,設置Configuration中keyboard的值為KEYBOARD_NOKEYS。這種Hack其實不好,破壞原生邏輯,缺乏移植性。非要這樣改的話,可以增加對設備的判斷,只有特定的鍵盤設備設置為KEYBOARD_NOKEYS,減少副作用。修改keylayout,去掉'Q'鍵映射。有時kl文件寫的不標準,為了通用把所有鍵的映射都寫上了,實際硬件鍵卻很少,我們就是這種情況。應該按照真實硬件來編寫kl文件。設置Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD為1。我認為這是最標準的修改方式,也非常方便。

關于第三個方案的修改方式有兩種,一種是修改缺省的setting值,在文件frameworks/base/packages/SettingsProvider/res/values/defaults.xml中增加,

<integer name="def_show_ime_with_hard_keyboard">1</integer>

另一種方式是在系統啟動時在代碼中通過接口進行設置。

Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 1);

上述就是小編為大家分享的Android中怎么檢測外接鍵盤了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

河北区| 张掖市| 安义县| 石首市| 阳朔县| 双鸭山市| 沅陵县| 山西省| 芷江| 耿马| 延寿县| 旬阳县| 内乡县| 青冈县| 阳西县| 清苑县| 高密市| 霍林郭勒市| 满洲里市| 保山市| 玉田县| 桐乡市| 栾川县| 团风县| 新乡县| 通许县| 怀宁县| 资溪县| 富阳市| 临邑县| 彰武县| 武宁县| 衡水市| 西丰县| 天柱县| 景德镇市| 夏津县| 宁强县| 兴仁县| 友谊县| 雅江县|