Android的模拟快速轻扫 [英] Android simulate fast swipe

查看:246
本文介绍了Android的模拟快速轻扫的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做一个通用的自动化脚本。

我需要发送复杂的刷卡事件到Android屏幕而不专不必聚焦的应用程序(S)

访问

我想通为止最好的方法是使用亚洲开发银行,创建的SendEvent命令的文件,将其推在设备上,并从那里运行它。即使这样,(慢得多相比,如果我在getevent和管道将其记录下来回)这是痛苦的缓慢。

我设法优化文件,因为我想通了,每个的SendEvent块没有特别要求X和Y,但它仍然是数量级的几个订单慢

的文件的一部分(我想在的HTC One)例如:

 的SendEvent的/ dev /输入/ event5 3 57 49
的SendEvent的/ dev /输入/ event5 3 53 942
的SendEvent的/ dev /输入/ event5 3 54 2747
的SendEvent的/ dev /输入/ event5 0 0 0

的SendEvent的/ dev /输入/ event5 3 53 1207
的SendEvent的/ dev /输入/ event5 3 54 2483
的SendEvent的/ dev /输入/ event5 0 0 0

的SendEvent的/ dev /输入/ event5 3 53 1472
的SendEvent的/ dev /输入/ event5 0 0 0

的SendEvent的/ dev /输入/ event5 3 54 2218
的SendEvent的/ dev /输入/ event5 0 0 0

的SendEvent的/ dev /输入/ event5 3 53 1207
的SendEvent的/ dev /输入/ event5 3 54 2483
的SendEvent的/ dev /输入/ event5 0 0 0

的SendEvent的/ dev /输入/ event5 3 53 1472
 

所以我的重点是优化而不是多个小的单长复杂刷卡的速度。

任何人都知道一个更好的方式来做到这一点?


因此​​,克里斯·斯特拉顿的思想工作原则(重新管道猫-ED输出成功生成相同的刷卡),但我不能够创建自己的code管道回去。我'猜它的东西做之间发送事件命令分离......但我仍然无法得到它的工作

我用sendevent.c文件的修改来获得,每行和输出三元组到另一个文件的一个文件。你碰巧知道可能是什么问题?转换看起来很不错...


SOLLUTION:我设法解决这个问题,主要是得益于答案波纹管。这里是一个C脚本,需要用十六进制值的文件,并输出相应的二进制文件。

用法:(对我来说,触摸驱动程序文件是/ dev /输入/ event5 - HTC的一个 - 为其他设备可能是不同的文件!)

  $>亚行外壳getevent> tmp.in
 $> ./sendevent tmp.in tmp.out
 $>亚行外壳推tmp.out到/ mnt / SD卡/
 $>亚行壳CD到/ mnt / SD卡/&安培;&安培;猫tmp.out>的/ dev /输入/ event5
 

和源:

 的#include< stdio.h中>
#包括< stdlib.h中>
#包括< string.h中>
#包括< stdint.h>
#包括< fcntl.h>
#包括< SYS / ioctl.h>
#包括< unistd.h中>
#包括< errno.h中>

的typedef uint32_t的__u32;
的typedef uint16_t __u16;
的typedef __signed__ INT __s32;

__attribute __((排列(1),装))结构input_event {
    __u32 time_dummy_1;
    __u32 time_dummy_2;
    __u16类型;
    __u16 code;
    __s32值;
};

INT转换(字符* STR){
    返程(INT)与strtol(STR,NULL,16);
}

#定义S_ALL(S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXG​​RP | S_IROTH | S_IWOTH | S_IXOTH)

INT主(INT ARGC,字符* argv的[]){
    INT I;
    INT的fd;
    INT RET;

    如果(ARGC 3;){
        fprintf中(错误,使用:%S在文件输出文件\ N的argv [0]);
        返回1;
    }

    FD =打开(的argv [2],O_CREAT | O_WRONLY,S_ALL);
    如果(FD&小于0){
        fprintf中(错误,无法打开%s%S \ N的argv [2],字符串错误(错误));
        返回1;
    }

    FILE * fd_in = FOPEN(的argv [1],R);
    如果(fd_in == NULL){
        fprintf中(错误,无法打开输入文件:%s \ N的argv [1]);
        返回1;
    }

    结构体input_event事件;
    char类型[32];
    字符code [32];
    char值[32];
    诠释计数= 0;
    而(的fscanf(fd_in,%s%s%S型,code,值)!= EOF){
        memset的(安培;事件,0,sizeof的(事件));
        //的printf(%d)%s%S%S \ N,++计数,类型,code,值);
        Event.type访问=转换(类型);
        。事件code =转换(code);
        event.value =转换(值);
        memset的(类型,0,sizeof的(类型));
        memset的(code,0,sizeof的(code));
        memset的(值0的sizeof(值));
        RET =写(FD,与放大器;事件的sizeof(事件));
        如果(RET<的sizeof(事件)){
            fprintf中(错误,写事件失败%S \ N,字符串错误(错误));
            返回-1;
        }
    }

    返回0;
}
 

解决方案

您迟延可能的低效率有一个结果,反复启动一个新的的SendEvent 工艺,解析文本事件记录,并打开设备节点 - 为每个单独的事件。如果你不是从一个单一的过程中所做的一切,打开设备文件只有一次,这将是更有效的。

如果我们看一下源代码的SendEvent在工具箱中(例如,从非官方的,但浏览的镜子<一href="https://github.com/android/platform_system_core/blob/master/toolbox/sendevent.c">https://github.com/android/platform_system_core/blob/master/toolbox/sendevent.c )我们看到,它是什么做的是编码的事件成二进制记录的核心

 结构input_event {
    timeval结构的时间;
    __u16类型;
    __u16 code;
    __s32值;
};
 

和其写入到相应的设备

  memset的(安培;事件,0,sizeof的(事件));
Event.type访问=的atoi(argv的[2]);
。事件code =的atoi(argv的[3]);
event.value =的atoi(argv的[4]);
RET =写(FD,与放大器;事件的sizeof(事件));
 

前提是您要执行什么作为用户ID或其他在输入 UNIX组,你应该能够做到同样的事情的SendEvent 不会从自己的定制程序,或使用像其他命令行工具,从而有效地推着文件事件记录。

例如

  ADB壳
CD到/ mnt / SD卡
猫的/ dev /输入/ EVENT2&GT;事件
 

做了一些触摸屏事件,然后按Ctrl-C杀掉猫

现在您可以回放二进制事件捕获文件:

 猫事件&GT;的/ dev /输入/ EVENT2
 

(注:的SendEvent是零每条记录的的timeval 部分,录制和回放可能无法做到这一点,你必须看到,如果它的事项零那些从你写回之前的文件中的每条记录)

部分

I am doing a generic automation script.

I need to send complex swipe events to the android screen without specifically having access to the focused application(s)

Best way I figured so far is to use adb, create a file with sendevent commands, push it on the device and run it from there. Even that, it is painfully slow (much slower compared to if I record it with getevent and pipe it back in).

I managed to optimize the file since I figured out that each sendevent block does not specifically require both X and Y, but it is still a few orders of magnitude slower

Example of part of the file (I'm trying on a 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

So my focus is to optimize the speed of single long-complex swipes, not of multiple small ones.

Anyone know of a better way to do this?


So, Chris Stratton's idea worked in principle (re-piping the cat-ed output generates the same swipe successfully), but I can't be able to create my own code to pipe it back in. I'm guessing it's something to do with the separators between send event commands... but I still can't get it to work

I used a modification of the sendevent.c file to get a file with triples per line and output to another file. Do you happen to know what could be the issue? Conversion looks good ...


SOLLUTION: I managed to solve it, mostly thanks to the answers bellow. Here is a C script that takes a file with HEX values and outputs the appropriate binary file.

Usage: (for me the touch driver file is /dev/input/event5 - HTC One - for other devices it might be a different file !!!)

 $> 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"

and the source:

#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;
}

解决方案

Your delay is likely a result of inefficiently having to repeatedly launch a new sendevent process, parse the textual event record, and open the device node - for each individual event. If you instead do everything from within a single process, opening the device file only once, it will be much more efficient.

If we look at the source for sendevent in toolbox (for example, from the unofficial but browsable mirror at https://github.com/android/platform_system_core/blob/master/toolbox/sendevent.c ) we see that the core of what it is doing is encoding the events into binary records

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

and writing them to the appropriate device

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));

Provided that you are executing something as the shell userid or another in the input unix group, you should be able to accomplish the same thing that sendevent does from your own custom program, or using other command line tools like cat, thus efficiently pushing a binary file of event records.

For example

adb shell
cd /mnt/sdcard
cat /dev/input/event2 > events

Do a few touch screen events, then ctrl-C to kill cat

Now you can play back the captured file of binary events:

cat events > /dev/input/event2 

(Note: sendevent is zeroing the timeval part of each record; recording and playback may not do that; you'll have to see, and if it matters zero those portions of each record from the file before you write it back)

这篇关于Android的模拟快速轻扫的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆