鍵字符映射文件( .kcm
文件)負責將帶有修飾符的 Android 鍵代碼組合映射到 Unicode 字符。
所有具有按鍵的內部(內置)輸入設備都需要特定於設備的按鍵佈局文件,如果只是為了告訴系統該設備僅用於特殊用途(不是全鍵盤)。
設備特定的按鍵佈局文件對於外部鍵盤來說是可選的,而且通常根本不需要。該系統提供了適用於許多外部鍵盤的通用鍵字符映射。
如果沒有設備特定的按鍵佈局文件可用,則係統將選擇默認值。
地點
關鍵字符映射文件按 USB 供應商、產品(和可選的版本)ID 或輸入設備名稱定位。
以下路徑依次查閱。
-
/odm/usr/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
-
/vendor/usr/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
-
/system/usr/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
-
/data/system/devices/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
-
/odm/usr/keychars/Vendor_XXXX_Product_XXXX.kcm
-
/vendor/usr/keychars/Vendor_XXXX_Product_XXXX.kcm
-
/system/usr/keychars/Vendor_XXXX_Product_XXXX.kcm
-
/data/system/devices/keychars/Vendor_XXXX_Product_XXXX.kcm
-
/odm/usr/keychars/DEVICE_NAME.kcm
-
/vendor/usr/keychars/DEVICE_NAME.kcm
-
/system/usr/keychars/DEVICE_NAME.kcm
-
/data/system/devices/keychars/DEVICE_NAME.kcm
-
/odm/usr/keychars/Generic.kcm
-
/vendor/usr/keychars/Generic.kcm
-
/system/usr/keychars/Generic.kcm
-
/data/system/devices/keychars/Generic.kcm
-
/odm/usr/keychars/Virtual.kcm
-
/vendor/usr/keychars/Virtual.kcm
-
/system/usr/keychars/Virtual.kcm
-
/data/system/devices/keychars/Virtual.kcm
構造包含設備名稱的文件路徑時,設備名稱中除 '0'-'9'、'a'-'z'、'A'-'Z'、'-' 或 '_' 之外的所有字符替換為“_”。
通用鍵字符映射文件
系統提供了一個特殊的內置鍵字符映射文件,稱為Generic.kcm
。此鍵字符映射旨在支持各種標準外部鍵盤。
不要修改通用鍵字符映射!
虛擬鍵字符映射文件
系統提供了一個特殊的內置鍵字符映射文件,稱為Virtual.kcm
,供虛擬鍵盤設備使用。
虛擬鍵盤設備是一種合成輸入設備,其 id 為 -1(請參閱KeyCharacterMap.VIRTUAL_KEYBOARD
)。它存在於從 Android Honeycomb 3.0 開始的所有 Android 設備上。虛擬鍵盤設備的目的是提供一種已知的內置輸入設備,該設備可用於通過 IME 或測試儀器將擊鍵注入應用程序,即使對於沒有內置鍵盤的設備也是如此。
假設虛擬鍵盤具有在所有設備上相同的完整 QWERTY 佈局。這使得應用程序可以使用虛擬鍵盤設備註入擊鍵並始終獲得相同的結果。
請勿修改虛擬鍵字符映射!
句法
鍵字符映射文件是由鍵盤類型聲明和一組鍵聲明組成的純文本文件。
鍵盤類型聲明
鍵盤類型聲明描述了鍵盤的整體行為。字符映射文件必須包含鍵盤類型聲明。為清楚起見,它通常放在文件的頂部。
type FULL
可識別以下鍵盤類型:
NUMERIC
:數字(12 鍵)鍵盤。數字鍵盤支持使用多次敲擊方法輸入文本。可能需要多次敲擊一個鍵來生成所需的字母或符號。
這種類型的鍵盤通常是為拇指打字而設計的。
對應於
KeyCharacterMap.NUMERIC
。PREDICTIVE
:具有所有字母的鍵盤,但每個鍵有多個字母。這種類型的鍵盤通常是為拇指打字而設計的。
對應於
KeyCharacterMap.PREDICTIVE
。ALPHA
:一個有所有字母的鍵盤,也許還有一些數字。字母鍵盤直接支持文本輸入,但可能具有緊湊的佈局和小尺寸。與
FULL
鍵盤相比,某些符號可能只能使用特殊的屏幕字符選擇器訪問。此外,為了提高打字速度和準確性,該框架為字母鍵盤提供了特殊的功能,例如自動大寫和切換/鎖定的 SHIFT 和 ALT 鍵。這種類型的鍵盤通常是為拇指打字而設計的。
FULL
:完整的 PC 風格鍵盤。全鍵盤的行為類似於 PC 鍵盤。所有符號都可以通過鍵盤上的按鍵直接訪問,無需屏幕支持或自動大寫等功能。
這種類型的鍵盤通常設計用於全雙手打字。
SPECIAL_FUNCTION
:僅用於執行系統控制功能而不是用於打字的鍵盤。特殊功能鍵盤僅包含非打印鍵,例如 HOME 和 POWER,它們實際上並不用於打字。
Generic.kcm
和Virtual.kcm
鍵字符映射都是FULL
鍵盤。
關鍵聲明
每個鍵聲明都由關鍵字key
後跟 Android 鍵代號、一個左大括號、一組屬性和行為以及一個右大括號組成。
key A { label: 'A' base: 'a' shift, capslock: 'A' ctrl, alt, meta: none }
特性
每個鍵屬性建立從鍵到行為的映射。為了使關鍵字符映射文件更緊湊,可以通過用逗號分隔多個屬性來將它們映射到相同的行為。
在上面的示例中, label
屬性被分配了'A'
行為。同樣, ctrl
、 alt
和meta
屬性都同時被指定為none
行為。
識別以下屬性:
label
:指定物理打印在鍵上的標籤,當它由單個字符組成時。這是KeyCharacterMap.getDisplayLabel
方法返回的值。number
:指定數字文本視圖具有焦點時的行為(應鍵入的字符),例如當用戶鍵入電話號碼時。緊湊型鍵盤通常將多個符號組合成一個鍵,這樣同一個鍵可能會用於鍵入
'1'
和'a'
或'#'
和'q'
。對於這些鍵,應設置number
屬性以指示應在數字上下文中鍵入哪個符號(如果有)。一些典型的“數字”符號是數字
'0'
到'9'
、'#'
、'+'
、'('
、')'
、','
和'.'
.base
:指定未按下修飾符時的行為(應鍵入的字符)。<modifier> 或 <modifier1>
+
<modifier2>+
...:指定按下鍵並且所有指定的修飾符都處於活動狀態時的行為(應鍵入的字符)。例如,修飾符屬性
shift
指定在按下 LEFT SHIFT 或 RIGHT SHIFT 修飾符時應用的行為。類似地,修飾符屬性
rshift+ralt
指定當同時按下 RIGHT SHIFT 和 RIGHT ALT 修飾符時應用的行為。
在修飾符屬性中可以識別以下修飾符:
-
shift
:當按下 LEFT SHIFT 或 RIGHT SHIFT 修飾符時應用。 -
lshift
:當按下 LEFT SHIFT 修飾符時應用。 -
rshift
:當按下 RIGHT SHIFT 修飾符時應用。 -
alt
:在按下 LEFT ALT 或 RIGHT ALT 修飾符時應用。 -
lalt
:在按下 LEFT ALT 修飾符時應用。 -
ralt
:當按下 RIGHT ALT 修飾符時應用。 -
ctrl
:當按下 LEFT CONTROL 或 RIGHT CONTROL 修飾符時應用。 -
lctrl
:當按下 LEFT CONTROL 修飾符時應用。 -
rctrl
:當按下 RIGHT CONTROL 修飾符時應用。 -
meta
:當按下 LEFT META 或 RIGHT META 修飾符時應用。 -
lmeta
:當按下 LEFT META 修飾符時應用。 -
rmeta
:當按下 RIGHT META 修飾符時應用。 -
sym
:當按下 SYMBOL 修飾符時應用。 -
fn
:當按下 FUNCTION 修飾符時應用。 -
capslock
:當 CAPS LOCK 修飾符被鎖定時應用。 -
numlock
:當 NUM LOCK 修飾符被鎖定時應用。 -
scrolllock
:當 SCROLL LOCK 修飾符被鎖定時應用。
列出屬性的順序很重要。將鍵映射到行為時,系統會按順序掃描所有相關屬性並返回它找到的最後適用的行為。
因此,稍後指定的屬性會覆蓋先前為給定鍵指定的屬性。
行為
每個屬性都映射到一個行為。最常見的行為是鍵入一個字符,但還有其他行為。
識別出以下行為:
none
:不輸入字符。此行為是未指定字符時的默認行為。指定
none
是可選的,但它可以提高清晰度。'X'
:鍵入指定的字符文字。此行為會導致將指定字符輸入到焦點文本視圖中。字符文字可以是任何 ASCII 字符,或以下轉義序列之一:
-
'\\'
:鍵入反斜杠字符。 -
'\n'
:輸入一個換行符(用於 ENTER / RETURN)。 -
'\t'
:鍵入 TAB 字符。 -
'\''
:鍵入撇號字符。 -
'\"'
:輸入引號字符。 -
'\uXXXX'
:鍵入 Unicode 字符,其代碼點由 XXXX 以十六進制形式給出。
-
fallback
<Android key code name>:如果應用程序未處理密鑰,則執行默認操作。當應用程序本身不處理指定的鍵時,此行為會導致系統模擬不同的按鍵。它用於支持並非所有應用程序都知道如何處理的新鍵的默認行為,例如 ESCAPE 或數字鍵盤鍵(當未按下 numlock 時)。
執行後備行為時,應用程序將收到兩次按鍵:一次用於原始鍵,另一次用於選擇的備用鍵。如果應用程序在 key up 期間處理原始鍵,則後備鍵事件將被取消(
KeyEvent.isCanceled
將返回true
)。
系統保留兩個 Unicode 字符來執行特殊功能:
'\uef00'
:執行此行為時,文本視圖會消耗並刪除光標前的四個字符,將它們解釋為十六進制數字,並插入相應的 Unicode 代碼點。'\uef01'
:執行此行為時,文本視圖會顯示一個包含各種符號的字符選擇器對話框。
系統將以下 Unicode 字符識別為組合變音死鍵字符:
-
'\u0300'
:重音。 -
'\u0301'
: 重音。 -
'\u0302'
: 抑揚頓挫口音。 -
'\u0303'
:波浪號重音。 -
'\u0308'
:變音符號。
當輸入一個死鍵後跟另一個字符時,死鍵和後面的字符就組成了。例如,當用戶鍵入重音死鍵後跟字母“a”時,結果為“à”。
有關死鍵處理的更多信息,請參閱KeyCharacterMap.getDeadChar
。
註釋
註釋行以“#”開頭並一直到行尾。像這樣:
# A comment!
空白行被忽略。
按鍵組合如何映射到行為
當用戶按下一個鍵時,系統會查找與該鍵按下和當前按下的修飾符的組合相關聯的行為。
SHIFT + A
假設用戶同時按下 A 和 SHIFT。系統首先定位與KEYCODE_A
關聯的一組屬性和行為。
key A { label: 'A' base: 'a' shift, capslock: 'A' ctrl, alt, meta: none }
系統從頭到尾,從左到右掃描屬性,忽略label
和number
屬性,這是特殊的。
遇到的第一個屬性是base
。無論按下什麼修飾符, base
屬性始終適用於鍵。它本質上指定鍵的默認行為,除非它被以下屬性覆蓋。由於base
屬性適用於此按鍵,因此系統會記下它的行為是'a'
(鍵入字符a
)這一事實。
然後系統繼續掃描後續屬性,以防它們中的任何一個比base
屬性更具體並覆蓋它。它遇到同樣適用於按鍵 SHIFT + A 的shift
。因此系統決定忽略base
屬性的行為並選擇與shift
屬性關聯的行為,即'A'
(鍵入字符A
)。
然後它繼續掃描表,但是沒有其他屬性適用於該鍵按下(CAPS LOCK 未鎖定,未按下 CONTROL 鍵,未按下 ALT 鍵且未按下 META 鍵)。
因此,組合鍵 SHIFT + A 的結果行為是'A'
。
控制 + A
現在考慮如果用戶同時按下 A 和 CONTROL 會發生什麼。
和以前一樣,系統會掃描屬性表。它會注意到應用了base
屬性,但也會繼續掃描,直到最終到達control
屬性。碰巧的是, control
屬性出現在base
之後,因此它的行為會覆蓋base
行為。
因此,組合鍵 CONTROL + A 的結果行為是none
。
逃脫
現在假設用戶按下了 ESCAPE。
key ESCAPE { base: fallback BACK alt, meta: fallback HOME ctrl: fallback MENU }
這次系統獲得了回退行為fallback BACK
,一種回退行為。因為沒有字符文字出現,所以不會輸入任何字符。
在處理密鑰時,系統會首先將KEYCODE_ESCAPE
傳遞給應用程序。如果應用程序沒有處理它,那麼系統將再次嘗試,但這一次它將按照回退行為的請求將KEYCODE_BACK
傳遞給應用程序。
因此,識別和支持KEYCODE_ESCAPE
的應用程序有機會按原樣處理它,但其他不支持的應用程序可以改為執行將密鑰視為KEYCODE_BACK
的回退操作。
NUMPAD_0 帶或不帶 NUM LOCK
根據 NUM LOCK 鍵是否被鎖定,數字小鍵盤的鍵有非常不同的解釋。
以下鍵聲明確保在按下 NUM LOCK 時KEYCODE_NUMPAD_0
類型0
。當 NUM LOCK 沒有被按下時,鍵像往常一樣被傳遞給應用程序,如果它沒有被處理,那麼回退鍵KEYCODE_INSERT
被傳遞。
key NUMPAD_0 { label, number: '0' base: fallback INSERT numlock: '0' ctrl, alt, meta: none }
正如我們所看到的,回退鍵聲明極大地提高了與舊應用程序的兼容性,這些舊應用程序不能識別或直接支持完整 PC 風格鍵盤上的所有鍵。
例子
全鍵盤
# This is an example of part of a key character map file for a full keyboard # include a few fallback behaviors for special keys that few applications # handle themselves. type FULL key C { label: 'C' base: 'c' shift, capslock: 'C' alt: '\u00e7' shift+alt: '\u00c7' ctrl, meta: none } key SPACE { label: ' ' base: ' ' ctrl: none alt, meta: fallback SEARCH } key NUMPAD_9 { label, number: '9' base: fallback PAGE_UP numlock: '9' ctrl, alt, meta: none }
字母數字鍵盤
# This is an example of part of a key character map file for an alphanumeric # thumb keyboard. Some keys are combined, such as `A` and `2`. Here we # specify `number` labels to tell the system what to do when the user is # typing a number into a dial pad. # # Also note the special character '\uef01' mapped to ALT+SPACE. # Pressing this combination of keys invokes an on-screen character picker. type ALPHA key A { label: 'A' number: '2' base: 'a' shift, capslock: 'A' alt: '#' shift+alt, capslock+alt: none } key SPACE { label: ' ' number: ' ' base: ' ' shift: ' ' alt: '\uef01' shift+alt: '\uef01' }
遊戲手柄
# This is an example of part of a key character map file for a game pad. # It defines fallback actions that enable the user to navigate the user interface # by pressing buttons. type SPECIAL_FUNCTION key BUTTON_A { base: fallback BACK } key BUTTON_X { base: fallback DPAD_CENTER } key BUTTON_START { base: fallback HOME } key BUTTON_SELECT { base: fallback MENU }
兼容性說明
在 Android Honeycomb 3.0 之前,Android 鍵字符映射使用非常不同的語法指定,並在構建時編譯為二進製文件格式 ( .kcm.bin
)。
儘管新格式使用相同的擴展名.kcm
,但語法完全不同(而且功能更強大)。
從 Android Honeycomb 3.0 開始,所有 Android 鍵字符映射文件都必須使用本文檔中描述的新語法和純文本文件格式。不支持舊語法並且系統無法識別舊的.kcm.bin
文件。
語言註釋
Android 目前不支持多語言鍵盤。此外,內置的通用鍵字符映射採用美國英語鍵盤佈局。
如果 OEM 是為其他語言設計的,則鼓勵 OEM 為其鍵盤提供自定義鍵字符映射。
未來的 Android 版本可能會更好地支持多語言鍵盤或用戶可選擇的鍵盤佈局。
驗證
確保使用Validate Keymaps工具驗證您的關鍵字符映射文件。