12

一般的な自動化スクリプトを実行しています。

フォーカスされたアプリケーションに特にアクセスせずに、複雑なスワイプイベントを 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

したがって、私の焦点は、複数の小さなスワイプではなく、単一の長い複雑なスワイプの速度を最適化することです.

これを行うためのより良い方法を知っている人はいますか?


したがって、Chris Stratton のアイデアは原則として機能しました (cat-ed 出力を再パイプすると、同じスワイプが正常に生成されます) が、それをパイプで戻す独自のコードを作成することはできません。イベント送信コマンド間のセパレーターを使用...しかし、まだ機能しません

sendevent.c ファイルを修正して、行ごとにトリプルを含むファイルを取得し、別のファイルに出力しました。何が問題なのか知っていますか?変換は良さそうです...


解決策:主に以下の回答のおかげで、なんとか解決できました。以下は、HEX 値を含むファイルを受け取り、適切なバイナリ ファイルを出力する C スクリプトです。

使用法: (私にとって、タッチ ドライバー ファイルは /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;
}
4

2 に答える 2

13

この回答は、Android の 2013 年頃のバージョンに関するものであり、現在のものには当てはまらない場合があることに注意してください。当時ジェリービーンは現代的であり、キットカットは質問が出されてから数週間後に出てきました

遅延は、sendevent個々のイベントごとに、新しいプロセスを繰り返し起動し、テキスト イベント レコードを解析し、デバイス ノードを開く必要がある非効率的な結果である可能性があります。代わりに、単一のプロセス内からすべてを実行し、デバイス ファイルを 1 回だけ開くと、はるかに効率的になります。

質問の日付と同時期のツールボックスで 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));

shellunix グループのユーザー ID または別のユーザー IDとして何かを実行している場合、独自のカスタム プログラムから、または のような他のコマンド ライン ツールを使用してinput、同じことを実行できるはずです。したがって、イベント レコードのバイナリファイルを効率的にプッシュできます。 .sendeventcat

例えば

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

いくつかのタッチ スクリーン イベントを実行してから、ctrl-C で cat を殺します

これで、バイナリ イベントのキャプチャ ファイルを再生できます。

cat events > /dev/input/event2 

(注意: sendevent はtimeval各レコードの一部をゼロにしています。記録と再生はそうしないかもしれません。確認する必要があります。問題がある場合は、書き戻す前にファイルから各レコードのそれらの部分をゼロにする必要があります)

于 2013-10-01T22:28:44.640 に答える
7

線形スワイプを生成したいだけの場合は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
于 2013-10-02T13:53:20.913 に答える