我正在做一个通用的自动化脚本.
我需要将复杂的滑动事件发送到Android屏幕,而无需专门访问重点应用程序
到目前为止,我认为最好的方法是使用adb,使用sendevent命令创建文件,将其推送到设备并从那里运行.即便如此,它也非常缓慢(与我用getevent录制并将其重新插入时相比要慢得多).
我设法优化文件,因为我发现每个sendevent块并不特别需要X和Y,但它仍然慢了几个数量级
文件的一部分示例(我正在尝试HTC One):
sendevent /dev/input/event5 3 57 49
sendevent /dev/input/event5 3 53 942
sendevent /dev/input/event5 3 54 2747
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 53 1207
sendevent /dev/input/event5 3 54 2483
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 53 1472
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 54 2218
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 53 1207
sendevent /dev/input/event5 3 54 2483
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 53 1472
Run Code Online (Sandbox Code Playgroud)
所以我的重点是优化单个长复杂滑动的速度,而不是多个小滑动.
有人知道更好的方法吗?
因此,Chris Stratton的想法原则上起作用(重新管道cat-ed输出会成功地生成相同的滑动),但是我无法创建自己的代码来重新输入它.我猜它是做的事情与发送事件命令之间的分隔符......但我仍然无法让它工作
我使用了对sendevent.c文件的修改来获取每行三元组并输出到另一个文件的文件.你碰巧知道可能是什么问题吗?转换看起来不错......
SOLLUTION:我设法解决了这个问题,主要归功于下面的答案.这是一个C脚本,它接收带有HEX值的文件并输出相应的二进制文件.
用法:(对我来说,触摸驱动文件是/ dev/input/event5 - HTC One - 对于其他设备,它可能是一个不同的文件!)
$> adb shell getevent > tmp.in
$> ./sendevent tmp.in tmp.out
$> adb shell push tmp.out /mnt/sdcard/
$> adb shell "cd /mnt/sdcard/ && cat tmp.out > /dev/input/event5"
Run Code Online (Sandbox Code Playgroud)
和来源:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
typedef uint32_t __u32;
typedef uint16_t __u16;
typedef __signed__ int __s32;
__attribute__((aligned(1),packed)) struct input_event {
__u32 time_dummy_1;
__u32 time_dummy_2;
__u16 type;
__u16 code;
__s32 value;
};
int convert (char * str) {
return (int) strtol(str, NULL, 16);
}
#define S_ALL (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH)
int main (int argc, char *argv[]) {
int i;
int fd;
int ret;
if(argc < 3) {
fprintf(stderr, "use: %s in-file out-file\n", argv[0]);
return 1;
}
fd = open(argv[2], O_CREAT | O_WRONLY, S_ALL);
if(fd < 0) {
fprintf(stderr, "could not open %s, %s\n", argv[2], strerror(errno));
return 1;
}
FILE * fd_in = fopen(argv[1], "r");
if (fd_in == NULL) {
fprintf(stderr, "Can't open input file: %s\n", argv[1]);
return 1;
}
struct input_event event;
char type[32];
char code[32];
char value[32];
int count = 0;
while (fscanf(fd_in, "%s %s %s", type, code, value) != EOF) {
memset(&event, 0, sizeof(event));
// printf("%d) %s %s %s\n", ++count, type, code, value);
event.type = convert(type);
event.code = convert(code);
event.value = convert(value);
memset(type, 0, sizeof(type));
memset(code, 0, sizeof(code));
memset(value, 0, sizeof(value));
ret = write(fd, &event, sizeof(event));
if(ret < sizeof(event)) {
fprintf(stderr, "write event failed, %s\n", strerror(errno));
return -1;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*ton 13
请注意,此答案适用于大约2013年版本的Android,可能不适用于当前版本.Jellybean当时是当代的,Kitkat在提出问题几个星期后问世
您的延迟很可能是因为无法重复启动新sendevent进程,解析文本事件记录以及打开设备节点 - 对于每个单独的事件.如果您在一个进程中执行所有操作,只打开一次设备文件,则效率会更高.
如果我们在问题日期的工具箱中查看sendevent的来源(例如,https: //android.googlesource.com/platform/system/core/+/jb-release/toolbox/sendevent.c )我们看到它正在做的核心是将事件编码为二进制记录
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
Run Code Online (Sandbox Code Playgroud)
并将它们写入适当的设备
memset(&event, 0, sizeof(event));
event.type = atoi(argv[2]);
event.code = atoi(argv[3]);
event.value = atoi(argv[4]);
ret = write(fd, &event, sizeof(event));
Run Code Online (Sandbox Code Playgroud)
如果您shell在inputunix组中执行某个用户ID或其他操作,您应该能够完成与sendevent您自己的自定义程序相同的操作,或使用其他命令行工具cat,从而有效地推送事件记录的二进制文件.
例如
adb shell
cd /mnt/sdcard
cat /dev/input/event2 > events
Run Code Online (Sandbox Code Playgroud)
做几个触摸屏事件,然后ctrl-C杀死猫
现在您可以播放捕获的二进制事件文件:
cat events > /dev/input/event2
Run Code Online (Sandbox Code Playgroud)
(注意:sendevent timeval将每个记录的部分归零;记录和回放可能不会这样做;你必须看到,并且如果在写回之前文件中的每个记录的那些部分都是重要的)
如果您只想生成线性滑动,可以input swipe在shell上使用命令.
$ adb shell input
usage: input ...
input text <string>
input keyevent <key code number or name>
input [touchscreen|touchpad|touchnavigation] tap <x> <y>
input [touchscreen|touchpad|touchnavigation] swipe <x1> <y1> <x2> <y2> [duration(ms)]
input trackball press
input trackball roll <dx> <dy>
Run Code Online (Sandbox Code Playgroud)
下面的命令在绘图应用程序中为我绘制了一条很好的线
$ adb shell input swipe 300 300 500 1000
Run Code Online (Sandbox Code Playgroud)
而且更快
$ adb shell input touchscreen swipe 300 300 500 1000 100
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
32542 次 |
| 最近记录: |