首页 > 技术文章 > atx-server android集群 搭建

yanhuidj 2019-08-01 13:09 原文

1.安装go环境  

go下载地址:https://golang.org/dl/(验证go version)

2.下载go ide 推荐goland(破解:http://idea.lanyus.com/

goland下载地址:自行解决

 

3.安装rethinkdb

下载地址:https://rethinkdb.com/docs/install/

4.安装atx-server

cmd 下  go get -github.com/openatx/atx-server

5.启动rethinkdb

cmd下 rethinkdb --http-port 8090 #指定端口启动rethinkdb

如图:

 

 

6.build atx-server

如图:

 

go build 没有报错,说明构建成功

 

7.启动atx-server

在当前目录下 atx-server --port 8000(我的当前目录是C:\Users\hui\go\src\github.com\openatx\atx-server)

启动成功后如图:

 

8.安装安装uiautomator2(确保adb devices 能够识别到设备下,执行)

命令:pip install --pre --upgrade uiautomator2

9.将uiautomator安装到手机上 并自动运行

python -m uiautomator2 init 10.247.28.146(这里好像有问题,研究中)

先到这里哈~

 

 

使用

与设备建立连接

#1. 通过WiFi连接设备

如果手机和电脑处于同一个局域网, 可以使用如下方式通过手机ip建立连接

import uiautomator2 as u2

d = u2.connect('10.234.12.104')
print d.info

其中'10.234.12.104'是手机的IP地址, 可以通过adb指令获得: adb shell ifconfig | grep Mask

运行结果如下:

{u'displayRotation': 0, u'displaySizeDpY': 829, u'displaySizeDpX': 393, u'screenOn': True, u'displayWidth': 1080, u'productName': u'lotus', u'currentPackageName': u'com.miui.home', u'sdkInt': 27, u'displayHeight': 2150, u'naturalOrientation': True}

#2.通过USB连接设备

如果手机与电脑有通过USB连接, 可以使用如下方式建立连接

import uiautomator2 as u2

d = u2.connect('62ab58430211')
print d.info

其中'62ab58430211'是手机的SN, 可以使用adb指令获得: adb devices

运行结果如下:

{u'displayRotation': 0, u'displaySizeDpY': 829, u'displaySizeDpX': 393, u'screenOn': True, u'displayWidth': 1080, u'productName': u'lotus', u'currentPackageName': u'com.miui.home', u'sdkInt': 27, u'displayHeight': 2150, u'naturalOrientation': True}

#3.通过adb WiFi连接

如果配置了手机指定端口监听TCP/IP连接, 比如

adb tcpip 5555

可以通过指定端口建立连接

import uiautomator2 as u2

d = u2.connect('10.234.12.104:5555')
print d.info

这个方法在我的机器上python2.7会报错, 可能要在3.0以上

命令行指令

注: 下面的$device_ip代表手机IP

#1. init 为设备安装所需要的程序

python -m uiautomator2 init

#2. install: 安装apk, apk通过URL给出

python -m uiautomator2.cli install $device_ip https://example.org/some.apk

#3. clear-cache: 清空缓存

python -m uiautomator2 clear-cache

#4. app-stop-all: 停止所有应用

python -m uiautomator2 app-stop-all $device_ip

#5. screenshot: 截图

python -m uiautomator2 screenshot $device_ip screenshot.jpg

#6. healthcheck: 健康检查

python -m uiautomator2 healthcheck $device_ip

常用API

全局设置

#1. Debug HTTP Requests

import uiautomator2 as u2

d = u2.connect('10.234.12.104')
d.debug=True
print d.info

运行结果:

23:17:15.628 $ curl -X POST -d '{"params": {}, "jsonrpc": "2.0", "id": "eaacec696e5911b38ea35b652f5a0d54", "method": "deviceInfo"}' 'http://10.234.12.104:7912/jsonrpc/0'
23:17:15.856 Response (228 ms) >>>
{"jsonrpc":"2.0","id":"eaacec696e5911b38ea35b652f5a0d54","result":{"currentPackageName":"com.miui.home","displayHeight":2150,"displayRotation":0,"displaySizeDpX":393,"displaySizeDpY":829,"displayWidth":1080,"productName":"lotus","screenOn":true,"sdkInt":27,"naturalOrientation":true}}
<<< END
{u'displayRotation': 0, u'displaySizeDpY': 829, u'displaySizeDpX': 393, u'screenOn': True, u'displayWidth': 1080, u'productName': u'lotus', u'currentPackageName': u'com.miui.home', u'sdkInt': 27, u'displayHeight': 2150, u'naturalOrientation': True}

#2.Implicit wait

设置元素操作等待时间, 单位: 秒

d.implicitly_wait(10.0)
d(text="小米体检").click()
print("wait timeout", d.implicitly_wait())

第一步为设置全局元素操作等待时间, 第二步点击文本"小米体检", 如果10秒内"小米体检还没有出现则会 raise UiObjectNotFoundError

这是设置会影响的操作有: click, long_click, drag_to, get_text, set_text, clear_text等

APP管理

#1. 安装APP

只支持从网络链接安装

d.app_install('http://some-domain.com/some.apk')

#2. 运行APP

d.app_start("com.example.hello_world") # start with package name

#3. 停止运行

# equivalent to `am force-stop`, thus you could lose data
d.app_stop("com.example.hello_world")
# equivalent to `pm clear`
d.app_clear('com.example.hello_world')

#4. 停止所有运行的app

# stop all
d.app_stop_all()
# stop all app except for com.examples.demo
d.app_stop_all(excludes=['com.examples.demo'])

#5. 获取APP信息

print d.app_info("com.examples.demo")

#6. 保存app图标

# save app icon
img = d.app_icon("com.examples.demo")
img.save("icon.png")

#7. Push文件到设备

# push to a folder
d.push("foo.txt", "/sdcard/")
# push and rename
d.push("foo.txt", "/sdcard/bar.txt")
# push fileobj
with open("foo.txt", 'rb') as f:
   d.push(f, "/sdcard/")
# push and change file access mode
d.push("foo.sh", "/data/local/tmp/", mode=0o755)

#8. 从设备pull文件

d.pull("/sdcard/tmp.txt", "tmp.txt")

# FileNotFoundError will raise if the file is not found on the device
d.pull("/sdcard/some-file-not-exists.txt", "tmp.txt")

#9. 检查并维持设备端守护进程处于运行状态

d.healthcheck()

基本API使用

Shell Command

adb_shell已经废弃,现在使用shell.

short-lived shell command

默认的超时为60s, 我们试试用shell命令发送pwd指令

output, exit_code = d.shell("pwd", timeout=60)
print output
print exit_code

输出:

/

0

也可以这样写

output = d.shell('pwd').output
exit_code = d.shell('pwd').exit_code

参数可以以list的形式使用,我们试试

output, exit_code = d.shell(['ls', '-l'])
print output
print exit_code

long-running shell command

r = d.shell("logcat", stream=True)
# r: requests.models.Response
deadline = time.time() + 10 # run maxium 10s
try:
   for line in r.iter_lines(): # r.iter_lines(chunk_size=512, decode_unicode=None, delimiter=None)
       if time.time() > deadline:
           break
       print("Read:", line.decode('utf-8'))
finally:
   r.close() # this method must be called

Session

#1. 使用session来操作APP的开启和关闭

sess = d.session("com.netease.cloudmusic") # start 网易云音乐
sess.close() # 停止网易云音乐

#2. 使用with来开启和关闭

with d.session("com.netease.cloudmusic") as sess:
   sess(text="Play").click()

#3. 创建已经打开的APP的session

sess = d.session('com.ganji.android.haoche_c', attach=True)
time.sleep(5)
sess.close()

#4. 侦测APP Crash

# When app is still running
sess(text="Music").click() # operation goes normal

# If app crash or quit
sess(text="Music").click() # raise SessionBrokenError
# other function calls under session will raise SessionBrokenError too

#5. 检查session是否正常

# When app is still running
sess(text="Music").click() # operation goes normal

# If app crash or quit
sess(text="Music").click() # raise SessionBrokenError
# other function calls under session will raise SessionBrokenError too

检索设备信息

#1. base information

print d.info

结果:

{u'displayRotation': 0, u'displaySizeDpY': 829, u'displaySizeDpX': 393, u'screenOn': True, u'displayWidth': 1080, u'productName': u'lotus', u'currentPackageName': u'com.miui.home', u'sdkInt': 27, u'displayHeight': 2150, u'naturalOrientation': True}

Process finished with exit code 0

#2. windows size

print(d.window_size())
# device upright output example: (1080, 1920)
# device horizontal output example: (1920, 1080)

#3. Get current app info

print d.current_app()

运行结果:

{'activity': u'com.ganji.android.haoche_c.ui.main.MainActivity', 'package': u'com.ganji.android.haoche_c'}

Process finished with exit code 0

#4. Wait activity

sess = d.session('com.ganji.android.haoche_c')
time.sleep(5)
print d.wait_activity('com.ganji.android.haoche_c.ui.main.MainActivity')

#5. Get device serial number

print d.serial

#6. Get WLAN ip

print d.wlan_ip

#7. Get detailed device info

print d.device_info

Key Events

#1. Turn on/off screen

d.screen_on() # turn on the screen
d.screen_off() # turn off the screen

#2. Get current screen status

print d.info.get('screenOn')

#3. Press hard/soft key

d.press("home") # press the home key, with key name
d.press("back") # press the back key, with key name
d.press(0x07, 0x02) # press keycode 0x07('0') with META ALT(0x02)

之前支持的key有以下这些:

home
back
left
right
up
down
center
menu
search
enter
delete ( or del)
recent (recent apps)
volume_up
volume_down
volume_mute
camera
power

更多key可以查看: Android KeyEvnet

#4. Unlock screen

d.unlock()
# This is equivalent to
# 1. launch activity: com.github.uiautomator.ACTION_IDENTIFY
# 2. press the "home" key

Gesture interaction with the device

#1. Click on the screen

d.click(x, y)

#2. Double click

d.double_click(x, y)
d.double_click(x, y, 0.1) # default duration between two click is 0.1s

#3. Long click on the screen

d.long_click(x, y)
d.long_click(x, y, 0.5) # long click 0.5s (default)

#4. Swipe

d.swipe(sx, sy, ex, ey)
d.swipe(sx, sy, ex, ey, 0.5) # swipe for 0.5s(default)

#5. Drag

d.drag(sx, sy, ex, ey)
d.drag(sx, sy, ex, ey, 0.5) # swipe for 0.5s(default)

#6. Swipe points

# swipe from point(x0, y0) to point(x1, y1) then to point(x2, y2)
# time will speed 0.2s bwtween two points
d.swipe((x0, y0), (x1, y1), (x2, y2), 0.2)

多用于九宫格解锁,提前获取到每个点的相对坐标(这里支持百分比), 更详细的使用参考这个帖子 使用u2实现九宫图案解锁

#7. Touch and drap (beta)

这个接口属于比较底层的原始接口,感觉并不完善,不过凑合能用。注:这个地方并不支持百分比

d.touch.down(10, 10) # 模拟按下
time.sleep(.01) # down 和 move 之间的延迟,自己控制
d.touch.move(15, 15) # 模拟移动
d.touch.up() # 模拟抬起

click, swipe, drag操作支持按比例操作, 比如

d.long_click(0.5, 0.5)

意思是长按屏幕中心

Screen-Related

#1. 获取当前设备方向

print d.orientation

可能的方向有

natural or n
left or l
right or r
upsidedown or u (can not be set)

#2. 设置设备方向

d.set_orientation('l') # or "left"
d.set_orientation("l") # or "left"
d.set_orientation("r") # or "right"
d.set_orientation("n") # or "natural"

#3. 禁止旋转和解除

# freeze rotation
d.freeze_rotation()
# un-freeze rotation
d.freeze_rotation(False)

#4. 截屏

# take screenshot and save to a file on the computer, require Android>=4.2.
d.screenshot("home.jpg")

# get PIL.Image formatted images. Naturally, you need pillow installed first
image = d.screenshot() # default format="pillow"
image.save("home.jpg") # or home.png. Currently, only png and jpg are supported

# get opencv formatted images. Naturally, you need numpy and cv2 installed first
import cv2
image = d.screenshot(format='opencv')
cv2.imwrite('home.jpg', image)

# get raw jpeg data
imagebin = d.screenshot(format='raw')
open("some.jpg", "wb").write(imagebin)

#5. 获取UI层级关系

# get the UI hierarchy dump content (unicoded).
xml = d.dump_hierarchy()

#6. 打开通知中心

d.open_notification()

#7. 快速设置

d.open_quick_settings()

Selector

选择当前窗口中的UI控件, 例如

# Select the object with text 'Clock' and its className is 'android.widget.TextView'
d(text='Clock', className='android.widget.TextView')

支持以下这些选择参数, 详细可以参考UiSelector Java doc

text, textContains, textMatches, textStartsWith
className, classNameMatches
description, descriptionContains, descriptionMatches, descriptionStartsWith
checkable, checked, clickable, longClickable
scrollable, enabled,focusable, focused, selected
packageName, packageNameMatches
resourceId, resourceIdMatches
index, instance

#1. Children (子级控件)

# get the children or grandchildren
d(className="android.widget.ListView").child(text="Bluetooth")

#2. Siblings(同级控件)

# get siblings
d(text="Google").sibling(className="android.widget.ImageView")

#3. children by text or description or instance

# get the child matching the condition className="android.widget.LinearLayout"
# and also its children or grandchildren with text "Bluetooth"
d(className="android.widget.ListView", resourceId="android:id/list") \
.child_by_text("Bluetooth", className="android.widget.LinearLayout")

# get children by allowing scroll search
d(className="android.widget.ListView", resourceId="android:id/list") \
.child_by_text(
   "Bluetooth",
   allow_scroll_search=True,
   className="android.widget.LinearLayout"
)

 

 

补充:mac config atx-server2

1.
node -v :v8.9.1
npm -v5.5.1
python:3.9.6
brew install rethinkdb【终端键入rethinkdb即可启动】
git clone https://github.com/openatx/atxserver2.git
安装:pip install -r requirements.txt
执行:python main.py
访问localhost:4000 或127.0.0.1:4000 列表是空的
需要安装atserver2-android-provider

2.
git clone https://github.com/openatx/atxserver2-android-provider
安装:pip install -r requirements.txt
执行:python main.py

3.
启动步骤:
先启动rethinkdb
再启动atx-server
再启动atxserver2-android-provider
再访问:http://127.0.0.1:4000
需要登陆用户名输入admin -点击使用即可
效果图:

推荐阅读