uiautomator2使用api

 

'''
uiautomator2使用api 原文地址:https://github.com/openatx/uiautomator2
1、 atx的将安装步骤:
    pip install --pre -U uiautomator2 # atx经常更新,所以用这个命令安装最新版手机接到电脑上之后,需要先运行一下命令 python -m
    uiautomator2 init 将需要的程序部署到手机上,以便后续的自动化(PS:每个手机初始化一次就够了)。

2、 安装ui查看器
    因为uiautomator是独占资源,所以当atx运行的时候uiautomatorviewer是不能用的,为了减少atx频繁的启停,开发人员了基于浏览器技术的
    weditor UI查看器。https://github.com/openatx/weditor
    Windows系统可以使用命令在桌面创建一个快捷方式 
    pip install --upgrade weditor
    python -m weditor --shortcut

3、 连接设备(sn号、ip连接、ip+port)
    import uiautomator2 as u2
    d = u2.connect('e731d13')
    d = u2.connect('10.172.24.119')
    d = u2.connect('10.172.24.119:5555') 5555代表的是是端口

4、 安装app(只支持URL)
    d.app_install('http://some-domain.com/some.apk')
    使用包装可以用subprocess.Popen()安装
    sub = subprocess.Popen(['adb', 'install', '-r', 'D:\pycharm\PycharmWorkSpase\AtxMultidevice\data\\apk\Tester_0.5.apk'],
                     shell=False, stdout=subprocess.PIPE)

5、 运行/关闭app
    d.app_start('包名')
    d.app_stop('包名')
    d.app_clear('包名')
    扩展:不知道怎么获取包名的可以打开一个app,doc下运行adb shell dumpsys activity activities | findstr "Run,会得到类似的
     Run #1: ActivityRecord{3a79cdb0 u0 com.hello.abc.presentation/com.hello.adc.presentation.view.activities.MainActivity t853}
     com.hello.abc.presentation 这就是包名

6、 停止所有app/停止除了此app之外的app
    d.app_stop_all()
    d.app_stop_all(excludes=‘包名’)

7、 获取app的信息
    d.app_info('包名')
    img = d.app_icon('包名')
    img.save('存储路径名')  #如果只写图像名 则会保存在当期那文件夹下

8、 push和pull
    # push文件夹
    d.push("foo.txt", "/sdcard/")

    # push并重命名
    d.push("foo.txt", "/sdcard/bar.txt")

    # push file对象
    with open("foo.txt", 'rb') as f:
        d.push(f, "/sdcard/")

    # push 并更改文件访问方式,读、写等等
    d.push("foo.sh", "/data/local/tmp/", mode=0o755)

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

9、 shell命令其实和subprocess.Popen差不多
    d.shell(arg) # arg可以使字符串或者list

10、 session:表示应用程序的生命周期,可以启动app可以检测app 崩溃
    sess = d.session('packageName') start app
    sess.close()  close app

    附加到正在运行的应用程序(不太理解)
    sess = d.session("com.netease.cloudmusic", attach=True)

    检查是否崩溃
    sess.running() # return True or False

11、 得到基本信息
    print(d.info)  当前包名、高度、是否旋转(猜的)、宽度、屏幕是否亮、sdk版本。有一些不知道
    {'currentPackageName': 'com.test.ui.activities.nihao', 'displayHeight': 1280, 'displayRotation': 0,
    'displaySizeDpX': 360, 'displaySizeDpY': 640, 'displayWidth': 720, 'productName': 'msm8909', 'screenOn': True,
    'sdkInt': 22, 'naturalOrientation': True}

12、 得到屏幕的尺寸
    print(d.window_size())

13、 获取当前应用程序信息
    print(d.current_app())
    {'package': 'com.test.ui.activities.nihao', 'activity': 'com.test.ui.activities.MainActivity'}

14、 等待activity出现
    d.wait_activity('com.test.ui.activities.MainActivity', timeout=10)

15、 获取sn号
    print(d.serial)

16、 获取WLAN 的ip
    print(d.wlan_ip)

17、 详细的设备信息
    print(d.device_info)
    {'udid': 'e731d13-34:87:3d:2d:60:fa-X990', 'version': '5.1.1', 'serial': 'e731d13', 'brand': 'Verifone', 'model':
    'X990', 'hwaddr': '34:87:3d:2d:60:fa', 'port': 7912, 'sdk': 22, 'agentVersion': '0.5.4', 'display': {'width': 720,
     'height': 1280}, 'battery': {'acPowered': True, 'usbPowered': False, 'wirelessPowered': False, 'status': 5,
     'health': 2, 'present': True, 'level': 100, 'scale': 100, 'voltage': 4186, 'temperature': 295, 'technology': ''}, 'memory': {'total': 922248, 'around': '1 GB'}, 'cpu': {'cores': 4, 'hardware': 'Qualcomm Technologies, Inc MSM8909'}, 'owner': None, 'presenceChangedAt': '0001-01-01T00:00:00Z', 'usingBeganAt': '0001-01-01T00:00:00Z', 'product': None, 'provider': None}

18、 屏幕的亮灭
    d.screen_on()
    d.screen_off()

19、 获取屏幕的状态
    print(d.info.get('screenOn))  return True or False

20、 软硬件的按键操作
    d.press('back')
    这些目前支持:
    home                    back                  left                  right
    up                        down
    center                   menu                 search             enter
    delete ( or del)          recent (recent apps)        volume_up           
    volume_down         volume_mute           camera    power

21、 解锁屏幕(当然是没有密码的那种)
    d.unlock()

22、事件操作
    单击、滑动、拖动操作支持百分比位置值

    1、点击:
    通过text点击 d(text='你好').click(timeout=5)
    通过坐标点击  d.click(x, y)

    2、双击:
    d.double_click(x, y, duration=0.1) #两次点击默认的时间间隔是0.1s

    3、长点击:
    d.long_click(0.515, 0.84, duration=0.5)  # 默认点击时间是0.5s

    4、滑动:
    1、 从一个坐标滑动到具体坐标
    d.swipe(sx, sy, ex, ey, duration=0.5)   # 开始坐标--结束坐标(下滑注意是大坐标变成小坐标),滑动持续时长。有时候可能看不
    到滑动的现象可以加time.sleep(2)看一下。
    例:
    subprocess.Popen(['adb',  'shell', 'am', 'start', '-n', 'com.android.settings/.Settings'])
    time.sleep(1)
    d.swipe(0.641, 0.863, 0.348, 0.232, 0.5)

    2、把一个UI元素从中心向一个方向移动固定的步长(感觉类似拖拽了)  上、下、左、右
    d(text="Settings").swipe("down", steps=20)

    3、两点手势,从开始点到结束点(不太会用可能是以前手机的截图之类的便捷操作)
    d(text="Settings").gesture((sx1, sy1), (sx2, sy2), (ex1, ey1), (ex2, ey2))

    5、拖拽:
    d.drag(sx, sy, ex, ey, duration=0.5) # 默认点击时间是0.5s
    例:  d.drag(0.621, 0.37, 0.863, 0.576, duration=0.5)

    6、从一个UI元素拖拽到另一个UI元素
    d(text="Settings").drag_to(x, y, duration=0.2)   # duration尽量小不然会移位
    d(text="Settings").drag_to(text="Clock", duration=0.2)

    7、多点之间滑动(九宫格解锁):
    d.swipe((x0, y0), (x1, y1), (x2, y2), duration=0.2)  # 多点坐标

23、 屏幕旋转
    natural or n
    left or l
    right or r
    upsidedown or u (can not be set)

    d.set_orientation('n')  # natural
    print(d.orientation) # 打印旋转的的状态

    控制旋转
    d.freeze_rotation(False)  # True or False

24、 截图
    d.screenshot("home.jpg")  # 存储路径

25、 获取UI的结构(可以理解成html结构)
    print(d.dump_hierarchy())

26、 查看通知栏
    d.open_notification()

27、 打开快捷下拉菜单
    d.open_quick_settings()

28、 元素选择器(个人觉得用的方便的:text、className、xpath就可以了,像一些相对定位,绝对定位,儿子,兄弟等就可以用xpath)
    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
例:
    d(text='你好').click(timeout=5)
    d(className="android.widget.ListView").click(timeout=5)
    xpath

    有时候其实会匹配一个list的对象用索引找到实例
    d(text="Add new")[0]

    获取到元素后可以进行赋值、删除操作,也可以得到元素的value值和js差不多
    d(text="Settings").get_text()  # get widget text
    d(text="Settings").set_text("My text...")  # set the text
    d(text="Settings").clear_text()  # clear the text

29、 获取元素的中心点坐标
    x, y =d(text="Settings").center()

30、 判断一个元素是否存在
    print(d(text="Settings").exists(timeout=5))  # True if exists, else False

31、 隐式等待,元素存在点击
    d(text='Skip').click_exists(timeout=10.0)  # 会返回一个bool值,存在则点击并返回True,否则返回False(不会报异常)

32、 获取元素对象的信息
    print(d(text='Setting').info)

33、 等待元素出现和消失
    # 等待元素出现
    d(text="Settings").wait(timeout=3.0) # return bool
    # 等待元素消失
    d(text="Settings").wait_gone(timeout=1.0)

34、fling(不知道最好的解释是什么)
    # 垂直向下滚动(default)
    d(scrollable=True).fling()
    # 水平滚动
    d(scrollable=True).fling.horiz.forward()
    # 垂直向上滚动
    d(scrollable=True).fling.vert.backward()
    # 貌似是滚动固定步长
    d(scrollable=True).fling.horiz.toBeginning(max_swipes=1000)
    # 垂直滚到低
    d(scrollable=True).fling.toEnd()

35、 滚动操作
    scroll()里面的参数steps默认是滑动一个屏幕的距离
    a.向上滚动:d(scrollable=True).scroll(steps=10)

    b.向下滑动:d(scrollable=True).scroll.vert.backward()

    c.水平向右滚动:d(scrollable=True).scroll.horiz.forward(steps=50)

    d.水平向左滚动:d(scrollable=True).scroll.horiz.backward(steps=50)

    e.水平滑动到最左边:d(scrollable=True).scroll.horiz.toBeginning(steps=100,         max_swipes=1000)

    f.水平滑动到最右边:d(scrollable=True).scroll.horiz.toEnd(steps=100, max_swipes=1000)

    g.竖直滑动到结尾:d(scrollable=True).scroll.toEnd()

    h.竖直滑动到开头:d(scrollable=True).scroll.toBeginning(steps=50)

    i.滑动到指定位置(测试):d(scrollable=True).scroll.to(text ='测试')

36、 Watcher(类似于监听器)
    1、当条件匹配时单击target
    如果监听到程序崩溃(AUTO_FC_WHEN_ANR出现),选择点击强制关闭
    注册一个AUTO_FC_WHEN_ANR的watcher然后监听text=ANR/Wait出现则点击
    d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait").click(text="Force Close") #这里是不是写错了应该是首先anr然后等待
    (理解成手机崩溃了会提示是否继续等待或者强制关闭)

    2、如果只有一个提示可以不写具体点击什么
    注册一个ALERT的watcher然后监听text=OK出现则点击
    d.watcher("ALERT").when(text="OK").click()
    same sa
    d.watcher("ALERT").when(text="OK").click(text='OK')

    3、当条件为真时按下一个键press
    d.watcher("ALERT").when(text="OK").press('back')

    4、检查监听器是否触发
    d.watcher("watcher_name").triggered   # return Ture or False

    5、移除特定的监听器
    d.watcher("watcher_name").remove()

    6、列举所有监听器
    d.watchers # return list

    7、检查是否触发
    d.watchers.triggered
    #  true in case of any watcher triggered

    8、重置所有监听器
    d.watchers.reset()

    9、移除所有监听器
    # remove all registered watchers
    d.watchers.remove()
    # remove the named watcher, same as d.watcher("watcher_name").remove()
    d.watchers.remove("watcher_name")

    10、强制运行所有监听器
    d.watchers.run()

    11、当页面更新时运行所有观察者。通常可以用来自动点击权限确认框,或者自动安装
    d.watcher("OK").when(text="OK").click(text="OK")
    # 启用自动触发监视程序
    d.watchers.watched = True

    # 禁用自动触发监视程序
    d.watchers.watched = False

    # 获取当前触发器监视者状态
    assert d.watchers.watched == False

37、全局设置
    # 设置每次UI点击后1.5秒的延迟
    d.click_post_delay = 1.5 # default no delay

    # 设置默认元素等待超时(秒)
    d.wait_timeout = 30.0 # default 20.0

38、 输入内容(原文说有的时候输入值点击back等键的时候无响应,需要安装一个输入法具体看原文吧)
    d.send_keys('str')

39、Toast
    1、显示toast
    d.toast.show("Hello world", 1.0) # show for 1.0s, default 1.0s

    2、获取toast
    # 5.0: 最大等待时间
    # 10.0: toast出现后的缓存时间. 默认 10.0
    # "default message": 返回的toast值. Default None
    d.toast.get_message(5.0, 10.0, "default message")

    # 一般用法
    assert "Short message" in d.toast.get_message(5.0, default="")

    # 清除toast缓存
    d.toast.reset()

40、 xpath
    # wait exists 10s
    d.xpath("//android.widget.TextView").wait(10.0) # return bool
    # find and click
    d.xpath("//*[@content-desc='分享']").click()
    # check exists
    if d.xpath("//android.widget.TextView[contains(@text, 'Se')]").exists:
        print("exists")
    # get all text-view text, attrib and center point
    for elem in d.xpath("//android.widget.TextView").all():
        print("Text:", elem.text)
        # Dictionary eg:
        # {'index': '1', 'text': '999+', 'resource-id': 'com.netease.cloudmusic:id/qb', 'package': 'com.netease.cloudmusic', 'content-desc': '', 'checkable': 'false', 'checked': 'false', 'clickable': 'false', 'enabled': 'true', 'focusable': 'false', 'focused': 'false','scrollable': 'false', 'long-clickable': 'false', 'password': 'false', 'selected': 'false', 'visible-to-user': 'true', 'bounds': '[661,1444][718,1478]'}
        print("Attrib:", elem.attrib)
        # Coordinate eg: (100, 200)
        print("Position:", elem.center())
'''
import subprocess
import time

import uiautomator2 as u2

if __name__ == '__main__':

    d = u2.connect('10.172.24.79')
    d.xpath("//android.widget.TextView").wait(10.0)
    d(scrollable=True).scroll()
    d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait").click(text="Force Close")
    # d(text="Settings").swipe("down", steps=20)
    # d(text="ATX").drag_to(text='SCB smartEDC', duration=0.2)
    # d.open_notification()
    # d.open_quick_settings()
    # xml = d.dump_hierarchy()
    # print(xml)

    # d.screenshot("D:\pycharm\PycharmWorkSpase\AtxMultidevice\yamlsTestCase\home.jpg")
    # d.drag(0.621, 0.37, 0.5, 0, duration=0.5)
    # d.set_orientation('n')  # or "left"
    # print(d.orientation)
    # d.freeze_rotation(False)
    # d.healthcheck()
    # d.screen_on()
    # print(d.info.get('screenOn'))
    # print(d.wlan_ip)
    # print(d.device_info)
    # sess = d.session('com.test.ui.activities.nihao')
    # d(text='测试工具').click_exists(timeout=5.0)
    # bool = d(text='Skip').click_exists(timeout=5.0)
    # print(bool)

    # d.long_click(0.515, 0.84, 0.5)  # long click 0.5s (default)
    subprocess.Popen(['adb',  'shell', 'am', 'start', '-n', 'com.android.settings/.Settings'])
    # d(scrollable=True).scroll(steps=10)
    d(scrollable=True).fling()
    # time.sleep(1)
    # d(scrollable=True).fling.vert.backward()
    # d(scrollable=True).fling.toEnd()
    # time.sleep(1)
    # d.swipe(0.641, 0.863, 0.348, 0.232, 0.5)
    # d.app_clear('com.test.ui.activities.nihao')
    # d.press('back')
    # d.unlock()
    # print(d.serial)
    # print(d.info)
    # print(d.window_size())
    # print(d.current_app())
    # print(d.wait_activity('com.test.ui.activities.MainActivity', timeout=10))
    # d.app_start('com.test.ui.activities.nihao')
    # d.swipe(0, 10, 1000, 10, 0.5)
    # print(sess.running())  # True or False
    # d(text="测试工具").click()
    # sub = subprocess.Popen(['adb', 'install', '-r', 'D:\pycharm\PycharmWorkSpase\AtxMultidevice\data\\apk\Tester_0.5.apk'],
    #                  shell=False, stdout=subprocess.PIPE)
    #
    # print(sub.stdout.readlines())

    # 注意这里不要再重定向到'>', 'D:\Config\log.txt',因为stdout就可以输出控制台的值
    # log = subprocess.Popen(['adb', 'logcat', '-v', 'time'], shell=False,stdout=subprocess.PIPE)
    # print(log.stdout.readlines())  #这里需要拔掉数据线才可以有log

    # time.sleep(1)
    # img = d.app_icon('com.test.ui.activities.nihao')
    # img.save('D:\pycharm\PycharmWorkSpase\AtxMultidevice\data\\apk\\asd.png')
    # d.app_clear('com.test.ui.activities.nihao')

 

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值