Android simular el golpe rápido

Estoy haciendo un script de automatización genérico.

Necesito enviar eventos complejos de desplazamiento a la pantalla de Android sin tener específicamente acceso a la aplicación (s) enfocada (s)

La mejor manera que pensé hasta ahora es usar adb, crear un archivo con comandos sendevent, empujarlo en el dispositivo y ejecutarlo desde allí. Incluso eso, es dolorosamente lento (mucho más lento en comparación con si lo grabo con getevent y tubo de nuevo en).

Me las arreglé para optimizar el archivo ya que me di cuenta de que cada bloque sendevent no requiere específicamente X y Y, pero sigue siendo unos pocos órdenes de magnitud más lento

Ejemplo de parte del archivo (estoy probando un 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 

Así que mi enfoque es optimizar la velocidad de los golpes individuales largos y complejos, no de varios pequeños.

Alguien sabe de una mejor manera de hacer esto?


Por lo tanto, la idea de Chris Stratton funcionó en principio (volver a canalizar la salida cat-ed genera el mismo golpe con éxito), pero no puedo ser capaz de crear mi propio código de tubería de nuevo pulg Im supongo que es algo que hacer Con los separadores entre los comandos de envío de eventos … pero todavía no puedo conseguir que funcione

He utilizado una modificación del archivo sendevent.c para obtener un archivo con triples por línea y salida a otro archivo. ¿Por casualidad usted sabe cuál podría ser el problema? La conversión parece buena …


SOLUCIÓN: He logrado solucionarlo, sobre todo gracias a las respuestas a continuación. Esta es una secuencia de comandos C que toma un archivo con valores HEX y genera el archivo binario apropiado.

Uso: (para mí, el archivo del controlador táctil es / dev / input / event5 – HTC One – para otros dispositivos podría ser un archivo diferente!)

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

Y la fuente:

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

Su retraso es probablemente el resultado de ineficaz tener que lanzar repetidamente un nuevo proceso sendevent , analizar el registro de eventos textual, y abrir el nodo de dispositivo – para cada evento individual. Si en su lugar lo hace todo desde un solo proceso, abriendo el archivo del dispositivo sólo una vez, será mucho más eficiente.

Si nos fijamos en la fuente para sendevent en caja de herramientas (por ejemplo, desde el espejo no oficial, pero navegable en https://github.com/android/platform_system_core/blob/master/toolbox/sendevent.c ) vemos que el núcleo de lo que Que está haciendo es la codificación de los eventos en los registros binarios

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

Y escribirlas en el dispositivo apropiado

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

Siempre que ejecutes algo como el userid del shell o el otro en el grupo unix de input , deberías ser capaz de lograr lo mismo que sendevent hace desde tu propio programa personalizado, o usando otras herramientas de línea de comandos como cat , de manera eficiente empujando un binario Archivo de registros de eventos.

Por ejemplo

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

Hacer unos pocos eventos de pantalla táctil, luego ctrl-C para matar al gato

Ahora puede reproducir el archivo capturado de eventos binarios:

 cat events > /dev/input/event2 

(Nota: sendevent está poniendo a cero la parte timeval de cada registro, la grabación y reproducción no puede hacer eso, tendrá que ver, y si importa cero esas porciones de cada registro del archivo antes de volver a escribirlo)

Si sólo desea producir desplazamientos lineales, puede utilizar input swipe comando de input swipe en 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> 

El comando abajo dibuja una línea agradable para mí en una aplicación de dibujo

 $ adb shell input swipe 300 300 500 1000 

Y una más rápida

 $ adb shell input touchscreen swipe 300 300 500 1000 100 
  • Cómo saber si el servicio se está ejecutando utilizando adb shell en android
  • ¿El depurador de Android trunca mensajes de depuración?
  • No se puede mostrar el dispositivo android en ubuntu 13.04
  • Android Studio 2.0 Esperando depurador
  • Adb conexión wifi con Android 6.0
  • ¿Cómo ejecuto un comando adb en Android Studio?
  • Desconexión ADB después de unos minutos
  • Cómo "Conectando sobre ADB a localhost: 5277 ... falló"
  • No se puede ver Nexus 6P para depurar
  • Android: ADB Driver para HTC One X
  • Cómo configurar la fecha / hora del dispositivo Android mediante programación
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.