底层按键程序Android版.docx
《底层按键程序Android版.docx》由会员分享,可在线阅读,更多相关《底层按键程序Android版.docx(7页珍藏版)》请在冰点文库上搜索。
![底层按键程序Android版.docx](https://file1.bingdoc.com/fileroot1/2023-6/15/df61d025-5bd6-4ec8-85ec-ba273401cedb/df61d025-5bd6-4ec8-85ec-ba273401cedb1.gif)
底层按键程序Android版
一、Android中按键为什么需要进行转换?
与用户交互的输入设备(触摸屏,键盘等)是获取用户意图的来源。
由于硬件本身的物理特性及由各大硬件厂商的标准不一,这将导致我们从设备上获取到的键值存在一定的差异性,为了让系统能够正确处理用户的操作,我们就必须将从输入设备上获取到的键值正确转换为Android系统定义的键值以便正确处理。
二、Android中按键输入转换过程
扫描键码Scancode是由Linux 的input驱动定义的整形类型,扫描键码根据读取的kl配置文档内容的转化后,形成按键的标签KeycodeLaybel。
按键的标签在经过数组KEYCODES的转换后形成keycode。
应用程序对keycode进行处理。
Android默认提供的按键布局文件主要包括qwerty.kl 和AVRCP.kl(/system/usr/keylayout/目录下)。
Qwerty.kl为全键盘的布局文件,是系统中默认使用的布局文件,AVRCP.kl用于多媒体控制。
三、Linux中按键定义的数据结构
3.1Linux中input_event结构体
(定义按键在 linux/input.h中)
struct input_event {
struct timeval time; //按键时间
__u16 type; //类型,在下面有定义
__u16 code; //要模拟成什么按键
__s32 value;//是按下还是释放
};
1、Code
事件的代码.如果事件的类型代码是EV_KEY,该代码code为设备键盘代码.
代码值0~127为键盘上的按键代码,0x110~0x116 为鼠标上按键代码,
其中0x110(BTN_ LEFT)为鼠标左键,
0x111(BTN_RIGHT)为鼠标右键,
0x112(BTN_ MIDDLE)为鼠标中键.
如果事件的类型代码是EV_REL,code值表示轨迹的类型.如指示鼠标的X轴方向REL_X(代码为0x00),指示鼠标的Y轴方向REL_Y(代码 为0x01),指示鼠标中轮子方向REL_WHEEL(代码为0x08).
其它代码含义请参看include/linux/input.h文件.
2、Type
/*Event types参考值*/
#define EV_SYN 0x00
#define EV_KEY 0x01 //按键 常用的用红色标记出来
#define EV_REL 0x02 //相对坐标(轨迹球)
#define EV_ABS 0x03 //绝对坐标(鼠标)
#define EV_MSC 0x04 //其他
#define EV_SW 0x05
#define EV_LED 0x11 //LED
#define EV_SND 0x12//声音
#define EV_REP 0x14//repeat
#define EV_FF 0x15
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
3、Value
事件的值.如果事件的类型代码是EV_KEY,当按键按下时值为1,松开时值为0;
如果事件的类型代码是EV_ REL,value的正数值和负数值分别代表两个不同方向的值.
3.2AndroidRawEvent结构体
Android中将从底层获取到的按键按照一定规则处理后,用如下结构描述:
/* A raw event as retrieved from the EventHub.*/
struct RawEvent {
nsecs_t when; //时间
int32_t deviceId; //设备ID
int32_t type; //类型,Keyboard、 TouchScreen、TraceBall
int32_t scanCode; //扫描键码
int32_t keyCode; //按键码
int32_t value;
uint32_t flags;
};
四、Linux层获取event的原理
对eventX进行read/write来抓取event的各种信息;
1、打开event设备
event0_fd = open(“/dev/input/event0”, O_RDWR);
2、read设备
rd = read(event0_fd, &event0, sizeof(struct input_event) * 64);
3、判断事件类型
如果,(event[i].type == 3 && event[i].code == 0),为鼠标位置的x坐标值;
(event[i].type == 3 && event[i].code == 1),为鼠标位置的y坐标值;
如果,(event[i].type == 1 && event[i].value == 1),为按下key;
(event[i].type == 1 && event[i].value == 0),为松开key;
如果,(event[i].type == 其它事件(如轨迹球...声音控制...))
具体见源码。
4、保存键值
保存您想要的键盘值,(相对/绝对)x,y的值。
5、键盘映射
由于Android输入处理经过那两次映射;
1、事件码(input.h定义的键盘值)------------------------------------>字符串;
2、字符串--------------->Android中java的UI程序中自定义的键盘key;
由于有键盘映射关系,而我们想要的值是Android中java 的 Ui自定义值;为此我在代码中自定义了一个数组,用来进行事件码和java的UI程序中自定义的键盘key进行转换。
五、源码
#include
#include
#include
#include
staticintevent0_fd=-1;
structinput_eventev0[64];
//forhandlingevent0,mouse/key/ts
staticinthandle_event0(){
inti,rd;
rd=read(event0_fd,ev0,sizeof(structinput_event)*64);
if(rdfor(i=0;iprintf("",ev0[i].type,ev0[i].code,ev0[i].value);
if(ev0[i].type==3&&ev0[i].code==0)
{
//realx=ev0[i].value;
printf("Touchevent:
XValue:
%3d;\n",ev0[i].value);
}
elseif(ev0[i].type==3&&ev0[i].code==1)
{
//realy=ev0[i].value;
printf("Touchevent:
YValue:
%3d;\n",ev0[i].value);
}
elseif(ev0[i].type==1&&ev0[i].value==0){
//realy=ev0[i].value;
printf("Keyevent:
Key:
%3dUp;\n",ev0[i].code);
}elseif(ev0[i].type==1&&ev0[i].value==1){
//realy=ev0[i].value;
printf("Keyevent:
Key:
%3dDown;\n",ev0[i].code);
}elseif(ev0[i].type==2){
printf("Ballevent:
Type:
%3d;\n",ev0[i].type);
}
elseif(ev0[i].type==0&&ev0[i].code==0&&ev0[i].value==0){
printf("EV_SYN;\n");
}
}
return1;
}
intmain(void){
intdone=1;
//printf("sizeof(structinput_event)=%d\n",sizeof(structinput_event));
printf("GetEventRunning;\n");
event0_fd=open("/dev/input/event0",O_RDWR);
if(event0_fd<0)
return-1;
while(done){
done=handle_event0();
}
if(event0_fd>0){
close(event0_fd);
event0_fd=-1;
}
return0;
}