Android底层事件注入,控制系统的触摸、点击、各个按钮触发

Android底层事件注入,在知道要实现这个功能的时候,我感觉技术含量瞬间提高了很多,涉及到底层事务。

Android实现按钮触发事件方法有多种,但并不是每种都适用,我们使用的方法是调用"sendevent"命令,这是Linux系统下的命令,在Android上使用首先要将机器获取到root权限,root过的手机才能使用 Runtime.getRuntime().exec("cmd");  方法取得操作Android底层的环境;既然要使用到这个,那么简单的介绍一下这个东西;这个东西主要就是用来模拟一套linux系统环境,在这个环境下可以通过Linux里面的一些命令实现对系统的操作,使用方法非常简单:

java代码:

DataOutputStream dos = null;
try {
//注入su命令获取权限
Process p = Runtime.getRuntime().exec("su");
dos = new DataOutputStream(p.getOutputStream());
System.out.println(cmd);
//写入要执行的命令语句,下面语句表示列出sdcard下的文件信息,并将信息输出到dos流中,可以新建一个输入流获取
dos.writeBytes("ls /mnt/sdcard\n");
dos.flush();
dos.writeBytes("exit\n");
dos.flush();
p.waitFor();

} catch (Exception e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


上面的代码模拟了获取sdcard下文件目录的信息岛输出流dos中的操作,我们暂把这个操作命名为“RuntimeExec操作”,需要注意的问题是:

1. exec的输入输出流需要自己处理

2. exec执行时阻塞、非阻塞,返回结果问题

3. 注意权限问题 


--------------------------------------------------------------------------------------------------------------------------------

我们要实现向按钮、屏幕等硬件发送底层事件,需要先获取硬件设备文件权限(文件权限跟root权限不同),再调用open函数打开设备,设备文件一般在Android系统目录的dev/input结构下:

static int open_device(int index)
{
if (index >= nDevsCount || pDevs == NULL) return -1;
debug("open_device prep to open");
char *device = pDevs[index].device_path;

debug("open_device call %s", device);
int version;
int fd;
char name[80];
char location[80];
char idstr[80];
struct input_id id;
fd = open(device, O_RDWR);
if(fd < 0) {
pDevs[index].ufds.fd = -1;
pDevs[index].device_name = NULL;
debug("could not open %s, %s", device, strerror(errno));
return -1;
}
pDevs[index].ufds.fd = fd;
ufds[index].fd = fd;
name[sizeof(name) - 1] = ‘\0‘;
if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
debug("could not get device name for %s, %s", device, strerror(errno));
name[0] = ‘\0‘;
}
debug("Device %d: %s: %s", nDevsCount, device, name);
pDevs[index].device_name = strdup(name);
return 0;
}


获取文件权限可使用“RuntimeExec操作”注入命令"chmod 777 filepath"的方法获取;一般来说dev/input目录下会有event0、event1等等文件,这些文件对应我们的一个硬件设备,比如屏幕,鼠标等


有了这些,我们就可以使用sendevent命令了。

首先android界面捕获事件的流程。用户在屏幕上点击一下后,程序里面的OnClickListener是怎样收到这个事件的。大致流程如下
用户点击-(硬件驱动部分)硬件产生一个中断,往/dev/input/event*写入一个相应的信号-&gt;jni部分,android循环读取/dev/input/event*的事件,再分发给WindowManagerServer,最后再发到相应的ViewGroup和View。这里可以通过往/dev/input/event*写信号的方式,来达到模拟事件的目的,接下来关心的就是信号的协议了。


关于sendevent命令使用推荐两篇博客:

http://zuoshu.iteye.com/blog/1775606

http://blog.csdn.net/roger_ge/article/details/5552740


我们在做的时候基本实现了需要的功能,触摸、点击、滑屏、返回、菜单、Home、声音按钮的控制


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。