Android имитирует быстрый салфетки
Я делаю универсальную автоматизацию script.
Мне нужно отправить сложные события салфетки на экран Android, не имея особого доступа к сфокусированным приложениям.
Лучший способ, который я догадался до сих пор, - использовать adb, создать файл с командами sendevent, нажать на него и запустить его оттуда. Даже это, это мучительно медленно (гораздо медленнее, если я записываю его с помощью getevent и возвращаю его обратно).
Мне удалось оптимизировать файл, так как я понял, что каждый блок отправления специально не требует как 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
Итак, я сосредоточен на оптимизации скорости одиночных длинномерных сложностей, а не нескольких небольших.
Кто-нибудь знает лучший способ сделать это?
Итак, идея Криса Стриттона работала в принципе (повторное подключение вывода cat-ed дает тот же салфетки успешно), но я не могу создать свой собственный код, чтобы его снова подключить. Я предполагаю, что это что-то делать с разделителями между командами событий отправки... но я все еще не могу заставить его работать
Я использовал модификацию файла sendevent.c для получения файла с тройками на строку и вывода в другой файл. Вы случайно не знаете, в чем проблема? Конверсия выглядит хорошо...
РЕШЕНИЕ: Мне удалось это решить, в основном благодаря ответам ниже. Вот C script, который принимает файл с значениями 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"
и источник:
#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;
}
Ответы
Ответ 1
Обратите внимание, что этот ответ относится к версиям Android около 2013 года и может не относиться к текущим версиям. В то время желе было современным, Киткат вышел через несколько недель после того, как был задан вопрос
Ваша задержка, вероятно, является результатом неэффективного повторного запуска нового процесса 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;
};
и запись их на соответствующее устройство
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
или другого во input
unix-группе, вы должны иметь возможность выполнить то же, что sendevent
делает из вашей собственной пользовательской программы или с помощью других инструментов командной строки, таких как cat
, таким образом эффективно выдвигая двоичный файл файл записей событий.
Например
adb shell
cd /mnt/sdcard
cat /dev/input/event2 > events
Сделайте несколько событий на сенсорном экране, затем нажмите Ctrl-C, чтобы убить кота.
Теперь вы можете воспроизвести захваченный файл бинарных событий:
cat events > /dev/input/event2
(Примечание: sendevent обнуляет timeval
часть каждой записи; запись и воспроизведение могут этого не делать; вам придется посмотреть, и если это имеет значение, обнулить эти части каждой записи из файла перед тем, как записать его обратно)
Ответ 2
Если вы просто хотите создать линейные прокрутки, вы можете использовать команду input swipe
для оболочки.
$ 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
Ответ 3
У кого-нибудь есть успех с лучшим ответом на Android 7.0? Я попытался изменить несколько параметров и попытаться изменить этот параметр, и все, что не будет работать. Даже если я использую исходный код для 7.0 файла sendevent.c из ядра Android, он не работает. Телефон рутирован, разрешение измененного отправителя изменено на 777, скомпилировано с помощью ndk. Когда я запускаю его с помощью терминала, он читает точки из файла и показывает строки printf из sendevent, но не хочет касаться.