Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/200.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android模拟快速滑动_Android_Adb - Fatal编程技术网

Android模拟快速滑动

Android模拟快速滑动,android,adb,Android,Adb,我正在做一个通用自动化脚本 我需要将复杂的刷卡事件发送到android屏幕,而无需特别访问重点应用程序 到目前为止,我认为最好的方法是使用adb,使用sendevent命令创建一个文件,将其推送到设备上并从那里运行。即便如此,它还是慢得令人痛苦(与使用getevent录制并将其重新导入相比要慢得多) 我设法优化了文件,因为我发现每个sendevent块并不特别需要X和Y,但它仍然要慢几个数量级 部分文件的示例(我正在尝试HTC版本): 因此,我的重点是优化单次长时间复杂滑动的速度,而不是多次小滑

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

我需要将复杂的刷卡事件发送到android屏幕,而无需特别访问重点应用程序

到目前为止,我认为最好的方法是使用adb,使用sendevent命令创建一个文件,将其推送到设备上并从那里运行。即便如此,它还是慢得令人痛苦(与使用getevent录制并将其重新导入相比要慢得多)

我设法优化了文件,因为我发现每个sendevent块并不特别需要X和Y,但它仍然要慢几个数量级

部分文件的示例(我正在尝试HTC版本):

因此,我的重点是优化单次长时间复杂滑动的速度,而不是多次小滑动的速度

有人知道更好的方法吗


因此,Chris Stratton的想法在原则上是可行的(重新管道化cat ed输出会成功地生成相同的刷击),但我无法创建自己的代码来管道化它。我猜这与发送事件命令之间的分隔符有关。。。但我还是不能让它工作

我对sendevent.c文件进行了修改,得到了一个每行有三个字符的文件,并输出到另一个文件。你知道可能是什么问题吗?转换看起来不错


解决方案:我设法解决了这个问题,主要是因为下面的答案。下面是一个C脚本,它获取一个具有十六进制值的文件并输出相应的二进制文件

用法:(对于我来说,触摸驱动程序文件是/dev/input/event5-HTC One-对于其他设备,它可能是另一个文件!!!)

资料来源:

#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
typedef uint32_t_32;
类型定义uint16\u t\u16;
typedef uuu signed uuu int uuu s32;
__属性(对齐(1),压缩))结构输入事件{
__u32时间_伪_1;
__u32时间μ2;
__u16型;
__u16代码;
__s32值;
};
整数转换(字符*str){
返回(int)strtol(str,NULL,16);
}
#定义S|ALL(S|IRUSR | S|IWUSR | S|IXUSR | S|IWGRP | S|IXGRP | S|IWOTH | S|IXOTH)
int main(int argc,char*argv[]){
int i;
int-fd;
int ret;
如果(argc<3){
fprintf(stderr,“使用文件中的%s-in-file-out-file\n”,argv[0]);
返回1;
}
fd=打开(argv[2],O|u创建| O|u WRONLY,S|u ALL);
如果(fd<0){
fprintf(stderr,“无法打开%s,%s\n”,argv[2],strerror(errno));
返回1;
}
文件*fd_in=fopen(argv[1],“r”);
if(fd_in==NULL){
fprintf(stderr,“无法打开输入文件:%s\n”,argv[1]);
返回1;
}
结构输入事件;
字符类型[32];
字符码[32];
字符值[32];
整数计数=0;
while(fscanf(fd_in,“%s%s%s”,类型、代码、值)!=EOF){
memset(&event,0,sizeof(event));
//printf(“%d)%s%s%s\n”++计数、类型、代码、值);
event.type=转换(类型);
event.code=转换(代码);
event.value=转换(值);
memset(type,0,sizeof(type));
memset(代码,0,sizeof(代码));
memset(值,0,sizeof(值));
ret=写入(fd和事件,sizeof(事件));
如果(ret
请注意,此答案适用于2013年左右的Android版本,可能不适用于当前版本。“果冻豆”在当时是同时代的,Kitkat在被问到这个问题几周后就出来了

您的延迟可能是由于必须重复启动新的
sendevent
进程、解析文本事件记录并打开设备节点(针对每个单独的事件)而导致的。相反,如果您在单个进程中执行所有操作,只打开设备文件一次,则效率会高得多

如果我们查看工具箱中sendevent的源代码以及问题的日期(例如),我们会发现它所做的核心工作是将事件编码为二进制记录

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};
并将它们写入适当的设备

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));
如果您正在以
shell
userid或
input
unix组中的另一个身份执行某些操作,您应该能够通过自己的自定义程序或使用其他命令行工具(如
cat
)完成与
sendevent
相同的操作,从而有效地推送事件记录的二进制文件

比如说

adb shell
cd /mnt/sdcard
cat /dev/input/event2 > events
执行一些触摸屏事件,然后按ctrl-C键杀死猫

现在,您可以播放捕获的二进制事件文件:

cat events > /dev/input/event2 

(注意:sendevent是将每条记录的
timeval
部分归零;录制和播放可能无法做到这一点;您必须查看,如果在回写之前将文件中每条记录的这些部分归零很重要)

如果您只想产生线性滑动,可以在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>
还有一个更快的

$ adb shell input touchscreen swipe 300 300 500 1000 100

不幸的是,我需要复杂的滑动,或者如果有线性滑动,那么我需要它们在结束时没有键控事件,这样我就可以在单个复杂中组合它们swipe@tak3r你有根访问权限吗?我认为不需要根访问权限。这似乎可以从adb shell中使用,这意味着
shell
userid有权执行任何需要的操作。input命令是一个脚本,它使用app process启动input.java(非官方repo),可以用类似编译和存储的自定义版本替换它。类似地,从adb外壳调用-如果应用程序在安全模型周围运行,则无法执行此操作。@ChrisStratton不幸的是,没有。在系统目录下,该应用程序将无法与组件对话。你甚至不能在Android存储库之外构建这个应用,因为它使用隐藏的API。安西
$ 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>
$ adb shell input swipe 300 300 500 1000
$ adb shell input touchscreen swipe 300 300 500 1000 100