• 通过 ADB 配对
  • 在手机无线调试中使用配对码配对设备,显示设备IP和配对端口

    adb pair <设备IP>:<配对端口>
  • 输入配对码完成配对
  • 连接设备

    adb connect <设备IP>:<无线调试端口>
  • 安装scrcpy

    https://github.com/Genymobile/scrcpy

  • 启动scrcpy

脚本连接,通过nmap扫描端口进行连接

// autoscrcpy.go
package main

import (
    "context"
    "flag"
    "fmt"
    "log"
    "os/exec"
    "sort"
    "sync"
    "syscall"
    "time"

    nmap "github.com/Ullaakut/nmap/v3"
)

var startPort = 1024
var endPort = 65535
var numThreads = 10

const SW_HIDE = 0 // 隐藏窗口
var (
    user32           = syscall.NewLazyDLL("user32.dll")
    kernel32         = syscall.NewLazyDLL("kernel32.dll")
    getConsoleWindow = kernel32.NewProc("GetConsoleWindow")
    showWindow       = user32.NewProc("ShowWindow")
)

func hideConsole() {
    hwnd, _, _ := getConsoleWindow.Call()
    if hwnd != 0 {
        showWindow.Call(hwnd, SW_HIDE)
    }
}

func scanPort(deviceIPAddress string, _startPort, _endPort int, wg *sync.WaitGroup, openPortsChan chan<- int) {
    defer wg.Done() // 标记 Goroutine 任务完成
    ctx, _ := context.WithTimeout(context.Background(), 5*time.Minute)
    portRange := fmt.Sprintf("%d-%d", _startPort, _endPort)
    scanner, err := nmap.NewScanner(
        ctx,
        nmap.WithTargets(deviceIPAddress),
        nmap.WithPorts(portRange),
        nmap.WithTimingTemplate(nmap.TimingAggressive),
    )
    if err != nil {
        log.Fatalf("unable to create nmap scanner: %v", err)
    }

    result, warnings, err := scanner.Run()
    if len(*warnings) > 0 {
        log.Printf("run finished with warnings: %s\n", *warnings)
    }
    if err != nil {
        log.Fatalf("unable to run nmap scan: %v", err)
    }

    for _, host := range result.Hosts {
        if len(host.Ports) == 0 || len(host.Addresses) == 0 {
            continue
        }
        for _, port := range host.Ports {
            if port.Status() == nmap.Open {
                openPortsChan <- int(port.ID)
            }
        }
    }

}

func adbConnect(deviceIPAddress string, port int) bool {
    cmd := exec.Command("adb", "connect", fmt.Sprintf("%s:%d", deviceIPAddress, port))
    cmdOutput, cmdErr := cmd.CombinedOutput()
    fmt.Printf("AdbConnect Output: %s\n", cmdOutput)
    if cmdErr != nil {
        return false
    } else {
        return true
    }
}

func adbDisconnect() {
    cmd := exec.Command("adb", "disconnect")
    cmdOutput, _ := cmd.CombinedOutput()
    fmt.Printf("AdbDisconnect Output: %s\n", cmdOutput)
}
func adbKillServer() {
    cmd := exec.Command("adb", "kill-server")
    cmdOutput, _ := cmd.CombinedOutput()
    fmt.Printf("AdbKillServer Output: %s\n", cmdOutput)
}

func scrcpyStart() bool {
    cmd := exec.Command("scrcpy", "--turn-screen-off", "--no-audio")
    cmdOutput, cmdErr := cmd.CombinedOutput()
    fmt.Printf("ScrcpyStart Output: %s\n", cmdOutput)
    if cmdErr != nil {
        return false
    } else {
        return true
    }

}

func main() {
    deviceIPAddress := flag.String("ip", "10.66.3.60", "输入设备IP地址")
    flag.Parse()
    fmt.Printf("设备IP地址:%s\n", *deviceIPAddress)

    totalPorts := endPort - startPort + 1 // 总端口数量
    portsPerThread := totalPorts / numThreads
    var wg sync.WaitGroup           // 用于等待所有 Goroutine 完成
    openPortsChan := make(chan int) // 结果通道

    for i := 0; i < numThreads; i++ {
        _startPort := startPort + i*portsPerThread
        _endPort := _startPort + portsPerThread - 1

        if i == numThreads-1 {
            _endPort = 65535
        }

        wg.Add(1)
        go scanPort(*deviceIPAddress, _startPort, _endPort, &wg, openPortsChan)
    }
    go func() {
        wg.Wait()
        close(openPortsChan)
    }()
    var openPorts []int
    for port := range openPortsChan {
        openPorts = append(openPorts, port)
    }
    // 对端口进行从大到小的排序
    sort.Slice(openPorts, func(i, j int) bool {
        return openPorts[i] > openPorts[j]
    })

    // 打印排序后的端口列表
    fmt.Println("Ports sorted from largest to smallest:", openPorts)

    for _, port := range openPorts {
        adbDisconnect()
        if adbConnect(*deviceIPAddress, port) {
            hideConsole()
            if scrcpyStart() {
                adbKillServer()
                break
            }
        }
        adbKillServer()
    }

}