android 使用uinput模拟输入设备的方法
在google remote中,android接收端接收socket发来的IR CODE,然后将IR CODE模拟出来发给系统处理,这就是google remote接收端的原理。
系统端怎样模拟input event呢?
方法一:通过Instrumentation.sendKeyDownUpSync 实现,简单使用但是问题在于sendKeyDownUpSync发出的event,无法运行到
interceptKeyBeforeDispatching,也就无法正常作用 HOME,VOL...
方法二:通过uinput桥接;原理是利用内核现有的uinput驱动,通过内核驱动uinput来发送input event,而且还容易使用kl,kcm 客制化;
经过比较方法二较优,下面就就给出方法二的测试代码...
1、main函数,setup_uinput_device 完成设备的注册,然后创建一个线程 VirtualInputDev_EventThread,该线程重复发出keycode;
int main()
{
printf("Enter process !!!! \n");
stVirtualInputDevData *pKpdData = (stVirtualInputDevData*) malloc(sizeof(stVirtualInputDevData));
pKpdData->min_keycode = umin_keycode;
pKpdData->max_keycode = umax_keycode;
if (setup_uinput_device(pKpdData) < 0) {
printf("Unable to find uInput device\n");
free(pKpdData);
return -1;
}
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (0 != pthread_create(&keypad_EventThreadId, &attr, VirtualInputDev_EventThread, (void *)0)) {
printf("Create KeypadEventThread Failed!!\n");
exit(1);
}
// Coverity server need set to ignore this.
while (1) {
usleep(1000000); // sleep 1 second
}
free(pKpdData);
pKpdData = 0;
// Destroy the device
ioctl(uinp_fd, UI_DEV_DESTROY);
close(uinp_fd);
return 0;
}
2、setup_uinput_device函数,完成设备注册;可以看到是直接打开uinput节点,设置了虚拟设备的name,verdor,product,bustype,
最后通过ioctl(uinp_fd, UI_DEV_CREATE)注册设备
int setup_uinput_device(stVirtualInputDevData* mstVirtualInputDevData)
{
struct uinput_user_dev uinp; // uInput device structure
int i;
// Open the input device
uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
if (uinp_fd == 0) {
printf("Unable to open /dev/uinput\n");
return -1;
}
// Intialize the uInput device to NULL
memset(&uinp, 0x00, sizeof(uinp));
strncpy(uinp.name, "virtualinputdev", sizeof(uinp.name)-1);
uinp.id.vendor = 0x1341;
uinp.id.product = 0x0001;
uinp.id.bustype = BUS_VIRTUAL;
// Keyboard
ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
for (i = mstVirtualInputDevData->min_keycode; i < mstVirtualInputDevData->max_keycode; i++) {
ioctl(uinp_fd, UI_SET_KEYBIT, i);
}
// Create input device into input sub-system
if (write(uinp_fd, &uinp, sizeof(uinp)) != sizeof(uinp)) {
printf("First write returned fail.\n");
return -1;
}
if (ioctl(uinp_fd, UI_DEV_CREATE)) {
printf("ioctl UI_DEV_CREATE returned fail.\n");
return -1;
}
return 1;
}
3、线程 VirtualInputDev_EventThread,只是重复发key,发key是通过write_event_to_device来完成的
static void* VirtualInputDev_EventThread(void *driver_data)
{
unsigned char u8Keycode,i=umin_keycode;
while (1) {
u8Keycode = 0xff;
/* sleep an interval time */
usleep(2000000);//sleep 5 s
/* fill event to uinput device. */
write_event_to_device(i++, 0);
if(i==4){
i = 0;
}
printf ("virtualinputdev thread ...\n");
//i %= umax_keycode;
}
printf ("virtualinputdev thread died\n");
pthread_exit(0);
return 0;
}
4、write_event_to_device 写event到uinput节点
void write_event_to_device(unsigned char u8KeyCode, unsigned char u8Repeat)
{
struct input_event event; // Input device structure
struct timespec s;
s.tv_nsec = 5000000L;
s.tv_sec = 0;
memset(&event, 0x00, sizeof(event));
gettimeofday(&event.time, 0);
event.type = EV_KEY;
event.code = u8KeyCode;
event.value = 1;
write(uinp_fd, &event, sizeof(event));
memset(&event, 0x00, sizeof(event));
gettimeofday(&event.time, 0);
event.type = EV_KEY;
event.code = u8KeyCode;
event.value = 0;
write(uinp_fd, &event, sizeof(event));
memset(&event, 0x00, sizeof(event));
gettimeofday(&event.time, 0);
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(uinp_fd, &event, sizeof(event));
}
- Android中的windowSoftInputMode属性详解
- Android WebView 不支持 H5 input type="file" 解决方法
- Android 数据存储之 FileInputStream 工具类及FileInputStream类的使用
- Android编程开发之EditText中inputType属性小结
- Android WebView支持input file启用相机/选取照片功能
- Android网页H5 Input选择相机和系统相册
- 详解Android WebView的input上传照片的兼容问题
- Android自定义PasswordInputView密码输入
- Android InputMethodManager输入法简介
- 从"Show tabs"了解Android Input系统
相关文章
详解Android10的分区存储机制(Scoped Storage)适配教程
这篇文章主要介绍了详解Android10的分区存储机制(Scoped Storage)适配教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-05-05Kotlin中let()with()run()apply()also()函数的使用方法与区别
在Kotlin中的源码标准库(Standard.kt)中提供了一些Kotlin扩展的内置函数可以优化kotlin的编码,今天为大家聊聊let,with,run,apply,also几个函数的用法与区别2018-03-03android音乐播放简单实现的简单示例(MediaPlayer)
本篇文章主要介绍了android音乐播放简单实现的简单示例(MediaPlayer),具有一定的参考价值,有兴趣的可以了解一下2017-08-08
最新评论