我的项目功能看起来像VNC。但与此略有不同。 我有一个在Android上运行的服务器程序和一个在PC上运行的客户端。我想通过在PC上操作来控制手机。
这个项目的大部分内容已经完成,但在控制步骤中发生了一点错误。也许你知道我们永远 使用the user level input subsystem来实现响应操作命令的目标 来自PC客户端。在编写这部分程序时,我引用了其他人。另外,我是Android新手,所以有些事情是我无法控制的。
好的,我会详细说明如下。 例如,当您单击鼠标或按下PC上的某些键时,服务器会通过某些协议接收此命令,例如 RFB,并获取有关您的命令事件的相关信息,例如按钮面具(可以决定左或 单击鼠标右键)或位置(X,Y坐标)。按照向Android发送命令的三个步骤。首先,通过" / dev / uinput"的开放设备创建输入设备。在android中。 其次,将相关事件注入输入子系统。 然后,将事件写入虚拟输入子系统。
简化代码:
//First ADN SECOND STEPS:
int initial()
{
int inputfd = -1;
uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
/* Set device to handle following types of events: */
/* Key and button repetition events */
if (ioctl(uinput_fd, UI_SET_EVBIT, EV_REP) == -1)
return -1;
/* Absolute pointer motions */
if (ioctl(uinput_fd, UI_SET_EVBIT, EV_ABS) == -1)
return -1;
/* Configure device to handle absolute x and y axis. */
if (ioctl(uinput_fd, UI_SET_ABSBIT, ABS_X) == -1)
goto err;
if (ioctl(uinput_fd, UI_SET_ABSBIT, ABS_Y) == -1)
return -1;
/* Synchronization events, this is probably set implicitely too. */
if (ioctl(uinput_fd, UI_SET_EVBIT, EV_SYN) == -1)
return -1;
struct uinput_user_dev user_dev;
/* Set device-specific information. */
memset(&user_dev, 0, sizeof(user_dev));
strncpy(user_dev.name, device_name, UINPUT_MAX_NAME_SIZE);
user_dev.id.bustype = BUS_USB;
user_dev.id.vendor = 1;
user_dev.id.product = 1;
user_dev.id.version = 1;
//minor tweak to support ABSolute events
user_dev.absmin[ABS_X] = 0;
user_dev.absmax[ABS_X] = 799;
user_dev.absfuzz[ABS_X] = 0;
user_dev.absflat[ABS_X] = 0;
user_dev.absmin[ABS_Y] = 0;
user_dev.absmax[ABS_Y] = 479;
user_dev.absfuzz[ABS_Y] = 0;
user_dev.absflat[ABS_Y] = 0;
if (write(uinput_fd, &user_dev, sizeof(user_dev)) != sizeof(user_dev))
return -1;
if (ioctl(uinput_fd, UI_DEV_CREATE) == -1)
return -1;
}
//THREE STEP:
//call by ptrEvent
int suinput_write(int uinput_fd, uint16_t type, uint16_t code, int32_t value)
{
struct input_event event, nullevent;
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, 0); /* This should not be able to fail ever.. */
event.type = type;
event.code = code;
event.value = value;
if (write(uinput_fd, &event, sizeof(event)) != sizeof(event))
return -1;
return 0;
}
//begin to deal with event
void ptrEvent(int buttonMask, int x, int y, rfbClientPtr cl)
{
static int leftClicked=0;
if ( inputfd == -1 )
return;
if (buttonMask & 1)
{ //left btn clicked
leftClicked=1;
suinput_write(inputfd, EV_ABS, ABS_X, x);
suinput_write(inputfd, EV_ABS, ABS_Y, y);
suinput_write(inputfd,EV_KEY,BTN_TOUCH,1);
suinput_write(inputfd, EV_SYN, SYN_REPORT, 0);
}
else if (leftClicked)
{ //left btn released
leftClicked=0;
suinput_write(inputfd, EV_ABS, ABS_X, x);
suinput_write(inputfd, EV_ABS, ABS_Y, y);
suinput_write(inputfd,EV_KEY,BTN_TOUCH,0);
suinput_write(inputfd, EV_SYN, SYN_REPORT, 0);
}
}
Android设备的分辨率为800 * 480。和客户端图片也有相同的大小。我调试上面的代码并找到它 服务器从事件消息中接收正确的位置。在ptrEvent的功能中,X和Y对应于真实 点击位置发生在PC上。但是从Android上显示的实际按压位置来看,还有不同之处。正如你看到的, 我将Android虚拟输入设备的最大绝对范围设置为与实际分辨率相同,因此显然客户端和服务器之间没有偏差 坐标。为什么会这样?