触摸屏和轨迹球上报的是坐标、按下、抬起等信息,信息量比较少。按键处理的过程稍微复杂,从驱动程序到Android的Java层受到的信息,键表示方式经过了两次转化,如图8-4所示。
键扫描码Scancode是由Linux的Input驱动框架定义的整数类型。键扫描码Scancode经过一次转化后,形成按键的标签KeycodeLabel,是一个字符串的表示形式。按键的标签KeycodeLabel经过转换后,再次形成整数型的按键码keycode。在Android应用程序层,主要使用按键码keycode来区分。
在本地框架层libui的头文件中KeycodeLabels.h,按键码为整数值的格式,其定义KeyCode(枚举值)如下所示:
进而在定义了KeycodeLabels.h中定义了从字符串到整数的映射关系,数组KEYCODES,定义如下所示:
数组KEYCODES表示的映射关系,左列的内容即表示按键标签KeyCodeLabel,右列的内容为按键码KeyCode(与KeyCode的数值对应)。实际上,在按键信息第二次转化的时候就是将字符串类型KeyCodeLabel转化成整数的KeyCode。
KeycodeLabel的Flags的定义如下所示:
KeycodeLabel表示按键的附属标识。
提示:frameworks/base/core/Java/android/view/KeyEvent.Java中定义了类android.view. KeyEvent类,其中定义整数类型的数值与KeycodeLabels.h中定义的KeyCode枚举值是对应的。
在本地框架层libui的头文件中KeyCharacterMap.h,定义了按键的字符映射关系,KeyCharacterMap类的定义如下所示:
KeyCharacterMap用于将按键的码映射为文本可识别的字符串(例如,显示的标签等)。KeyCharacterMap是一个辅助的功能:由于按键码只是一个与UI无关整数,通常用程序对其进行捕获处理,然而如果将按键事件转换为用户可见的内容,就需要经过这个层次的转换了。
KeyCharacterMap需要从本地层传送到Java层,JNI的代码路径如下所示:
frameworks/base/core/jni/android_text_KeyCharacterMap.cpp
KeyCharacterMap Java框架层次的代码如下所示:
frameworks/base/core/Java/android/view/KeyCharacterMap.Java
android.view.KeyCharacterMap类是Android平台的API可以在应用程序中使用这个类。
android.text.method中有各种Linstener,可以之间监听KeyCharacterMap相关的信息。DigitsKeyListener NumberKeyListener TextKeyListener。
以上关于按键码和按键字符映射的内容是在代码中实现的内容,还需要配合动态的配置文件来使用。在实现Android系统的时候,有可能需要更改这两种文件。
动态的配置文件包括:
KL(Keycode Layout):后缀名为kl的配置文件
KCM(KeyCharacterMap):后缀名为kcm的配置文件
Donut及其之前配置文件的路径为:
development/emulator/keymaps/
Eclair及其之后配置文件的路径为:
sdk/emulator/keymaps/
这些配置文件经过系统生成后,将被放置在目标文件系统的/system/usr/keylayout/目录或者/system/usr/keychars/目录中。
提示:kl文件将被直接复职到目标文件系统中;由于尺寸较大,kcm文件放置在目标文件系统中之前,需要经过压缩处理。KeyLayoutMap.cpp负责解析处理kl文件,KeyCharacterMap.cpp负责解析kcm文件。