开发过程中免不得需要增加或减少按键码值,在android2.3系统事件处理部分,主要向上层提供统一的按键码(KeyCode),这个按键码是一个整数,在上层的JAVA程序中主要通过这个值来判断系统的实现。 这里主要讲android事件的处理过程,需要经过两个转换步骤: ?? 1、键扫描码ScanCode是由linux的Input驱动框架定义的整数类型,可参考input.h头文件 在步骤一中将其值转换成表示按键的字符串 键盘布局文件(*.kl)将完成第一步的转换,放在/system/usr/keylayout/下面 举例如下: input.h 中字母键定义: #define KEY_Q 16 #define KEY_W 17 #define KEY_E 18 #define KEY_R 19 #define KEY_T 20 #define KEY_Y 21 #define KEY_U 22 #define KEY_I 23 #define KEY_O 24 #define KEY_P 25 而qwert.kl中定义如下: ScanCode + 字符串值 key 16 Q key 17 W key 18 E key 19 R key 20 T key 21 Y key 22 U key 23 I key 24 O key 25 P 2、通过查找KEYCODES数组,将literal字符串转换成value的整型值,即转换到KeyCode值了 片段如下,右边的值是android系统中使用的KeyCode值:(文件路径:frameworks/base/include/ui/KeycodeLabels.h) static const KeycodeLabel KEYCODES[] = { ... { "A", 29 }, { "B", 30 }, { "C", 31 }, { "D", 32 }, { "E", 33 }, { "F", 34 }, { "G", 35 }, { "H", 36 }, { "I", 37 }, { "J", 38 }, { "K", 39 }, { "L", 40 }, { "M", 41 }, { "N", 42 }, { "O", 43 }, { "P", 44 }, { "Q", 45 }, { "R", 46 }, { "S", 47 }, { "T", 48 }, { "U", 49 }, { "V", 50 }, { "W", 51 }, { "X", 52 }, { "Y", 53 }, { "Z", 54 }, ... }; 右边的值在android中定义如下:(文件路径:frameworks/base/include/android/keycodes.h) /* * Key codes. */ enum { AKEYCODE_A = 29, AKEYCODE_B = 30, AKEYCODE_C = 31, AKEYCODE_D = 32, AKEYCODE_E = 33, AKEYCODE_F = 34, AKEYCODE_G = 35, AKEYCODE_H = 36, AKEYCODE_I = 37, AKEYCODE_J = 38, AKEYCODE_K = 39, AKEYCODE_L = 40, AKEYCODE_M = 41, AKEYCODE_N = 42, AKEYCODE_O = 43, AKEYCODE_P = 44, AKEYCODE_Q = 45, AKEYCODE_R = 46, AKEYCODE_S = 47, AKEYCODE_T = 48, AKEYCODE_U = 49, AKEYCODE_V = 50, AKEYCODE_W = 51, AKEYCODE_X = 52, AKEYCODE_Y = 53, AKEYCODE_Z = 54, .. }; 这里的键值与KeyEvent.java中的值是对应的:(文件路径:frameworks/base/core/java/android/view/KeyEvent.java) /** Key code constant: 'A' key. */ public static final int KEYCODE_A = 29; /** Key code constant: 'B' key. */ public static final int KEYCODE_B = 30; /** Key code constant: 'C' key. */ public static final int KEYCODE_C = 31; /** Key code constant: 'D' key. */ public static final int KEYCODE_D = 32; /** Key code constant: 'E' key. */ public static final int KEYCODE_E = 33; /** Key code constant: 'F' key. */ public static final int KEYCODE_F = 34; /** Key code constant: 'G' key. */ public static final int KEYCODE_G = 35; /** Key code constant: 'H' key. */ public static final int KEYCODE_H = 36; /** Key code constant: 'I' key. */ public static final int KEYCODE_I = 37; /** Key code constant: 'J' key. */ public static final int KEYCODE_J = 38; /** Key code constant: 'K' key. */ public static final int KEYCODE_K = 39; /** Key code constant: 'L' key. */ public static final int KEYCODE_L = 40; /** Key code constant: 'M' key. */ public static final int KEYCODE_M = 41; /** Key code constant: 'N' key. */ public static final int KEYCODE_N = 42; /** Key code constant: 'O' key. */ public static final int KEYCODE_O = 43; /** Key code constant: 'P' key. */ public static final int KEYCODE_P = 44; /** Key code constant: 'Q' key. */ public static final int KEYCODE_Q = 45; /** Key code constant: 'R' key. */ public static final int KEYCODE_R = 46; /** Key code constant: 'S' key. */ public static final int KEYCODE_S = 47; /** Key code constant: 'T' key. */ public static final int KEYCODE_T = 48; /** Key code constant: 'U' key. */ public static final int KEYCODE_U = 49; /** Key code constant: 'V' key. */ public static final int KEYCODE_V = 50; /** Key code constant: 'W' key. */ public static final int KEYCODE_W = 51; /** Key code constant: 'X' key. */ public static final int KEYCODE_X = 52; /** Key code constant: 'Y' key. */ public static final int KEYCODE_Y = 53; /** Key code constant: 'Z' key. */ public static final int KEYCODE_Z = 54; ... 如果改动了这里,影响到API则需要调用make update-api ok,理清楚了以上的转换关系,下面就说一下如何增加按键,以增加gamekey为例: 1 、键盘布局文件中增加键,一般是qwery.kl (一定是以*.kl结尾的文件): key 304 BUTTON_A key 305 BUTTON_B key 306 BUTTON_C key 307 BUTTON_X key 308 BUTTON_Y key 309 BUTTON_Z key 315 BUTTON_START key 316 BUTTON_MODE 2、在frameworks/base/include/ui/KeycodeLabels.h中增加KeycodeLabel类型的Code数组 { "BUTTON_A", 96 }, { "BUTTON_B", 97 }, { "BUTTON_C", 98 }, { "BUTTON_X", 99 }, { "BUTTON_Y", 100 }, { "BUTTON_Z", 101 }, { "BUTTON_START", 108 }, { "BUTTON_MODE", 110 }, 目前的2.3系统已经添加 3、在frameworks/base/include/android/keycodes.h中增加KeyCode的枚举值 AKEYCODE_BUTTON_A = 96, AKEYCODE_BUTTON_B = 97, AKEYCODE_BUTTON_C = 98, AKEYCODE_BUTTON_X = 99, AKEYCODE_BUTTON_Y = 100, AKEYCODE_BUTTON_Z = 101, AKEYCODE_BUTTON_START = 108, AKEYCODE_BUTTON_MODE = 110, 目前的2.3系统已经添加 4、JAVA层的keyEvent.java中增加用于java应用程序使用 略,目前的2.3系统已经添加 5、在frameworks\base\core\res\res\values\attrs.xml中增加表示属性的资源文件,添加相应用name="keycode"的attr
ok,完成以上步骤应该就可以使用了。
查找key是否有没有被过滤掉重点确认的地方:
1、EventHub.cpp 文件中的getEvent函数
if (iev.type == EV_KEY) { status_t err = device->layoutMap->map(iev.code, & outEvent->keyCode, & outEvent->flags); LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n", iev.code, outEvent->keyCode, outEvent->flags, err); if (err != 0) { outEvent->keyCode = AKEYCODE_UNKNOWN; outEvent->flags = 0; }
}
确认这里转换是否ok了,如果没有则可能*.kl文件中没有添加进去这个键值
2、InputReader.cpp文件中的KeyboardInputMapper处理函数process
void KeyboardInputMapper::process(const RawEvent* rawEvent) { switch (rawEvent->type) { case EV_KEY: { int32_t scanCode = rawEvent->scanCode; if (isKeyboardOrGamepadKey(scanCode)) { processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode, rawEvent->flags); } break; } } } bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) { return scanCode < BTN_MOUSE || scanCode >= KEY_OK || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI); }
可以在processKey中加打印,确认已通过notifyKey上报键值给android系统了。
附加,如何编译生成qwerty.kcm.bin 文件:
android为了减少载入时间,并没有使用原始按键表文件,而是将其转换成二进制文件 转换的工具源代码在android源代码build/tools/kcm目录下,android在编译过程中会 首先编译转换工具,然后利用转换工具将qwerty.kcm文件转换成qwerty.kcm.bin
转换后的二进制文件复制到out/target/product//system/usr/keychars 目录下,也就是目标平台的/system/usr/keychars目录中。
用法:
static int usage() { fprintf(stderr, "usage: kcm INPUT OUTPUT\n" "\n" "INPUT keycharmap file\n" "OUTPUT compiled keycharmap file\n" ); return 1; }
|