Android 手机遥控器添加模拟鼠标功能
手机遥控器要求有模拟鼠标功能,之前别人做的模拟鼠标是用service加上自己画的图标来实现的,不能像真正鼠标一样方便,而且实现比较难。网上查找资料发现可以通过UInput来实现这个功能。Uinput是一个虚拟的设备,使得可以在用户控件处理input设备,一般来讲uinput设备文件存在于/dev/input或者/dev/input/uinput目录中。在Linux中一切都是文件,所以使用uinpu
·
手机遥控器要求有模拟鼠标功能,之前别人做的模拟鼠标是用service加上自己画的图标来实现的,不能像真正鼠标一样方便,而且实现比较难。网上查找资料发现可以通过UInput来实现这个功能。
Uinput是一个虚拟的设备,使得可以在用户控件处理input设备,一般来讲uinput设备文件存在于/dev/input或者/dev/input/uinput目录中。在Linux中一切都是文件,所以使用uinput也很简单只需要open这个设备就可以了
打开设备:
extern "C"
JNIEXPORT int JNICALL
Java_com_remote_uinput_UInput_open(JNIEnv *env, jclass clazz) {
struct uinput_user_dev uidev;
//以只读的方式打开字符设备
fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
// if (fd < 0) die("error: open ");
LOGD( "fd == %d", fd);
//打印出打开设备失败的原因,可以看看是否因为权限导致
LOGD("open %s fail, %s\n", "/dev/uinput", strerror(errno));
if (fd<0) {
LOGD( "fd == %d", fd);
return -1;
}
//config uinput working mode, mouse or touchscreen? relative coordinates or absolute coordinate?
if (ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0) //support key button
die("error: ioctl UI_SET_EVBIT");
if (ioctl(fd, UI_SET_KEYBIT, BTN_LEFT) < 0) //support mouse left key
die("error: ioctl UI_SET_KEYBIT");
if (ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT) < 0) //support mouse right key
die("error: ioctl UI_SET_KEYBIT");
if (ioctl(fd, UI_SET_EVBIT, EV_REL) < 0) //uinput use relative coordinates
die("error: ioctl UI_SET_EVBIT");
if (ioctl(fd, UI_SET_RELBIT, REL_X) < 0) //uinput use x coordinates
die("error: ioctl UI_SET_RELBIT REL_X");
if (ioctl(fd, UI_SET_RELBIT, REL_Y) < 0) //uinput use y coordinates
die("error: ioctl REL_Y");
memset(&uidev, 0,
sizeof(uidev)); //creat an virtul input device node in /dev/input/***
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");//配置设备名称
uidev.id.bustype = BUS_USB;//配置设备类型
uidev.id.vendor = 0x1;//配置设备vendor
uidev.id.product = 0x1;//配置设备product
uidev.id.version = 1;//配置设备version
//将配置写到uinput中
if (write(fd, &uidev, sizeof(uidev)) < 0){
die("error: write");
return -1;
}
//通过ioctl创建这个虚拟设备
if (ioctl(fd, UI_DEV_CREATE) < 0){
die("error: ioctl");
return -1;
}
return 1;
}
使用设备:
extern "C"
JNIEXPORT void JNICALL
Java_com_remote_uinput_UInput_simulateMouseMove(JNIEnv *env, jclass clazz, jint dx,
jint dy) {
struct input_event ev;//input_event 结构体
//send input event to kernel input system
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_REL; //send x coordinates 事件类型 EV_REL相对事件, EV_KEY key事件, EV_ABS绝对事件
ev.code = REL_X;//键值
ev.value = dx;//key 1 表示按下,0表示释放 鼠标代表移动距离
if (write(fd, &ev, sizeof(struct input_event)) < 0)
die("error: write");
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_REL; //send y coordinates
ev.code = REL_Y;
ev.value = dy;
if (write(fd, &ev, sizeof(struct input_event)) < 0)
die("error: write");
// memset(&ev, 0, sizeof(struct input_event));
// ev.type = EV_KEY; //mouse left key 左键
// ev.code = BTN_LEFT;
// ev.value = 1;
// if(write(fd, &ev, sizeof(struct input_event)) < 0)
// die("error: write");
//EV_SYN 同步 即执行这个事件
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_SYN; // inform input system to process this input event
ev.code = 0;
ev.value = 0;
if (write(fd, &ev, sizeof(struct input_event)) < 0)
die("error: write");
}
销毁:
extern "C"
JNIEXPORT void JNICALL
Java_com_ktc_remote_uinput_UInput_close(JNIEnv *env, jclass clazz) {
//销毁这个设备
if (ioctl(fd, UI_DEV_DESTROY) < 0)
die("error: ioctl");
//关闭这个文件
close(fd);
}
这个方法不只是支持鼠标模拟,包括按键模拟,触摸屏模拟都可以实现,功能比较强大。
使用时需要注意,uinput这个文件不是可写的,低版本的系统可以在应用类修改文件权限,但是在高版本的Android中动态修改权限会失败,所以只能在系统初始化 init.rc中直接修改该文件为可读写,其次需要修改selinux权限,否则会因为权限不足无法创建设备。
更多推荐
已为社区贡献1条内容
所有评论(0)