Android鍵盤輸出增加按鍵碼
開發過程中免不得需要增加或減少按鍵碼值,在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目錄中。
用法:
static int usage()
{
fprintf(stderr,
"usage: kcm INPUT OUTPUT\n"
"\n"
"INPUT keycharmap file\n"
"OUTPUT compiled keycharmap file\n"
);
return 1;
}