mirror of https://github.com/mvdan/fdroidcl.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
3.0 KiB
156 lines
3.0 KiB
/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */ |
|
/* See LICENSE for licensing information */ |
|
|
|
package adb |
|
|
|
import ( |
|
"bufio" |
|
"fmt" |
|
"net" |
|
"os/exec" |
|
"regexp" |
|
"strconv" |
|
"strings" |
|
) |
|
|
|
const ( |
|
port = 5037 |
|
) |
|
|
|
func IsServerRunning() bool { |
|
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", port)) |
|
if err != nil { |
|
return false |
|
} |
|
conn.Close() |
|
return true |
|
} |
|
|
|
func StartServer() error { |
|
cmd := exec.Command("adb", "start-server") |
|
err := cmd.Run() |
|
if err != nil { |
|
return err |
|
} |
|
return nil |
|
} |
|
|
|
type Device struct { |
|
Id string |
|
Usb string |
|
Product string |
|
Model string |
|
Device string |
|
} |
|
|
|
var deviceRegex = regexp.MustCompile(`^([^\s]+)\s+device(.*)$`) |
|
|
|
func Devices() ([]Device, error) { |
|
cmd := exec.Command("adb", "devices", "-l") |
|
stdout, err := cmd.StdoutPipe() |
|
if err != nil { |
|
return nil, err |
|
} |
|
if err := cmd.Start(); err != nil { |
|
return nil, err |
|
} |
|
var devices []Device |
|
scanner := bufio.NewScanner(stdout) |
|
for scanner.Scan() { |
|
line := scanner.Text() |
|
m := deviceRegex.FindStringSubmatch(line) |
|
if m == nil { |
|
continue |
|
} |
|
device := Device{ |
|
Id: m[1], |
|
} |
|
extras := m[2] |
|
for _, extra := range strings.Split(extras, " ") { |
|
sp := strings.SplitN(extra, ":", 2) |
|
if len(sp) < 2 { |
|
continue |
|
} |
|
switch sp[0] { |
|
case "usb": |
|
device.Usb = sp[1] |
|
case "product": |
|
device.Product = sp[1] |
|
case "model": |
|
device.Model = sp[1] |
|
case "device": |
|
device.Device = sp[1] |
|
} |
|
} |
|
devices = append(devices, device) |
|
} |
|
return devices, nil |
|
} |
|
|
|
func (d Device) AdbCmd(args ...string) *exec.Cmd { |
|
cmdArgs := append([]string{"-s", d.Id}, args...) |
|
return exec.Command("adb", cmdArgs...) |
|
} |
|
|
|
func (d Device) AdbShell(args ...string) *exec.Cmd { |
|
shellArgs := append([]string{"shell"}, args...) |
|
return d.AdbCmd(shellArgs...) |
|
} |
|
|
|
func (d Device) Install(path string) error { |
|
cmd := d.AdbCmd("install", path) |
|
if err := cmd.Start(); err != nil { |
|
return err |
|
} |
|
return nil |
|
} |
|
|
|
func (d Device) Uninstall(pkg string) error { |
|
cmd := d.AdbCmd("uninstall", pkg) |
|
if err := cmd.Start(); err != nil { |
|
return err |
|
} |
|
return nil |
|
} |
|
|
|
type Package struct { |
|
ID string |
|
VCode int |
|
VName string |
|
} |
|
|
|
var ( |
|
packageRegex = regexp.MustCompile(`^ Package \[([^\s]+)\]`) |
|
verCodeRegex = regexp.MustCompile(`^ versionCode=([0-9]+)`) |
|
verNameRegex = regexp.MustCompile(`^ versionName=(.+)`) |
|
) |
|
|
|
func (d Device) Installed() ([]Package, error) { |
|
cmd := d.AdbShell("dumpsys", "package", "packages") |
|
stdout, err := cmd.StdoutPipe() |
|
if err != nil { |
|
return nil, err |
|
} |
|
if err := cmd.Start(); err != nil { |
|
return nil, err |
|
} |
|
var packages []Package |
|
scanner := bufio.NewScanner(stdout) |
|
var cur *Package |
|
for scanner.Scan() { |
|
l := scanner.Text() |
|
if m := packageRegex.FindStringSubmatch(l); m != nil { |
|
packages = append(packages, Package{ID: m[1]}) |
|
cur = &packages[len(packages)-1] |
|
} else if m := verCodeRegex.FindStringSubmatch(l); m != nil { |
|
n, err := strconv.Atoi(m[1]) |
|
if err != nil { |
|
panic(err) |
|
} |
|
cur.VCode = n |
|
} else if m := verNameRegex.FindStringSubmatch(l); m != nil { |
|
cur.VName = m[1] |
|
} |
|
} |
|
return packages, nil |
|
}
|
|
|