mirror of
https://github.com/taigrr/adb.git
synced 2026-04-02 02:58:42 -07:00
Adding code from twitch stream https://www.twitch.tv/videos/1548041732
This commit is contained in:
104
adb.go
104
adb.go
@@ -2,8 +2,11 @@ package adb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Serial string
|
type Serial string
|
||||||
@@ -20,15 +23,18 @@ const (
|
|||||||
// Device contains the information necessary to connect to and
|
// Device contains the information necessary to connect to and
|
||||||
// communicate with a device
|
// communicate with a device
|
||||||
type Device struct {
|
type Device struct {
|
||||||
SerialNo Serial
|
IsAuthorized bool
|
||||||
ConnType Connection
|
SerialNo Serial
|
||||||
IP net.IPAddr
|
ConnType Connection
|
||||||
FileHandle string // TODO change this to a discrete type
|
IP net.IPAddr
|
||||||
|
Port uint
|
||||||
|
FileHandle string // TODO change this to a discrete type
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provides a connection string for Connect()
|
// Provides a connection string for Connect()
|
||||||
type ConnOptions struct {
|
type ConnOptions struct {
|
||||||
Address net.IPAddr
|
Address net.IPAddr
|
||||||
|
Port uint
|
||||||
SerialNo Serial
|
SerialNo Serial
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,14 +43,37 @@ type ConnOptions struct {
|
|||||||
// This will return a Device struct, which can be used to call other methods.
|
// This will return a Device struct, which can be used to call other methods.
|
||||||
// If the connection fails or cannot complete on time, Connect will return an error.
|
// If the connection fails or cannot complete on time, Connect will return an error.
|
||||||
func Connect(ctx context.Context, opts ConnOptions) (Device, error) {
|
func Connect(ctx context.Context, opts ConnOptions) (Device, error) {
|
||||||
|
if opts.Port == 0 {
|
||||||
|
opts.Port = 5555
|
||||||
|
}
|
||||||
return Device{}, nil
|
return Device{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d Device) ConnString() string {
|
||||||
|
if d.Port == 0 {
|
||||||
|
d.Port = 5555
|
||||||
|
}
|
||||||
|
return d.IP.String() + ":" + strconv.Itoa(int(d.Port))
|
||||||
|
}
|
||||||
|
|
||||||
// Connect to a previously discovered device.
|
// Connect to a previously discovered device.
|
||||||
//
|
//
|
||||||
// This function is helpful when connecting to a device found from the Devices call
|
// This function is helpful when connecting to a device found from the Devices call
|
||||||
// or when reconnecting to a previously connected device.
|
// or when reconnecting to a previously connected device.
|
||||||
func (d Device) Connect(ctx context.Context) (Device, error) {
|
func (d Device) Reconnect(ctx context.Context) (Device, error) {
|
||||||
|
if d.ConnType == USB {
|
||||||
|
return d, ErrConnUSB
|
||||||
|
}
|
||||||
|
cmd := []string{"connect", d.ConnString()}
|
||||||
|
stdout, stderr, errcode, err := execute(ctx, cmd)
|
||||||
|
if err != nil {
|
||||||
|
return d, err
|
||||||
|
}
|
||||||
|
if errcode != 0 {
|
||||||
|
return d, ErrUnspecified
|
||||||
|
}
|
||||||
|
_, _ = stdout, stderr
|
||||||
|
// TODO capture and store serial number into d before returning
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +83,35 @@ func (d Device) Connect(ctx context.Context) (Device, error) {
|
|||||||
// It is recommended to call IsConnected() against the device you're interested in using and connect
|
// It is recommended to call IsConnected() against the device you're interested in using and connect
|
||||||
// if not already connected before proceeding.
|
// if not already connected before proceeding.
|
||||||
func Devices(ctx context.Context) ([]Device, error) {
|
func Devices(ctx context.Context) ([]Device, error) {
|
||||||
return []Device{}, nil
|
cmd := []string{"devices"}
|
||||||
|
stdout, _, errcode, err := execute(ctx, cmd)
|
||||||
|
devs := []Device{}
|
||||||
|
if err != nil {
|
||||||
|
return devs, err
|
||||||
|
}
|
||||||
|
if errcode != 0 {
|
||||||
|
return devs, ErrUnspecified
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseDevices(stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDevices(stdout string) ([]Device, error) {
|
||||||
|
devs := []Device{}
|
||||||
|
lines := strings.Split(stdout, "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
words := strings.Fields(line)
|
||||||
|
if len(words) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d := Device{
|
||||||
|
SerialNo: Serial(words[0]),
|
||||||
|
IsAuthorized: words[1] == "device",
|
||||||
|
}
|
||||||
|
devs = append(devs, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
return devs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect from a device.
|
// Disconnect from a device.
|
||||||
@@ -88,6 +145,10 @@ func (d Device) Push(ctx context.Context, src, dest string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if errcode != 0 {
|
||||||
|
return ErrUnspecified
|
||||||
|
}
|
||||||
|
_, _ = stdout, stderr
|
||||||
// TODO check the return strings of the output to determine if the file copy succeeded
|
// TODO check the return strings of the output to determine if the file copy succeeded
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -96,6 +157,19 @@ func (d Device) Push(ctx context.Context, src, dest string) error {
|
|||||||
//
|
//
|
||||||
// Returns an error if src does not exist, or if dest already exists or cannot be created
|
// Returns an error if src does not exist, or if dest already exists or cannot be created
|
||||||
func (d Device) Pull(ctx context.Context, src, dest string) error {
|
func (d Device) Pull(ctx context.Context, src, dest string) error {
|
||||||
|
_, err := os.Stat(src)
|
||||||
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stdout, stderr, errcode, err := execute(ctx, []string{"pull", src, dest})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if errcode != 0 {
|
||||||
|
return ErrUnspecified
|
||||||
|
}
|
||||||
|
_, _ = stdout, stderr
|
||||||
|
// TODO check the return strings of the output to determine if the file copy succeeded
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +178,15 @@ func (d Device) Pull(ctx context.Context, src, dest string) error {
|
|||||||
// Once the device reboots, you must manually reconnect.
|
// Once the device reboots, you must manually reconnect.
|
||||||
// Returns an error if the device cannot be contacted
|
// Returns an error if the device cannot be contacted
|
||||||
func (d Device) Reboot(ctx context.Context) error {
|
func (d Device) Reboot(ctx context.Context) error {
|
||||||
|
stdout, stderr, errcode, err := execute(ctx, []string{"reboot"})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if errcode != 0 {
|
||||||
|
return ErrUnspecified
|
||||||
|
}
|
||||||
|
_, _ = stdout, stderr
|
||||||
|
// TODO check the return strings of the output to determine if the file copy succeeded
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,5 +198,14 @@ func (d Device) Reboot(ctx context.Context) error {
|
|||||||
// Once adb is relaunched as root, it will stay root until rebooted.
|
// Once adb is relaunched as root, it will stay root until rebooted.
|
||||||
// returns true if the device successfully relaunched as root
|
// returns true if the device successfully relaunched as root
|
||||||
func (d Device) Root(ctx context.Context) (success bool, err error) {
|
func (d Device) Root(ctx context.Context) (success bool, err error) {
|
||||||
|
stdout, stderr, errcode, err := execute(ctx, []string{"root"})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if errcode != 0 {
|
||||||
|
return false, ErrUnspecified
|
||||||
|
}
|
||||||
|
_, _ = stdout, stderr
|
||||||
|
// TODO check the return strings of the output to determine if the file copy succeeded
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|||||||
43
adb_test.go
Normal file
43
adb_test.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package adb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_parseDevices(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
stdout string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want []Device
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "2 auth 1 unauth", args: args{stdout: `List of devices attached
|
||||||
|
19291FDEE0023W device
|
||||||
|
9B061FFBA00BC9 device
|
||||||
|
HT75R0202681 unauthorized`},
|
||||||
|
wantErr: false,
|
||||||
|
want: []Device{
|
||||||
|
{IsAuthorized: true, SerialNo: "19291FDEE0023W"},
|
||||||
|
{IsAuthorized: true, SerialNo: "9B061FFBA00BC9"},
|
||||||
|
{IsAuthorized: false, SerialNo: "HT75R0202681"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := parseDevices(tt.args.stdout)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("parseDevices() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("parseDevices() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,5 +10,6 @@ var (
|
|||||||
ErrStdoutEmpty = errors.New("stdout expected to contain data but was empty")
|
ErrStdoutEmpty = errors.New("stdout expected to contain data but was empty")
|
||||||
ErrNotInstalled = errors.New("adb is not installed or not in PATH")
|
ErrNotInstalled = errors.New("adb is not installed or not in PATH")
|
||||||
ErrCoordinatesNotFound = errors.New("coordinates for an input event are missing")
|
ErrCoordinatesNotFound = errors.New("coordinates for an input event are missing")
|
||||||
|
ErrConnUSB = errors.New("cannot call connect to device using USB")
|
||||||
ErrUnspecified = errors.New("an unknown error has occurred, please open an issue on GitHub")
|
ErrUnspecified = errors.New("an unknown error has occurred, please open an issue on GitHub")
|
||||||
)
|
)
|
||||||
|
|||||||
1
shell.go
1
shell.go
@@ -12,6 +12,7 @@ import (
|
|||||||
// Instead of using Shell, please consider submitting a PR with the functionality
|
// Instead of using Shell, please consider submitting a PR with the functionality
|
||||||
// you require.
|
// you require.
|
||||||
func (d Device) Shell(ctx context.Context, command string) (stdout string, stderr string, ErrCode int, err error) {
|
func (d Device) Shell(ctx context.Context, command string) (stdout string, stderr string, ErrCode int, err error) {
|
||||||
|
|
||||||
return "", "", 1, nil
|
return "", "", 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user