您的位置:首页 > 移动开发 > Android开发

android键盘输出增加按键码

2011-12-31 18:04 316 查看
开发过程中免不得需要增加或减少按键码值,在android2.3系统事件处理部分,主要向上层提供统一的按键码(KeyCode),这个按键码是一个整数,在上层的J***A程序中主要通过这个值来判断系统的实现。

关于输入事件的处理前面已经讲过,请参考:/article/1341941.html

这里主要讲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、J***A层的keyEvent.java中增加用于java应用程序使用


略,目前的2.3系统已经添加

5、在frameworks\base\core\res\res\values\attrs.xml中增加表示属性的资源文件,添加相应用name="keycode"的attr

<enum name="KEYCODE_BUTTON_A" value="96" />

<enum name="KEYCODE_BUTTON_B" value="97" />

<enum name="KEYCODE_BUTTON_C" value="98" />

<enum name="KEYCODE_BUTTON_X" value="99" />

<enum name="KEYCODE_BUTTON_Y" value="100" />

<enum name="KEYCODE_BUTTON_Z" value="101" />

<enum name="KEYCODE_BUTTON_START" value="108" />

<enum name="KEYCODE_BUTTON_MODE"
value="110" />

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/<board_name>/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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: