{"id":13613310,"url":"https://github.com/electricbubble/gidevice","last_synced_at":"2025-04-05T07:05:46.148Z","repository":{"id":37856995,"uuid":"357743524","full_name":"electricbubble/gidevice","owner":"electricbubble","description":"communicate with iOS devices implemented with Golang","archived":false,"fork":false,"pushed_at":"2023-12-12T08:10:02.000Z","size":81,"stargazers_count":280,"open_issues_count":10,"forks_count":70,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-29T06:06:05.256Z","etag":null,"topics":["golang","golang-library","gomod","gomodule","ios","iphone","libimobiledevice","usbmuxd","xcode","xctest"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/electricbubble.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-14T02:01:54.000Z","updated_at":"2025-03-25T13:55:15.000Z","dependencies_parsed_at":"2024-06-18T14:06:13.823Z","dependency_job_id":"0162307a-e53e-4218-ae54-24521af2e84a","html_url":"https://github.com/electricbubble/gidevice","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/electricbubble%2Fgidevice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/electricbubble%2Fgidevice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/electricbubble%2Fgidevice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/electricbubble%2Fgidevice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/electricbubble","download_url":"https://codeload.github.com/electricbubble/gidevice/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247299832,"owners_count":20916190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","golang-library","gomod","gomodule","ios","iphone","libimobiledevice","usbmuxd","xcode","xctest"],"created_at":"2024-08-01T20:00:43.892Z","updated_at":"2025-04-05T07:05:46.125Z","avatar_url":"https://github.com/electricbubble.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Golang-iDevice\n\n[![go doc](https://godoc.org/github.com/electricbubble/gidevice?status.svg)](https://pkg.go.dev/github.com/electricbubble/gidevice?tab=doc#pkg-index)\n[![go report](https://goreportcard.com/badge/github.com/electricbubble/gidevice)](https://goreportcard.com/report/github.com/electricbubble/gidevice)\n[![license](https://img.shields.io/github/license/electricbubble/gidevice)](https://github.com/electricbubble/gidevice/blob/master/LICENSE)\n\n\u003e much more easy to use 👉 [electricbubble/gidevice-cli](https://github.com/electricbubble/gidevice-cli)\n\n## Installation\n\n```shell script\ngo get github.com/electricbubble/gidevice\n```\n\n#### Devices\n\n```go\npackage main\n\nimport (\n\tgiDevice \"github.com/electricbubble/gidevice\"\n\t\"log\"\n)\n\nfunc main() {\n\tusbmux, err := giDevice.NewUsbmux()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tdevices, err := usbmux.Devices()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfor _, dev := range devices {\n\t\tlog.Println(dev.Properties().SerialNumber, dev.Properties().ProductID, dev.Properties().DeviceID)\n\t}\n}\n\n```\n\n### GetValue\n\n```go\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\tgiDevice \"github.com/electricbubble/gidevice\"\n\t\"log\"\n)\n\ntype DeviceDetail struct {\n\tDeviceName                string `json:\"DeviceName,omitempty\"`\n\tDeviceColor               string `json:\"DeviceColor,omitempty\"`\n\tDeviceClass               string `json:\"DeviceClass,omitempty\"`\n\tProductVersion            string `json:\"ProductVersion,omitempty\"`\n\tProductType               string `json:\"ProductType,omitempty\"`\n\tProductName               string `json:\"ProductName,omitempty\"`\n\tModelNumber               string `json:\"ModelNumber,omitempty\"`\n\tSerialNumber              string `json:\"SerialNumber,omitempty\"`\n\tSIMStatus                 string `json:\"SIMStatus,omitempty\"`\n\tPhoneNumber               string `json:\"PhoneNumber,omitempty\"`\n\tCPUArchitecture           string `json:\"CPUArchitecture,omitempty\"`\n\tProtocolVersion           string `json:\"ProtocolVersion,omitempty\"`\n\tRegionInfo                string `json:\"RegionInfo,omitempty\"`\n\tTelephonyCapability       bool   `json:\"TelephonyCapability,omitempty\"`\n\tTimeZone                  string `json:\"TimeZone,omitempty\"`\n\tUniqueDeviceID            string `json:\"UniqueDeviceID,omitempty\"`\n\tWiFiAddress               string `json:\"WiFiAddress,omitempty\"`\n\tWirelessBoardSerialNumber string `json:\"WirelessBoardSerialNumber,omitempty\"`\n\tBluetoothAddress          string `json:\"BluetoothAddress,omitempty\"`\n\tBuildVersion              string `json:\"BuildVersion,omitempty\"`\n}\n\nfunc main() {\n\tusbmux, err := giDevice.NewUsbmux()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tdevices, err := usbmux.Devices()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif len(devices) == 0 {\n\t\tlog.Fatal(\"No Device\")\n\t}\n\n\td := devices[0]\n\n\tdetail, err1 := d.GetValue(\"\", \"\")\n\tif err1 != nil {\n\t\tfmt.Errorf(\"get %s device detail fail : %w\", d.Properties().SerialNumber, err1)\n\t}\n\n\tdata, _ := json.Marshal(detail)\n\td1 := \u0026DeviceDetail{}\n\tjson.Unmarshal(data, d1)\n\tfmt.Println(d1)\n}\n```\n\n#### DeveloperDiskImage\n\n```go\npackage main\n\nimport (\n\t\"encoding/base64\"\n\tgiDevice \"github.com/electricbubble/gidevice\"\n\t\"log\"\n)\n\nfunc main() {\n\tusbmux, err := giDevice.NewUsbmux()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tdevices, err := usbmux.Devices()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif len(devices) == 0 {\n\t\tlog.Fatal(\"No Device\")\n\t}\n\n\td := devices[0]\n\n\timageSignatures, err := d.Images()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tfor i, imgSign := range imageSignatures {\n\t\tlog.Printf(\"[%d] %s\\n\", i+1, base64.StdEncoding.EncodeToString(imgSign))\n\t}\n\n\tdmgPath := \"/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/14.4/DeveloperDiskImage.dmg\"\n\tsignaturePath := \"/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/14.4/DeveloperDiskImage.dmg.signature\"\n\n\terr = d.MountDeveloperDiskImage(dmgPath, signaturePath)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n}\n\n```\n\n#### App\n\n```go\npackage main\n\nimport (\n\tgiDevice \"github.com/electricbubble/gidevice\"\n\t\"log\"\n\t\"path/filepath\"\n)\n\nfunc main() {\n\tusbmux, err := giDevice.NewUsbmux()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tdevices, err := usbmux.Devices()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tif len(devices) == 0 {\n\t\tlog.Fatalln(\"No Device\")\n\t}\n\n\td := devices[0]\n\n\tbundleID := \"com.apple.Preferences\"\n\tpid, err := d.AppLaunch(bundleID)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\terr = d.AppKill(pid)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\trunningProcesses, err := d.AppRunningProcesses()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tfor _, process := range runningProcesses {\n\t\tif process.IsApplication {\n\t\t\tlog.Printf(\"%4d\\t%-24s\\t%-36s\\t%s\\n\", process.Pid, process.Name, filepath.Base(process.RealAppName), process.StartDate)\n\t\t}\n\t}\n}\n\n```\n\n#### Screenshot\n\n```go\npackage main\n\nimport (\n\tgiDevice \"github.com/electricbubble/gidevice\"\n\t\"image\"\n\t\"image/jpeg\"\n\t\"image/png\"\n\t\"log\"\n\t\"os\"\n)\n\nfunc main() {\n\tusbmux, err := giDevice.NewUsbmux()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tdevices, err := usbmux.Devices()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tif len(devices) == 0 {\n\t\tlog.Fatalln(\"No Device\")\n\t}\n\n\td := devices[0]\n\n\traw, err := d.Screenshot()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\timg, format, err := image.Decode(raw)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\tuserHomeDir, _ := os.UserHomeDir()\n\tfile, err := os.Create(userHomeDir + \"/Desktop/s1.\" + format)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\tdefer func() { _ = file.Close() }()\n\tswitch format {\n\tcase \"png\":\n\t\terr = png.Encode(file, img)\n\tcase \"jpeg\":\n\t\terr = jpeg.Encode(file, img, nil)\n\t}\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\tlog.Println(file.Name())\n}\n\n```\n\n#### SimulateLocation\n\n```go\npackage main\n\nimport (\n\tgiDevice \"github.com/electricbubble/gidevice\"\n\t\"log\"\n)\n\nfunc main() {\n\tusbmux, err := giDevice.NewUsbmux()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tdevices, err := usbmux.Devices()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\tif len(devices) == 0 {\n\t\tlog.Fatalln(\"No Device\")\n\t}\n\n\td := devices[0]\n\n\t// https://api.map.baidu.com/lbsapi/getpoint/index.html\n\tif err = d.SimulateLocationUpdate(116.024067, 40.362639, giDevice.CoordinateSystemBD09); err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\t// https://developer.amap.com/tools/picker\n\t// https://lbs.qq.com/tool/getpoint/index.html\n\t// if err = d.SimulateLocationUpdate(120.116979, 30.252876, giDevice.CoordinateSystemGCJ02); err != nil {\n\t// \tlog.Fatalln(err)\n\t// }\n\n\t// if err = d.SimulateLocationUpdate(121.499763, 31.239580,giDevice.CoordinateSystemWGS84); err != nil {\n\t// if err = d.SimulateLocationUpdate(121.499763, 31.239580); err != nil {\n\t// \tlog.Fatalln(err)\n\t// }\n\n\t// err = d.SimulateLocationRecover()\n\t// if err != nil {\n\t// \tlog.Fatalln(err)\n\t// }\n}\n\n```\n\n#### XCTest\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\tgiDevice \"github.com/electricbubble/gidevice\"\n\t\"log\"\n\t\"os\"\n\t\"os/signal\"\n)\n\nfunc main() {\n\tusbmux, err := giDevice.NewUsbmux()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tdevices, err := usbmux.Devices()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif len(devices) == 0 {\n\t\tlog.Fatal(\"No Device\")\n\t}\n\n\td := devices[0]\n\n\tout, cancel, err := d.XCTest(\"com.leixipaopao.WebDriverAgentRunner.xctrunner\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tdone := make(chan os.Signal, 1)\n\tsignal.Notify(done, os.Interrupt)\n\n\tgo func() {\n\t\tfor s := range out {\n\t\t\tfmt.Print(s)\n\t\t}\n\t}()\n\n\t\u003c-done\n\tcancel()\n\tfmt.Println()\n\tlog.Println(\"DONE\")\n}\n\n```\n\n#### Connect and Forward\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\tgiDevice \"github.com/electricbubble/gidevice\"\n\t\"io\"\n\t\"log\"\n\t\"net\"\n\t\"os\"\n\t\"os/signal\"\n\t\"time\"\n\t\"syscall\"\n)\n\nfunc main() {\n\tusbmux, err := giDevice.NewUsbmux()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tdevices, err := usbmux.Devices()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif len(devices) == 0 {\n\t\tlog.Fatal(\"No Device\")\n\t}\n\n\td := devices[0]\n\n\tlocalPort, remotePort := 8100, 8100\n\n\tlistener, err := net.Listen(\"tcp\", fmt.Sprintf(\":%d\", localPort))\n\n\tgo func(listener net.Listener) {\n\t\tfor {\n\t\t\tvar accept net.Conn\n\t\t\tif accept, err = listener.Accept(); err != nil {\n\t\t\t\tlog.Println(\"accept:\", err)\n\t\t\t}\n\n\t\t\tfmt.Println(\"accept\", accept.RemoteAddr())\n\n\t\t\trInnerConn, err := d.NewConnect(remotePort)\n\t\t\tif err != nil {\n\t\t\t\tlog.Println(err)\n\t\t\t\tos.Exit(0)\n\t\t\t}\n\n\t\t\trConn := rInnerConn.RawConn()\n\t\t\t_ = rConn.SetDeadline(time.Time{})\n\n\t\t\tgo func(lConn net.Conn) {\n\t\t\t\tgo func(lConn, rConn net.Conn) {\n\t\t\t\t\tif _, err := io.Copy(lConn, rConn); err != nil {\n\t\t\t\t\t\t//do sth\n\t\t\t\t\t}\n\t\t\t\t}(lConn, rConn)\n\t\t\t\tgo func(lConn, rConn net.Conn) {\n\t\t\t\t\tif _, err := io.Copy(rConn, lConn); err != nil {\n\t\t\t\t\t\t//do sth\n\t\t\t\t\t}\n\t\t\t\t}(lConn, rConn)\n\t\t\t}(accept)\n\t\t}\n\t}(listener)\n\n\tdone := make(chan os.Signal, syscall.SIGTERM)\n\tsignal.Notify(done, os.Interrupt, os.Kill)\n\t\u003c-done\n}\n```\n\n## Thanks\n\n| |About|\n|---|---|\n|[libimobiledevice/libimobiledevice](https://github.com/libimobiledevice/libimobiledevice)|A cross-platform protocol library to communicate with iOS devices|\n|[anonymous5l/iConsole](https://github.com/anonymous5l/iConsole)|iOS usbmuxd communication impl iTunes protocol|\n|[alibaba/taobao-iphone-device](https://github.com/alibaba/taobao-iphone-device)|tidevice can be used to communicate with iPhone device|\n\nThank you [JetBrains](https://www.jetbrains.com/?from=gwda) for providing free open source licenses\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felectricbubble%2Fgidevice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felectricbubble%2Fgidevice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felectricbubble%2Fgidevice/lists"}