V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
hongxi2200
V2EX  ›  Go 编程语言

Golang 实现的与 iOS 设备 进行通信的跨平台工具库

  •  
  •   hongxi2200 ·
    electricbubble · 2021-05-12 23:49:31 +08:00 · 2029 次点击
    这是一个创建于 1325 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目地址

    Go Module 版本: https://github.com/electricbubble/gidevice
    CLI 版本: https://github.com/electricbubble/gidevice-cli

    项目说明

    使用 Golang 实现的的与 iOS 设备 进行通信的跨平台工具库

    所有功能无需越狱
    macOS 可直接使用
    Windows 需要先安装 iTunes 或者 usbmuxd
    Linux 或其他需先安装 usbmuxd

    已实现功能:

    • 设备列表查询
    • 开发者镜像挂载
    • App 启 /停 /卸载 /安装
    • 端口转发
    • 截图
    • XCTest
    • Syslog
    • CrashReport
    • 沙盒文件访问
    • 定位修改 /恢复
    • Pair

    部分 CLI 版本使用示例

    Devices

    $ gidevice list
    

    DeveloperDiskImage

    $ gidevice mount -l
    # gidevice mount -l -u=39xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7
    $ gidevice mount -d=/path/.../DeviceSupport/14.4/
    $ gidevice mount /path/.../DeviceSupport/14.4/DeveloperDiskImage.dmg /path/.../DeviceSupport/14.4/DeveloperDiskImage.dmg.signature
    

    Forward

    # Default port local=8100 remote=8100
    $ gidevice forward
    $ gidevice forward -l=9100 -r=9100 -u=39xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7
    

    部分 Go Module 版本使用示例

    Devices

    package main
    
    import (
    	giDevice "github.com/electricbubble/gidevice"
    	"log"
    )
    
    func main() {
    	usbmux, err := giDevice.NewUsbmux()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	devices, err := usbmux.Devices()
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	for _, dev := range devices {
    		log.Println(dev.Properties().SerialNumber, dev.Properties().ProductID, dev.Properties().DeviceID)
    	}
    }
    
    

    DeveloperDiskImage

    package main
    
    import (
    	"encoding/base64"
    	giDevice "github.com/electricbubble/gidevice"
    	"log"
    )
    
    func main() {
    	usbmux, err := giDevice.NewUsbmux()
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	devices, err := usbmux.Devices()
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	if len(devices) == 0 {
    		log.Fatal("No Device")
    	}
    
    	d := devices[0]
    
    	imageSignatures, err := d.Images()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	for i, imgSign := range imageSignatures {
    		log.Printf("[%d] %s\n", i+1, base64.StdEncoding.EncodeToString(imgSign))
    	}
    
    	dmgPath := "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/14.4/DeveloperDiskImage.dmg"
    	signaturePath := "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/14.4/DeveloperDiskImage.dmg.signature"
    
    	err = d.MountDeveloperDiskImage(dmgPath, signaturePath)
    	if err != nil {
    		log.Fatalln(err)
    	}
    }
    
    

    App

    package main
    
    import (
    	giDevice "github.com/electricbubble/gidevice"
    	"log"
    	"path/filepath"
    )
    
    func main() {
    	usbmux, err := giDevice.NewUsbmux()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	devices, err := usbmux.Devices()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	if len(devices) == 0 {
    		log.Fatalln("No Device")
    	}
    
    	d := devices[0]
    
    	bundleID := "com.apple.Preferences"
    	pid, err := d.AppLaunch(bundleID)
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	err = d.AppKill(pid)
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	runningProcesses, err := d.AppRunningProcesses()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	for _, process := range runningProcesses {
    		if process.IsApplication {
    			log.Printf("%4d\t%-24s\t%-36s\t%s\n", process.Pid, process.Name, filepath.Base(process.RealAppName), process.StartDate)
    		}
    	}
    }
    
    

    Screenshot

    package main
    
    import (
    	giDevice "github.com/electricbubble/gidevice"
    	"image"
    	"image/jpeg"
    	"image/png"
    	"log"
    	"os"
    )
    
    func main() {
    	usbmux, err := giDevice.NewUsbmux()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	devices, err := usbmux.Devices()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	if len(devices) == 0 {
    		log.Fatalln("No Device")
    	}
    
    	d := devices[0]
    
    	raw, err := d.Screenshot()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	img, format, err := image.Decode(raw)
    	if err != nil {
    		log.Fatalln(err)
    	}
    	userHomeDir, _ := os.UserHomeDir()
    	file, err := os.Create(userHomeDir + "/Desktop/s1." + format)
    	if err != nil {
    		log.Fatalln(err)
    	}
    	defer func() { _ = file.Close() }()
    	switch format {
    	case "png":
    		err = png.Encode(file, img)
    	case "jpeg":
    		err = jpeg.Encode(file, img, nil)
    	}
    	if err != nil {
    		log.Fatalln(err)
    	}
    	log.Println(file.Name())
    }
    
    

    SimulateLocation

    package main
    
    import (
    	giDevice "github.com/electricbubble/gidevice"
    	"log"
    )
    
    func main() {
    	usbmux, err := giDevice.NewUsbmux()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	devices, err := usbmux.Devices()
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	if len(devices) == 0 {
    		log.Fatalln("No Device")
    	}
    
    	d := devices[0]
    
    	// https://api.map.baidu.com/lbsapi/getpoint/index.html
    	if err = d.SimulateLocationUpdate(116.024067, 40.362639, giDevice.CoordinateSystemBD09); err != nil {
    		log.Fatalln(err)
    	}
    
    	// https://developer.amap.com/tools/picker
    	// https://lbs.qq.com/tool/getpoint/index.html
    	// if err = d.SimulateLocationUpdate(120.116979, 30.252876, giDevice.CoordinateSystemGCJ02); err != nil {
    	// 	log.Fatalln(err)
    	// }
    
    	// if err = d.SimulateLocationUpdate(121.499763, 31.239580,giDevice.CoordinateSystemWGS84); err != nil {
    	// if err = d.SimulateLocationUpdate(121.499763, 31.239580); err != nil {
    	// 	log.Fatalln(err)
    	// }
    
    	// err = d.SimulateLocationRecover()
    	// if err != nil {
    	// 	log.Fatalln(err)
    	// }
    }
    
    
    15 条回复    2021-08-19 10:46:32 +08:00
    janxin
        1
    janxin  
       2021-05-13 07:21:55 +08:00 via iPhone   ❤️ 1
    桥了一下 libimobiledevice ?
    hongxi2200
        2
    hongxi2200  
    OP
       2021-05-13 08:56:46 +08:00 via iPhone
    @janxin
    是哒,不过没抄全,只实现了基本功能。。
    janxin
        3
    janxin  
       2021-05-13 08:57:57 +08:00 via iPhone
    @hongxi2200 🐂体力活啊
    learningman
        4
    learningman  
       2021-05-13 09:10:29 +08:00 via Android
    一眼看成 Google 实现的。。。
    hongxi2200
        5
    hongxi2200  
    OP
       2021-05-13 09:57:21 +08:00
    @janxin
    抄作业而已。。。
    hongxi2200
        6
    hongxi2200  
    OP
       2021-05-13 09:59:48 +08:00
    @learningman
    是用的 `Golang` 翻译了 [libimobiledevice]( https://github.com/libimobiledevice/libimobiledevice) 的代码呀
    dxatgp02
        7
    dxatgp02  
       2021-05-13 10:31:26 +08:00
    用这工具能做什么事?
    hongxi2200
        8
    hongxi2200  
    OP
       2021-05-13 10:32:47 +08:00
    @work19990909

    已实现功能:

    - 设备列表查询
    - 开发者镜像挂载
    - App 启 /停 /卸载 /安装
    - 端口转发
    - 截图
    - XCTest
    - Syslog
    - CrashReport
    - 沙盒文件访问
    - 定位修改 /恢复
    - Pair
    hongxi2200
        9
    hongxi2200  
    OP
       2021-05-13 10:33:35 +08:00
    @work19990909
    电脑连上 iOS 设备 就可以干这些事儿
    dxatgp02
        10
    dxatgp02  
       2021-05-13 11:11:33 +08:00
    @hongxi2200 厉害,等于实现远程启动 APP
    hongxi2200
        11
    hongxi2200  
    OP
       2021-05-13 11:49:44 +08:00
    @work19990909
    额,也不算 `远程`
    iOS 设备 还是需要 `usb` 连上 电脑 的
    > 无线调试 也试过。。不是每个功能都用 无线调试 成功。。
    95276
        12
    95276  
       2021-05-14 11:25:36 +08:00
    楼主厉害,这个修改一下搞到一个小型 linux 设备上就可以随时改定位了.
    市场上好像有这种东西.
    hongxi2200
        13
    hongxi2200  
    OP
       2021-05-14 13:16:19 +08:00
    @95276
    以前在淘宝上看到过有人卖 C# 版的。。
    hongxi2200
        14
    hongxi2200  
    OP
       2021-05-14 13:19:03 +08:00
    @95276

    哈哈哈,我的确也有计划用 树莓派 搞一个玩
    visionsmile
        15
    visionsmile  
       2021-08-19 10:46:32 +08:00
    请问能实现端口的 reverse 反向转发吗?把 PC/Mac 的端口转发到 IOS 上。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2781 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 13:41 · PVG 21:41 · LAX 05:41 · JFK 08:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.