From 3e348641d8dcd9991864b079a12801e2cc56b988 Mon Sep 17 00:00:00 2001 From: Tai Groot Date: Tue, 2 Aug 2022 23:12:35 -0700 Subject: [PATCH] tap and swipe replay works --- capture.go | 12 +++++++++--- examples/injection/main.go | 35 +++++++++++++++++++++++++++++++++++ examples/taps/main.go | 19 ++++++++++++++----- shell.go | 32 ++++++++++++++++++++++++++------ 4 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 examples/injection/main.go diff --git a/capture.go b/capture.go index 015639c..0d91e1a 100644 --- a/capture.go +++ b/capture.go @@ -2,6 +2,7 @@ package adb import ( "context" + "errors" "log" "regexp" "strconv" @@ -151,10 +152,15 @@ func (d Device) CaptureSequence(ctx context.Context) (t TapSequence, err error) // this command will never finish without ctx expiring. As a result, // it will always return error code 130 if successful stdout, _, errCode, err := execute(ctx, []string{"shell", "getevent", "-tl"}) - if errCode != 130 { - // TODO remove log output here - log.Printf("Expected error code 130, but got %d\n", errCode) + // TODO better error checking here + if errors.Is(err, ErrUnspecified) { + err = nil } + if errCode != 130 && errCode != -1 { + // TODO remove log output here + log.Printf("Expected error code 130 or -1, but got %d\n", errCode) + } + if stdout == "" { return TapSequence{}, ErrStdoutEmpty } diff --git a/examples/injection/main.go b/examples/injection/main.go new file mode 100644 index 0000000..af7be0d --- /dev/null +++ b/examples/injection/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "context" + "fmt" + + "github.com/taigrr/adb" +) + +var command string + +func init() { + // TODO allow for any input to be used as the command + command = "ls" +} + +func main() { + ctx := context.TODO() + devs, err := adb.Devices(ctx) + if err != nil { + fmt.Printf("Error enumerating devices: %v\n", err) + return + } + for _, dev := range devs { + if !dev.IsAuthorized { + fmt.Printf("Dev `%s` is not authorized, authorize it to continue.\n", dev.SerialNo) + continue + } + err := dev.GoHome(ctx) + if err != nil { + // handle error here + fmt.Printf("Error: %v\n", err) + } + } +} diff --git a/examples/taps/main.go b/examples/taps/main.go index 1fa88b1..6855f4d 100644 --- a/examples/taps/main.go +++ b/examples/taps/main.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "time" "github.com/taigrr/adb" ) @@ -15,7 +16,8 @@ func init() { } func main() { - ctx := context.TODO() + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() devs, err := adb.Devices(ctx) if err != nil { fmt.Printf("Error enumerating devices: %v\n", err) @@ -26,11 +28,18 @@ func main() { fmt.Printf("Dev `%s` is not authorized, authorize it to continue.\n", dev.SerialNo) continue } - w, h, err := dev.GetScreenResolution(ctx) + //w, h, err := dev.GetScreenResolution(ctx) + //if err != nil { + // // handle error here + // fmt.Printf("Error: %v\n", err) + //} + fmt.Printf("Begin tapping on device %s now...\n", dev.SerialNo) + t, err := dev.CaptureSequence(ctx) if err != nil { - // handle error here - fmt.Printf("Error: %v\n", err) + fmt.Printf("Error capturing sequence: %v\n", err) + return } - fmt.Printf("%s screen resolution: %dx%d\n", dev.SerialNo, w, h) + fmt.Println("Sequence captured, replaying now...") + dev.ReplayTapSequence(context.TODO(), t) } } diff --git a/shell.go b/shell.go index 80c1437..ddb2edf 100644 --- a/shell.go +++ b/shell.go @@ -51,7 +51,13 @@ func parseScreenResolution(in string) (int, int, error) { } func (d Device) Tap(ctx context.Context, X, Y int) error { - return nil + cmd := []string{ + "-s", string(d.SerialNo), "shell", + "input", "tap", + strconv.Itoa(X), strconv.Itoa(Y), + } + _, _, _, err := execute(ctx, cmd) + return err } // Simulates a long press @@ -59,30 +65,44 @@ func (d Device) Tap(ctx context.Context, X, Y int) error { // Under the hood, this calls swipe with the same start and end coordinates // with a duration of 250ms func (d Device) LongPress(ctx context.Context, X, Y int) error { - return nil + return d.Swipe(ctx, X, Y, X, Y, time.Millisecond*250) } func (d Device) Swipe(ctx context.Context, X1, Y1, X2, Y2 int, duration time.Duration) error { - return nil + cmd := []string{ + "-s", string(d.SerialNo), "shell", + "input", "swipe", + strconv.Itoa(X1), strconv.Itoa(Y1), + strconv.Itoa(X2), strconv.Itoa(Y2), + strconv.Itoa(int(duration.Milliseconds())), + } + _, _, _, err := execute(ctx, cmd) + return err } // Equivalent to pressing the home button // // Calls `input keyevent KEYCODE_HOME` under the hood func (d Device) GoHome(ctx context.Context) error { - return nil + cmd := []string{"-s", string(d.SerialNo), "shell", "input", "keyevent", "KEYCODE_HOME"} + _, _, _, err := execute(ctx, cmd) + return err } //Equivalent to pressing the back button // // Calls `input keyevent KEYCODE_BACK` under the hood func (d Device) GoBack(ctx context.Context) error { - return nil + cmd := []string{"-s", string(d.SerialNo), "shell", "input", "keyevent", "KEYCODE_BACK"} + _, _, _, err := execute(ctx, cmd) + return err } // Equivalent to pushing the app switcher. You probably want to call this twice. // // Calls `input keyevent KEYCODE_APP_SWITCH` under the hood func (d Device) SwitchApp(ctx context.Context) error { - return nil + cmd := []string{"-s", string(d.SerialNo), "shell", "input", "keyevent", "KEYCODE_APP_SWITCH"} + _, _, _, err := execute(ctx, cmd) + return err }