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

2021-05-12 23:49:31 +08:00
 hongxi2200

项目地址

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

项目说明

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

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

已实现功能:

部分 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)
	// }
}

1995 次点击
所在节点    Go 编程语言
15 条回复
janxin
2021-05-13 07:21:55 +08:00
桥了一下 libimobiledevice ?
hongxi2200
2021-05-13 08:56:46 +08:00
@janxin
是哒,不过没抄全,只实现了基本功能。。
janxin
2021-05-13 08:57:57 +08:00
@hongxi2200 🐂体力活啊
learningman
2021-05-13 09:10:29 +08:00
一眼看成 Google 实现的。。。
hongxi2200
2021-05-13 09:57:21 +08:00
@janxin
抄作业而已。。。
hongxi2200
2021-05-13 09:59:48 +08:00
@learningman
是用的 `Golang` 翻译了 [libimobiledevice]( https://github.com/libimobiledevice/libimobiledevice) 的代码呀
dxatgp02
2021-05-13 10:31:26 +08:00
用这工具能做什么事?
hongxi2200
2021-05-13 10:32:47 +08:00
@work19990909

已实现功能:

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

哈哈哈,我的确也有计划用 树莓派 搞一个玩
visionsmile
2021-08-19 10:46:32 +08:00
请问能实现端口的 reverse 反向转发吗?把 PC/Mac 的端口转发到 IOS 上。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/776598

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX