按键字符映射文件

按键字符映射文件(.kcm 文件)负责将 Android 按键代码与修饰符的组合映射到 Unicode 字符。

如果只是告诉系统该设备仅用于特殊用途(非全键盘),那么对于具有按键的所有内部(内置)输入设备,特定于设备的按键布局文件必不可少

对于外部键盘,特定于设备的按键布局文件为可选项,并且通常根本不需要。系统会提供适用于许多外部键盘的通用按键字符映射。

如果没有提供特定于设备的按键布局文件,系统将选择默认按键布局文件。

位置

按键字符映射文件可以通过 USB 供应商、产品(和可选版本)ID 或输入设备名称进行定位。

按上述顺序查阅以下路径。

  • /system/usr/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
  • /system/usr/keychars/Vendor_XXXX_Product_XXXX.kcm
  • /system/usr/keychars/DEVICE_NAME.kcm
  • /data/system/devices/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
  • /data/system/devices/keychars/Vendor_XXXX_Product_XXXX.kcm
  • /data/system/devices/keychars/DEVICE_NAME.kcm
  • /system/usr/keychars/Generic.kcm
  • /data/system/devices/keychars/Generic.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.kcmVirtual.kcm 按键字符映射都是 FULL 键盘。

按键声明

按键声明包括关键字 key,后跟 Android 按键代码名称、左大括号、一组属性和行为以及一个右大括号。

key A {
    label:                              'A'
    base:                               'a'
    shift, capslock:                    'A'
    ctrl, alt, meta:                    none
}

属性

每个按键属性都会建立从按键到行为的映射。为了使按键字符映射文件更加紧凑,可以将多个属性(用逗号分隔)映射到同一个行为。

在上面的例子中,label 属性被分配了 'A' 行为。同样,ctrlaltmeta 属性同时被分配了 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':按照 XXXX 格式输入以十六进制形式提供代码点的 Unicode 字符。
  • fallback <Android 按键代码名称>:如果应用未处理该按键,则执行默认操作。

    当应用本身不处理指定的按键时,此行为会导致系统模拟不同的按键。它用于支持并非所有应用都知道如何处理的新按键的默认行为,例如 ESCAPE 或数字小键盘按键(在未按下 numlock 时)。

    当执行回退行为时,应用将收到两个按键:一个用于原始键,另一个用于所选的回退键。如果应用在松开按键期间处理原始键,则后退键事件将被取消(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
}

系统按从头到尾、从左到右的顺序扫描属性,但会忽略 labelnumber 这两个特殊属性。

遇到的第一个属性是 base。无论按哪个修饰符,base 属性始终会应用于按键。它主要是指定按键的默认行为,除非它被后续属性所替换。由于 base 属性会应用于此按键,因此系统会记录其行为为 'a'(输入字符 a)的事实。

系统继续扫描后续属性,如果其中出现任何比 base 更具体的属性,则会进行替换。这时,系统遇到也会应用于按键 SHIFT + A 的 shift。因此,系统决定忽略 base 属性的行为,并选择与 shift 属性关联的行为,即 'A'(输入字符 A)。

系统继续扫描上述表格,但是没有其他属性会应用于此按键(CAPS LOCK 未锁定,CONTROL 键、ALT 键和 META 键均未按下)。

因此,按键组合 SHIFT + A 生成的行为是 'A'

CONTROL + A

现在考虑一下,如果用户一起按下 A 和 CONTROL 将会发生什么。

如前所述,系统将扫描属性表。系统会注意到应用的 base 属性,但仍将继续扫描,直到它最终达到 control 属性。恰巧的是,control 属性出现在 base 之后,因此其行为会替换 base 行为。

因此,CONTROL + A 组合键生成的行为是 none

ESCAPE

现在假设用户按下 ESCAPE。

key ESCAPE {
    base:                               fallback BACK
    alt, meta:                          fallback HOME
    ctrl:                               fallback MENU
}

这次系统获得行为 fallback BACK,这是一种回退行为。因为没有字符文字出现,所以不会输入字符。

处理按键时,系统将首先向应用传递 KEYCODE_ESCAPE。如果应用未处理它,系统将再次尝试,但这次它将按照回退行为的要求向应用传递 KEYCODE_BACK

因此,识别和支持 KEYCODE_ESCAPE 的应用有机会按原样处理它,但是其他应用不能替代执行处理该键的回退操作,就像它是 KEYCODE_BACK 一样。

带有或不带 NUM LOCK 的 NUMPAD_0

根据 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) 为其键盘提供自定义按键字符映射。

未来版本的 Android 可能会为多语言键盘或用户可选型键盘布局提供更好的支持。

验证

请务必使用验证按键映射工具验证您的按键字符映射文件。