|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
×
Android键盘系统——改变按键功能(1)交换两个按键的功能
改变按键的功能最简单的方法就是交换俩个按键的功能。在做这项测试之前,先分析一下键盘布局文件和按键的原理。在明白这些之后,你就会发现只是如此的简单。
从键盘布局文件截取一部分类容:
Key 2 1
Key 158 BACK WAKE_DROPPED
其中,第二列是一个整数值,表示驱动程序中Event事件的名称。我们可以这么理解,2表示Event事件2。即当我们按下一个键时,就会有相应的中断产生,并且这个中断号是已知的。
在input.c中定义了输入设备的数据结构:其中
struct event_dev {
struct input_dev *input;
int irq;
unsigned addr;
char name[0];
};
#define KEY_BACK 158
在这个结构体中保存着中断号的信息以及另外一个非常的结构体:struct input_dev *input;。
struct input_dev *input;这个结构体的数据结构很庞大,包含的信息量很多。其中有:
struct input_id id;
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; //区分哪中输入设备
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; //按键与按钮
unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;
int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
//以上是几个与键盘关系较密切的几个成员。,
#define KEY_BACK 158
表示的意思是事件码158(scancode)对应的字符串为KEY_BACK。Android的输入处理经过了两次映射,第一次就是将事件码映射成字符串。这个与键盘布局文件中的内容是一致的。
第二次将该字符串映射成Java的UI程序中使用的整数值(keycode)。keycode是怎么取得的呢?
在驱动层以上的KeyEvent.java中,有一个KEYCODES映射表,与KEY_BACK对应的是:
Public static final int KEYCODEA_BACK = 4;
在驱动层,有一个向用户态提供的接口:ioctl();
当ioctl()的命令参数为:EVIOCGKEYCODE时,驱动层函数的调用过程如下:
对于驱动层来说,哪一个键按下产生的中断是不变的(每一个按键的scancode一定),但scancode对应的字符串我们可以在键盘布局文件中修改,一旦在布局文件进行这样的修改,而KEYCODES映射表及其它内容保持不变的话,scancode对应的KEYCODE会发生变化:
修改前:
Key 2 1
Key 158 BACK WAKE_DROPPED
scancode(2)-------------ltteral(1) -------------KEYCODE(8)
scancode(158)----------ltteral(BACK) ------KEYCODE(4)
修改后:
Key 2 BACK WAKE_DROPPED
Key 158 1
scancode(2)----------------ltteral(BACK) ------KEYCODE(4)
scancode(158)-------------ltteral(1) -------------KEYCODE(8)
我们可以看到,在这种情况下,红色部分的对应关系没有变,即没有对KEYCODES映射表进行修改。而前部分对应关系改变是对键盘映射文件内容进行修改的结果。
经过这样简单的修改,就将“1”和“返回”键的功能互换了——按下“1”则能返回。但从模拟器日志打印信息可以看到,这两个键的scancode是没有发生变化的。
原帖地址http://hi.baidu.com/gengjie/item/28bd3226e61d85c9a4275a6e
新的,好像要编译,不会啊,H大,帮忙编译个吧
3.按键功能添加:
对keypad来说,以SAR为例涉及到的有以下几个:
1.首先在*.kl文件中,添加新的键值信息:Example: key 100 MEDIA_PLAY_PAUSE ,把100定义到input.h中#define KEY_PLAYPAUSE 100
注意:新加的键值不要与已有的重复。
2. ./kernel/drivers/**/input/Adc_keypad.c驱动对应的board-8726m-refc03.c中的
adc_kp_key[]对应的键位添加自定义的键码 如 :{KEY_PLAYPAUSE , "playpause", CHAN_5, 419, 60},
3. ./frameworks/base/include/ui/keycodeLabels.h
在数组static const KeycodeLabel KEYCODES[] 中添加 新定义的信息
{ "PLAYPAUSE", 120 },
4. ./ frameworks/base/native/include/android/Keycodes.h
枚举类型 中添加
AKEYCODE_PLAYPAUSE = 120
5. ./frameworks/base/core/res/res/values/attrs.xml
<enum name="KEYCODE_BUTTON_PLAYPAUSE" value="120"/>
6. ./frameworks/base/core/java/android/view/KeyEvent.java
public static final int KEYCODE_PLAYPAUSE = 120;
注意:要修改为 private static final int LAST_KEYCODE = KEYCODE_PLAYPAUSE;
7. ./frameworks/base/libs/ui/input.java
在bool KeyEvent::isSystemKey(int32_t keyCode)()中,同样需要添加:
case AKEYCODE_PLAYPAUSE:
8. 通过以上的更改,新的键值就添加上去了,注意上面标红色的数字表示必须相同的,另外由于更改了 KeyEvent,影响到了API, 所以需要make update-api
如果对新键值进行处理,可以通过获取相应的keycode,对它进行处理;对于按键事件的处理一般如下文件中
frameworks/policies/base/phone/com/android/internal/policy/impl /PhoneWindowManager.java,综上可知,我们可以根据需求定义自己的键值,并对键值所对应的事件信息进行合理化处理。
补充: 在写程序时,需要捕获KEYCODE_HOME、KEYCODE_ENDCALL、KEYCODE_POWER这几个按键,但是这几个按键系统做了特殊处 理,在进行dispatch之前做了一些操作,HOME除了Keygaurd之外,不分发给任何其他APP,ENDCALL和POWER也类似,应用程序 在View和Activity的onKeyDown/Up中是监听不到的,所以需要我们系统处理之前进行处理,我的做法是自己定义一个FLAG,在自己的 程序中添加此FLAG,然后在WindowManagerServices.java中获取当前窗口的FLAG属性,如果是我们自己设置的那个FLAG, 则不进行特殊处理,直接分发按键消息到我们的APP当中,由APP自己处理。这部分代码最好添加在
@Override
boolean preprocessEvent(InputDevice device, RawInputEvent event)方法中,这个方法是KeyInputQueue中的一个虚函数,在处理按键事件之前的一个“预处理”。
注意:对HOME键的处理好像必需要修改PhoneWindowManager.java中的interceptKeyTi方法,具体可以参考对KeyGuard程序的处理。
|
|