怎么看android底层源码,Android 底层按键获取

本文详细介绍了Android系统如何处理底层按键输入,包括按键的转换过程,从Linux的input_event结构体到Android的RawEvent结构体的转换,并探讨了Linux层获取事件的原理。通过读取并解析/dev/input/event0设备,展示了如何捕获和处理按键事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

与用户交互的输入设备(触摸屏,键盘等)是获取用户意图的来源。由于硬件本身的物理特性及由各大硬件厂商的标准不一,这将导致我们从设备上获取到的键值存在一定的差异性,为了让系统能够正确处理用户的操作,我们就必须将从输入设备上获取到的键值正确转换为Android系统定义的键值以便正确处理。

二、Android中按键输入转换过程

0818b9ca8b590ca3270a3433284dd417.png

扫描键码Scancode是由Linux 的input驱动定义的整形类型,扫描键码根据读取的kl配置文档内容的转化后,形成按键的标签KeycodeLaybel。按键的标签在经过数组KEYCODES的转换后形成keycode。应用程序对keycode进行处理。

Android默认提供的按键布局文件主要包括qwerty.kl 和AVRCP.kl(/system/usr/keylayout/目录下)。Qwerty.kl为全键盘的布局文件,是系统中默认使用的布局文件,AVRCP.kl用于多媒体控制。

三、Linux中按键定义的数据结构

3.1 Linux中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.2 Android RawEvent结构体

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

static int event0_fd = -1;

struct input_event ev0[64];

//for handling event0, mouse/key/ts

static int handle_event0() {

int i, rd;

rd = read(event0_fd, ev0, sizeof(struct input_event) * 64);

if ( rd < sizeof(struct input_event) ) return 0;

for (i = 0; i < rd / sizeof(struct input_event); i++) {

printf("", ev0[i].type, ev0[i].code, ev0[i].value);

if (ev0[i].type == 3 && ev0[i].code == 0)

{

//realx = ev0[i].value;

printf("Touch event: X Value: %3d;\n",ev0[i].value);

}

else if (ev0[i].type == 3 && ev0[i].code == 1)

{

//realy = ev0[i].value;

printf("Touch event: Y Value: %3d;\n",ev0[i].value);

}

else if (ev0[i].type == 1&& ev0[i].value == 0) {

//realy = ev0[i].value;

printf("Key event: Key: %3d Up;\n",ev0[i].code);

}else if (ev0[i].type == 1&& ev0[i].value == 1) {

//realy = ev0[i].value;

printf("Key event: Key: %3d Down;\n",ev0[i].code);

} else if (ev0[i].type == 2) {

printf("Ball event: Type: %3d;\n",ev0[i].type);

}

else if(ev0[i].type == 0 && ev0[i].code == 0 && ev0[i].value == 0) {

printf("EV_SYN;\n");

}

}

return 1;

}

int main(void) {

int done = 1;

//printf("sizeof(struct input_event) = %d\n", sizeof(struct input_event));

printf("GetEvent Running;\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;

}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值