Scrcpy无线连接
- 通过 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()
}
}