diff --git a/errors.go b/errors.go index 5c26ec2..b508228 100644 --- a/errors.go +++ b/errors.go @@ -11,5 +11,6 @@ var ( ErrNotInstalled = errors.New("adb is not installed or not in PATH") ErrCoordinatesNotFound = errors.New("coordinates for an input event are missing") ErrConnUSB = errors.New("cannot call connect to device using USB") + ErrResolutionParseFail = errors.New("failed to parse screen size from input text") ErrUnspecified = errors.New("an unknown error has occurred, please open an issue on GitHub") ) diff --git a/examples/taps/main.go b/examples/taps/main.go new file mode 100644 index 0000000..1fa88b1 --- /dev/null +++ b/examples/taps/main.go @@ -0,0 +1,36 @@ +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 + } + w, h, err := dev.GetScreenResolution(ctx) + if err != nil { + // handle error here + fmt.Printf("Error: %v\n", err) + } + fmt.Printf("%s screen resolution: %dx%d\n", dev.SerialNo, w, h) + } +} diff --git a/shell.go b/shell.go index b28da6d..80c1437 100644 --- a/shell.go +++ b/shell.go @@ -2,6 +2,8 @@ package adb import ( "context" + "regexp" + "strconv" "time" "github.com/google/shlex" @@ -26,8 +28,26 @@ func (d Device) Shell(ctx context.Context, command string) (stdout string, stder // adb shell wm size // Physical size: 1440x3120 -func (d Device) GetScreenResolution(ctx context.Context) (width int, lenght int, err error) { - return 0, 0, nil +func (d Device) GetScreenResolution(ctx context.Context) (width int, height int, err error) { + cmd := []string{"-s", string(d.SerialNo), "shell", "wm", "size"} + stdout, _, _, err := execute(ctx, cmd) + if err != nil { + return -1, -1, err + } + return parseScreenResolution(stdout) +} + +// Parses input, example: +// Physical size: 1440x3040 +func parseScreenResolution(in string) (int, int, error) { + r := regexp.MustCompile(`Physical size: ([0-9]+)x([0-9]+)`) + resStr := r.FindStringSubmatch(in) + if len(resStr) != 3 { + return -1, -1, ErrResolutionParseFail + } + w, _ := strconv.Atoi(resStr[1]) + h, _ := strconv.Atoi(resStr[2]) + return w, h, nil } func (d Device) Tap(ctx context.Context, X, Y int) error { diff --git a/shell_test.go b/shell_test.go new file mode 100644 index 0000000..fb7a4d2 --- /dev/null +++ b/shell_test.go @@ -0,0 +1,36 @@ +package adb + +import "testing" + +func Test_parseScreenResolution(t *testing.T) { + type args struct { + in string + } + tests := []struct { + name string + args args + wantWidth int + wantLength int + wantErr bool + }{ + {name: "Pixel 4XL", args: args{in: "Physical size: 1440x3040"}, wantWidth: 1440, wantLength: 3040, wantErr: false}, + {name: "Pixel XL", args: args{in: "Physical size: 1440x2560"}, wantWidth: 1440, wantLength: 2560, wantErr: false}, + {name: "garbage", args: args{in: "asdfhjkla"}, wantWidth: -1, wantLength: -1, wantErr: true}, + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + w, l, err := parseScreenResolution(tt.args.in) + if (err != nil) != tt.wantErr { + t.Errorf("parseScreenResolution() error = %v, wantErr %v", err, tt.wantErr) + return + } + if w != tt.wantWidth { + t.Errorf("parseScreenResolution() got = %v, want %v", w, tt.wantWidth) + } + if l != tt.wantLength { + t.Errorf("parseScreenResolution() got1 = %v, want %v", l, tt.wantLength) + } + }) + } +}