https://github.com/electricbubble/guia2
appium-uiautomator2-server ( Android ) Client Library in Golang
https://github.com/electricbubble/guia2
android appium appium-android appium-uiautomator2-server golang uiautomator2
Last synced: 7 months ago
JSON representation
appium-uiautomator2-server ( Android ) Client Library in Golang
- Host: GitHub
- URL: https://github.com/electricbubble/guia2
- Owner: electricbubble
- License: mit
- Created: 2020-08-06T00:01:56.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2021-05-16T08:45:41.000Z (about 4 years ago)
- Last Synced: 2024-06-18T20:21:20.283Z (12 months ago)
- Topics: android, appium, appium-android, appium-uiautomator2-server, golang, uiautomator2
- Language: Go
- Homepage:
- Size: 101 KB
- Stars: 131
- Watchers: 5
- Forks: 25
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Golang-UIAutomator2
[](https://pkg.go.dev/github.com/electricbubble/guia2?tab=doc)
[](https://github.com/electricbubble/guia2/blob/master/LICENSE)使用 Golang 实现 [appium/appium-uiautomator2-server](https://github.com/appium/appium-uiautomator2-server) 的客户端库
## 扩展库
- [electricbubble/guia2-ext-opencv](https://github.com/electricbubble/guia2-ext-opencv) 直接通过指定图片进行操作
> 如果使用 `IOS` 设备, 可查看 [electricbubble/gwda](https://github.com/electricbubble/gwda)
## 安装
```bash
go get github.com/electricbubble/guia2
```## 使用
> 首次使用需要在 `Android` 设备中安装两个 `apk`
> `appium-uiautomator2-server-debug-androidTest.apk`
> `appium-uiautomator2-server-vXX.XX.XX.apk`
>
>> `apk` 可以选择通过 [appium/appium-uiautomator2-server](https://github.com/appium/appium-uiautomator2-server#building-project) 进行构建
>> 也可以直接从这里下载 [electricbubble/appium-uiautomator2-server-apk](https://github.com/electricbubble/appium-uiautomator2-server-apk/releases)
>
>
> 再通过 `adb` 启动 `appium-uiautomator2-server`
> ```shell script
> adb shell am instrument -w io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner
> # ⬇️ 后台运行
> adb shell "nohup am instrument -w io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner >/sdcard/uia2server.log 2>&1 &"
> # or
> adb -s $serial shell "nohup am instrument -w io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner >/sdcard/uia2server.log 2>&1 &"
> ```### `guia2.NewUSBDriver()`
该函数使用期间, `Android` 设备必须一直保持 `USB` 的连接 (`模拟器` 也使用该函数)### `guia2.NewWiFiDriver("192.168.1.28")`
1. 先通过 `USB` 连接 `Android` 设备
2. 让设备在 5555 端口监听 TCP/IP 连接
```shell script
adb tcpip 5555
# or
adb -s $serial tcpip 5555
```
3. 查询 `Android` 设备的 `IP` (这一步骤开始可选择断开 `USB` 连接)
4. 通过 `IP` 连接 `Android` 设备
```shell script
adb connect $deviceIP
```
5. 确认连接状态
```shell script
adb devices
```
看到以下格式的设备, 说明连接成功
```shell script
$deviceIP:5555 device
``````go
package mainimport (
"fmt"
"github.com/electricbubble/guia2"
"io/ioutil"
"log"
"os"
)func main() {
driver, err := guia2.NewUSBDriver()
// driver, err := guia2.NewWiFiDriver("192.168.1.28")
checkErr(err)
defer func() { _ = driver.Dispose() }()// err = driver.AppLaunch("tv.danmaku.bili")
err = driver.AppLaunch("tv.danmaku.bili", guia2.BySelector{ResourceIdID: "tv.danmaku.bili:id/action_bar_root"})
checkErr(err, "launch the app until the element appears")// fmt.Println(driver.Source())
// returndeviceSize, err := driver.DeviceSize()
checkErr(err)var startX, startY, endX, endY int
startX = deviceSize.Width / 2
startY = deviceSize.Height / 2
endX = startX
endY = startY / 2
err = driver.Swipe(startX, startY, endX, endY)
checkErr(err)var startPoint, endPoint guia2.PointF
startPoint = guia2.PointF{X: float64(startX), Y: float64(startY)}
endPoint = guia2.PointF{X: startPoint.X, Y: startPoint.Y * 1.6}
err = driver.SwipePointF(startPoint, endPoint)
checkErr(err)element, err := driver.FindElement(guia2.BySelector{ResourceIdID: "tv.danmaku.bili:id/expand_search"})
checkErr(err)err = element.Click()
checkErr(err)bySelector := guia2.BySelector{UiAutomator: guia2.NewUiSelectorHelper().Focused(true).String()}
element, err = waitForElement(driver, bySelector)
checkErr(err)err = element.SendKeys("雾山五行")
checkErr(err)err = driver.PressKeyCode(guia2.KCEnter, guia2.KMEmpty)
checkErr(err)bySelector = guia2.BySelector{UiAutomator: guia2.NewUiSelectorHelper().TextStartsWith("番剧").String()}
element, err = waitForElement(driver, bySelector)
checkErr(err)
checkErr(element.Click())bySelector = guia2.BySelector{UiAutomator: guia2.NewUiSelectorHelper().Text("立即观看").String()}
element, err = waitForElement(driver, bySelector)
checkErr(err)
checkErr(element.Click())bySelector = guia2.BySelector{ResourceIdID: "tv.danmaku.bili:id/videoview_container_space"}
element, err = waitForElement(driver, bySelector)
checkErr(err)// time.Sleep(time.Second * 5)
screenshot, err := element.Screenshot()
checkErr(err)
userHomeDir, _ := os.UserHomeDir()
checkErr(ioutil.WriteFile(userHomeDir+"/Desktop/element.png", screenshot.Bytes(), 0600))err = driver.PressKeyCode(guia2.KCMediaPause, guia2.KMEmpty)
checkErr(err)err = driver.PressBack()
checkErr(err)
}func waitForElement(driver *guia2.Driver, bySelector guia2.BySelector) (element *guia2.Element, err error) {
var ce error
exists := func(d *guia2.Driver) (bool, error) {
element, ce = d.FindElement(bySelector)
if ce == nil {
return true, nil
}
// 如果直接返回 error 将直接终止 `driver.Wait`
return false, nil
}
if err = driver.Wait(exists); err != nil {
return nil, fmt.Errorf("%s: %w", err.Error(), ce)
}
return
}func checkErr(err error, msg ...string) {
if err == nil {
return
}var output string
if len(msg) != 0 {
output = msg[0] + " "
}
output += err.Error()
log.Fatalln(output)
}```
> 感谢小伙伴提供的 `红米 Note 5A`

## Thanks
Thank you [JetBrains](https://www.jetbrains.com/?from=gwda) for providing free open source licenses