2013-09-28 155 views
11

我正在做一個通用的自動化腳本。Android模擬快速刷卡

我需要複雜的刷卡事件發送到Android屏幕而不特別是具有訪問焦點應用(一個或多個)

我想通到目前爲止最好的辦法是使用ADB,創建的SendEvent命令的文件,將其推在設備上並從那裏運行。即使如此,它的速度卻非常緩慢(如果我用getevent記錄並重新輸入它,速度要慢得多)。

我設法優化文件,因爲我想出每個的SendEvent塊沒有特別要求X和Y,但它仍然是大小較慢的文件的一部分

實施例的幾個數量級(I」米試穿的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 

所以我的重點是優化而不是多個小的單長複雜的揮動速度。

任何人都知道更好的方法來做到這一點?


所以,克里斯·斯特拉頓的想法原則上工作(重新管道貓-ED輸出成功生成相同的刷卡),但我不能夠創建自己的代碼來管回。我猜測這是與發送事件命令之間的分隔符...但我仍然無法讓它工作

我使用了sendevent.c文件的修改來獲取每行三元文件和輸出到另一個文件。你碰巧知道可能是什麼問題?轉換看起來不錯...


SOLLUTION:我設法解決它,主要得益於下面的答案。這是一個C腳本,它接受一個具有HEX值的文件並輸出相應的二進制文件。

用法:(對我來說,觸摸驅動程序文件是/ dev /輸入/ 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; 
} 
+0

我知道這是一個老問題,但你將能夠解釋如何將這個新的sendevents.c文件放到android設備上,我推測你會使用adb push,但不知道我可以將文件放在哪個目錄下,以便它是可執行文件。 –

+0

我現在已經創建了一個更合適的問題。你的幫助將不勝感激。 http://stackoverflow.com/questions/23131081/adding-a-custom-tool-to-the-android-adb-shell –

+0

我發佈了你的問題的答案。希望它有助於:http://stackoverflow.com/questions/23131081/adding-a-custom-tool-to-the-android-adb-shell/23135779#23135779 – Stefan

回答

12

您的延遲很可能是因爲無法重複啓動新的sendevent進程,解析文本事件記錄並打開設備節點 - 對於每個單獨的事件而言。如果您只是在一個流程內完成所有工作,只需打開一次設備文件,那麼效率會更高。

如果我們看一下源的SendEvent在工具箱中(例如,從https://github.com/android/platform_system_core/blob/master/toolbox/sendevent.c非官方的,但可瀏覽鏡像),我們看到它是什麼做的是編碼的事件爲二進制記錄的核心

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

,並將它們寫入假如您正在執行的東西作爲shell用戶ID或另一個input UNIX組在相應的設備

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

,你應該能夠完成SA我的東西,sendevent從你自己的自定義程序,或使用其他命令行工具如cat,從而有效地推動事件記錄文件的二進制文件。

例如

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

做了幾個觸摸屏事件,然後按Ctrl-C殺掉貓

現在,您可以播放二進制事件捕獲文件:

cat events > /dev/input/event2 

(注意:sendevent正在調零每個記錄的timeval部分;記錄和回放可能不會這樣做;您必須查看,並且如果它重要爲零的每個記錄的那些部分在你寫回之前的文件)

+0

這似乎是一個好主意。讓我試試看,我會盡快回復你 – Stefan

+0

它幾乎可以工作,你可以看看我更新的帖子,也許你知道什麼是錯的 – Stefan

+0

@ tak3r - 雖然我不知道這是你唯一的問題,但它看起來像你正在使用'int'的格式說明符,即「%d」,但是將指針傳遞給__u16(實際上是一個'unsigned short')給fscanf。你可能想要「%hu」,否則讀入一個臨時的unsigned int然後複製它。 –

6

如果你只是想產生線性滑動,你可以在shell上使用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 
+0

不幸的是我需要複雜的滑動操作,或者如果有線性滑動,那麼我需要它們在最後沒有keyup事件,所以我可以將它們組合成一個複雜的滑動 – Stefan

+0

@ tak3r你有root權限嗎? – auselen

+1

我不認爲需要root權限。這似乎可以從adb shell使用,這意味着'shell'用戶標識有權執行任何需要的操作。輸入命令是一個腳本,它使用app-process來啓動input.java(非官方回購https://github.com/android/platform_frameworks_base/blob/master/cmds/input/src/com/android/commands/input/Input 。java),它可能被替換爲類似編譯和存儲的自定義版本。並且類似地從adb shell *中調用* - 您將無法從應用程序執行此操作,從而繞着安全模型運行。 –