1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/supernatural-fork-uiautomator2

Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

uiautomator2 Статус сборки PyPI PyPI Windows Build

Версии различных библиотек

  • PyPI
  • GitHub tag (latest SemVer)
  • GitHub tag (latest SemVer)
  • PyPI
  • PyPI
  • PyPI

Проект находится в активной разработке QQ-группа: 499563266

Внезапное объявление о найме : в настоящее время команда автора (Команда качества при Taobao, Alibaba: расположена в парке XiXi, Ханчжоу) ищет новых сотрудников (HIRE) Дополнительные сведения можно найти здесь https://testerhome.com/topics/23010

[UiAutomator](https://developer.android.com/training/testing/ui-automator.html) — это Java-библиотека, предоставленная Google для автоматизированного тестирования Android, основанная на сервисе доступности. Функционал очень мощный, позволяет тестировать сторонние приложения, получать свойства любого элемента управления на экране и выполнять с ними любые действия. Однако есть два недостатка: 1. тестовые сценарии могут быть написаны только на Java; 2. тестовые сценарии должны быть упакованы в jar или apk-файлы и загружены на устройство для выполнения.Мы хотим, чтобы логика тестирования была написана на Python и могла управлять смартфоном с компьютера. Здесь мы хотели бы выразить особую благодарность Xiaocong He ([@xiaocong][]) за реализацию этой идеи (см. [xiaocong/uiautomator](https://github.com/xiaocong/uiautomator)). Принцип заключается в запуске HTTP-RPC-сервиса на смартфоне, который открывает функции UiAutomator, а затем эти HTTP-интерфейсы упаковываются в Python-библиотеку. Так как библиотека `xiaocong/uiautomator` давно не обновлялась, мы просто fork-нули её версию и добавили номер 2 в конце [openatx/uiautomator2](https://github.com/openatx/uiautomator2). Кроме устранения ошибок в существующих библиотеках, были добавлены новые функции. Основные изменения включают:
  • Подключение устройств и разработочных машин через Wi-Fi без использования USB-кабеля (основано на atx-agent)
  • Интеграция openstf/minicap для реального времени отображения экрана и моментальных снимков экрана
  • Интеграция openstf/minitouch для точного управления устройством в реальном времени
  • Устранение проблем с частыми выходами из xiaocong/uiautomator
  • Переработка и упрощение кода для удобства поддержки
  • Создание платформы управления устройствами (также поддерживает iOS) atxserver2
  • Расширение функций получения и отображения уведомлений (toast)> Здесь следует отметить, что часто задают вопрос о том, что openatx/uiautomator2 не поддерживает тестирование iOS. Для автоматизации тестирования iOS можно использовать этот репозиторий openatx/facebook-wda.

PS: Этот репозиторий https://github.com/NeteaseGame/ATX больше не поддерживается, поэтому рекомендуется как можно скорее перейти на другой.

Вот краткое руководство, предназначенное для тех, кто уже знаком с библиотекой QUICK REFERENCE GUIDE, приветствуют ваши отзывы.

Требования

  • Версия Android 4.4+
  • Python 3.6+ (сообщество сообщило, что версия 3.8.0 не поддерживается, но версия 3.8.2 поддерживается)

Если вы используете pip для Python 2, будет установлена старая версия библиотеки 0.2.3; если вы используете pip для Python 3.5, будет установлена старая версия библиотеки 0.3.3; обе версии больше не поддерживаются. Последняя версия на PYPI доступна по ссылке: https://pypi.org/project/uiautomator2/

БЫСТРОЕ НАЧАЛО

Подготовьте одно устройство Android с включенным режимом разработчика, подключите его к компьютеру и убедитесь, что устройство видно при выполнении команды adb devices.

Выполните pip3 install -U uiautomator2 для установки uiautomator2.

Выполните python3 -m uiautomator2 init для установки APK с HTTP-RPC-сервисом на устройство + atx-agent, minicap, minitouch (в предыдущих версиях это было обязательным шагом, но начиная с версии 1.3.0, при выполнении команды u2.connect() эти файлы будут автоматически загружены).Запустите командную строку python для открытия окна интерактивного режима Python. Затем введите следующий код в окно.

import uiautomator2 as u2

d = u2.connect() # подключение к устройству
print(d.info)

Если вы видите подобный вывод, вы можете начать использовать эту библиотеку. Поскольку функциональность библиотеки очень обширна, вам потребуется время, чтобы изучить все ее возможности.

{'currentPackageName': 'net.oneplus.launcher', 'displayHeight': 1920, 'displayRotation': 0, 'displaySizeDpX': 411, 'displaySizeDpY': 731, 'displayWidth': 1080, 'productName': 'OnePlus5', 'screenOn': True, 'sdkInt': 27, 'naturalOrientation': True}

Обычно всё проходит顺利,不过也可能会有意外。可以加QQ群反馈问题,群里有很多大佬可以帮你解决问题。

Спонсоры

Благодарим всех наших спонсоров! ✨🍰✨

Золотой спонсор (Gold Sponsor)

Logo-Хогвартс Тест Академия

Хогвартс Тест Академия — ведущий образовательный бренд в области тестирования и разработки, принадлежащий компании Цеширен (Пекин). Курсы академии проводятся ведущими экспертами в области тестирования из BAT, предоставляя практические курсы по автоматическому тестированию API, мобильному тестированию, производительности и непрерывной интеграции с DevOps, а также услуги рекрутинга талантов в области тестирования. Узнать больше!


Обычно всё проходит顺利,不过也可能会有意外。可以加QQ群反馈问题,群里有很多大佬可以帮你解决问题。

Спонсоры

Благодарим всех наших спонсоров! ✨🍰✨

Золотой спонсор (Gold Sponsor)

Logo-Хогвартс Тест Академия

Хогвартс Тест Академия — ведущий образовательный бренд в области тестирования и разработки, принадлежащий компании Цеширен (Пекин). Курсы академии проводятся ведущими экспертами в области тестирования из BAT, предоставляя практические курсы по автоматическому тестированию API, мобильному тестированию, производительности и непрерывной интеграции с DevOps, а также услуги рекрутинга талантов в области тестирования. Узнать больше!Хогвартс Тест Академия — первый золотой спонсор ATX.

Связанные проекты

  • Платформа управления устройствами, необходимая при большом количестве устройств atxserver2
  • Библиотека для взаимодействия с ADB adbutils
  • atx-agent — сервис, работающий на устройстве, написанный на Go, для поддержания жизнеспособности связанных сервисов на устройстве
  • weditor — редактор, похожий на uiautomatorviewer, специально разработанный для этого проекта

Установка

Подключение к устройству

Командная строка

Глобальные настройки

Экспериментальные функцииЭкспериментальные функции

  • Удаленное отображение
  • htmlreport
  • Диагностика методов uiautomator2
  • Плагины
  • Хуки
  • Показ уведомления при неудаче

История проектаИстория проекта

КонtributorsУчастники

LICENSEЛицензия

Установка

  1. Установка uiautomator2

    # Поскольку uiautomator2 находится в разработке, вам нужно добавить --pre для установки разрабатываемой версии
    pip install --upgrade --pre uiautomator2
    
    # Или вы можете установить напрямую из исходного кода github
    git clone https://github.com/openatx/uiautomator2
    pip install -e uiautomator2

    Проверка установки uiautomator2 --help

  2. Установка weditor (UI Inspector)

    Поскольку uiautomator является исключительным ресурсом, uiautomatorviewer не может использоваться, когда atx запущен. Чтобы уменьшить частые запуски и остановки atx, мы разработали weditor UI-инспектор на основе браузерной технологии. https://github.com/openatx/weditor

    Метод установки (примечание: текущая стабильная версия - 0.1.0)

    pip install -U weditor

    После установки вы можете запустить weditor --help в командной строке для проверки установки. > В Windows можно использовать команду для создания ярлыка на рабочем столе weditor --shortcut

    Ввод weditor в командной строке автоматически откроет браузер, введите IP-адрес или серийный номер устройства и нажмите Connect.

    Подробнее см. статью: Небольшое обсуждение автоматизированного тестирования с помощью python-uiautomator2

  3. Установка демонов на устройство (необязательно)

    Подключите компьютер к одному или нескольким телефонам, убедитесь, что adb добавлен в переменные окружения, выполните следующую команду для автоматической установки необходимых программ на устройстве: uiautomator-server, atx-agent, openstf/minicap, openstf/minitouch```bash

инициализация всех подключенных к компьютеру устройств

python -m uiautomator2 init


Иногда инициализация может завершиться ошибкой, в этом случае обратитесь к [руководству по ручной инициализации](https://github.com/openatx/uiautomator2/wiki/Manual-Init)

Успешное завершение инициализации будет отображаться как `success`

4. 【опционально】 AppetizerIO редактор сценариев "что вы видите, то и получаете"[AppetizerIO](https://www.appetizer.io) предоставляет глубокую интеграцию с uiautomator2, позволяющую графически управлять устройствами ATX и использовать редактор сценариев "что вы видите, то и получаете".
* Сайт позволяет загрузить и открыть приложение, при первом использовании необходимо зарегистрироваться.
* В разделе `Управление устройствами` можно проверить, правильно ли инициализированы устройства, запустить или остановить atx-agent, а также получить файл atx-agent.log.
* В разделе `Тестовые сценарии` можно использовать вспомогательный редактор сценариев, который обеспечивает синхронизацию интерфейса в реальном времени, позволяющую вставлять различные коды при нажатии на элементы интерфейса. Поддерживается как uiautomator, так и Appium.
* **[Видео-руководство, нажмите здесь](https://github.com/openatx/uiautomator2/wiki/Appetizer%E6%89%80%E8%A7%81%E5%8D%B3%E6%89%80%E5%BE%97u2%E8%84%9A%E6%9C%AC%E7%BC%96%E8%BE%91%E5%99%A8)** [другие документы здесь](http://doc.appetizer.io)# Подключение к устройству
Существует два способа подключения к устройству.

1. **Через Wi-Fi**

Предположим, что IP-адрес устройства `10.0.0.1`, а ваш ПК находится в той же сети.

```python
import uiautomator2 as u2

d = u2.connect('10.0.0.1') # псевдоним для u2.connect_wifi('10.0.0.1')
print(d.info)
  1. Через USB

Предположим, что серийный номер устройства 123456f (виден из adb devices)

import uiautomator2 as u2

d = u2.connect('123456f') # псевдоним для u2.connect_usb('123456f')
print(d.info)
  1. Через ADB Wi-Fi
import uiautomator2 as u2

d = u2.connect_adb_wifi("10.0.0.1:5555")

# Равносильно
# + Shell: adb connect 10.0.0.1:5555
# + Python: u2.connect_usb("10.0.0.1:5555")

Вызов u2.connect() без аргументов, uiautomator2 получит IP-адрес устройства из переменной окружения ANDROID_DEVICE_IP или ANDROID_SERIAL. Если эта переменная окружения пустая, uiautomator вернётся к connect_usb и вам нужно убедиться, что подключено только одно устройство.

Командная строка

В которой $device_ip представляет IP-адрес устройства

Для указания конкретного устройства необходимо передать --serial, например python3 -m uiautomator2 --serial bff1234 <SubCommand>, где SubCommand — это подкоманда (init, или screenshot и т.д.)

1.0.3 Добавлено: python3 -m uiautomator2 можно сократить до uiautomator2- screenshot: Скриншот

```bash
$ uiautomator2 screenshot screenshot.jpg
```
  • current: Получение текущего имени пакета и активности

    $ uiautomator2 current
    {
        "package": "com.android.browser",
        "activity": "com.uc.browser.InnerUCMobile",
        "pid": 28478
    }
  • uninstall: Удаление ```bash $ uiautomator2 uninstall <имя_пакета> # Удаление одного пакета $ uiautomator2 uninstall <имя_пакета_1> <имя_пакета_2> # Удаление нескольких пакетов $ uiautomator2 uninstall --all # Удаление всех пакетов

  • stop: Остановка приложения

    $ uiautomator2 stop com.example.app # Остановка одного приложения
    $ uiautomator2 stop --all # Остановка всех приложений
  • install: Установка apk, apk указывается по URL (временно недоступно)

  • healthcheck: Проверка состояния (временно недоступно)

Документация по API

Новый таймаут команды

Сколько времени (в секундах) будет ожидать новый запрос от клиента перед тем, как предположить, что клиент отключился и завершить работу службы uiautomator (по умолчанию 3 минуты).

Настройка максимального времени ожидания для сервиса доступности, при превышении которого ресурсы будут автоматически освобождены. По умолчанию 3 минуты.

d.set_new_command_timeout(300) # изменение на 5 минут, единица измерения - секунды

Отладка HTTP-запросов

Отслеживание HTTP-запросов и ответов для понимания их работы.

>>> d.debug = True
>>> d.info
12:32:47.182 $ curl -X POST -d '{"jsonrpc": "2.0", "id": "b80d3a488580be1f3e9cb3e926175310", "method": "deviceInfo", "params": {}}' 'http://127.0.0.1:54179/jsonrpc/0'
12:32:47.225 Ответ >>>
{"jsonrpc":"2.0","id":"b80d3a488580be1f3e9cb3e926175310","result":{"currentPackageName":"com.android.mms","displayHeight":1920,"displayRotation":0,"displaySizeDpX":360,"displaySizeDpY":640,"displayWidth":1080,"productName":"odin","screenOn":true,"sdkInt":25,"naturalOrientation":true}}
<<< КОНЕЦ
```### Неявное ожидание
Установка стандартного времени ожидания для элементов, единица измерения  секунды

Установка времени ожидания для поиска элементов (по умолчанию 20 секунд)

```python
d.implicitly_wait(10.0) # также можно изменить через d.settings['wait_timeout'] = 10.0
d(text="Настройки").click() # если кнопка "Настройки" не появится в течение 10 секунд, будет выброшено исключение UiObjectNotFoundError

print("таймаут ожидания", d.implicitly_wait()) # получение стандартного неявного таймаута

Эта функция влияет на click, long_click, drag_to, get_text, set_text, clear_text и другие.

Управление приложениями

Этот раздел демонстрирует, как выполнять управление приложениями

Установка приложения

Мы поддерживаем установку APK по URL

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

Запуск приложения

# Этот метод по умолчанию использует atx-agent для анализа APK-пакета и определения mainActivity, затем запускает приложение с помощью am start -n $package/$activity
d.app_start("com.example.hello_world")

# Запуск приложения с помощью monkey -p com.example.hello_world -c android.intent.category.LAUNCHER 1
# Этот метод имеет побочный эффект: он автоматически отключает вращение экрана на устройстве
d.app_start("com.example.hello_world", use_monkey=True) # запуск с использованием имени пакета

# Запуск приложения, указав main activity, эквивалентно вызову am start -n com.example.hello_world/.MainActivity
d.app_start("com.example.hello_world", ".MainActivity")
```### Остановка приложения
```python
# эквивалентно `am force-stop`, поэтому вы можете потерять данные
d.app_stop("com.example.hello_world") 
# эквивалентно `pm clear`
d.app_clear('com.example.hello_world')

Остановка всех запущенных приложений

# остановить все
d.app_stop_all()
# остановить все приложения, кроме com.examples.demo
d.app_stop_all(excludes=['com.examples.demo'])

Получение информации о приложении

d.app_info("com.examples.demo")
# ожидаемый вывод
#{
#    "mainActivity": "com.github.uiautomator.MainActivity",
#    "label": "ATX",
#    "versionName": "1.1.7",
#    "versionCode": 1001007,
#    "size": 1760809
#}

# сохранение значка приложения
img = d.app_icon("com.examples.demo")
img.save("icon.png")

Перечисление всех запущенных приложений

d.app_list_running()
# ожидаемый вывод
# ["com.xxxx.xxxx", "com.github.uiautomator", "xxxx"]

Ожидание запуска приложения

pid = d.app_wait("com.example.android") # ожидание запуска приложения, возвращает pid(int)
if not pid:
    print("com.example.android не запущено")
else:
    print("pid приложения com.example.android равен %d" % pid)

d.app_wait("com.example.android", front=True) # ожидание запуска приложения в переднем плане
d.app_wait("com.example.android", timeout=20.0) # максимальное время ожидания 20 секунд (по умолчанию)

Добавлено в версии 1.2.0

Передача и получение файлов

  • передача файла на устройство

    # передача в папку
    d.push("foo.txt", "/sdcard/")
    # передача и переименование
    d.push("foo.txt", "/sdcard/bar.txt")
    # передача файла
    with open("foo.txt", 'rb') as f:
        d.push(f, "/sdcard/")
    # передача и изменение режима доступа файла
    d.push("foo.sh", "/data/local/tmp/", mode=0o755)
  • извлечение файла с устройства ```python d.pull("/sdcard/tmp.txt", "tmp.txt")

    FileNotFoundError будет вызван, если файл не найден на устройстве

    d.pull("/sdcard/some-file-not-exists.txt", "tmp.txt")

Проверка и поддержание работы守护进程 на устройстве

d.healthcheck()

Автоматическое согласование диалогов разрешений

Внимание функция disable_popups обнаружена нестабильной, временно не использовать, ожидайте дальнейших инструкций.

Введено в версии 0.1.1

d.disable_popups() # автоматическое пропускание всплывающих окон
d.disable_popups(False) # отключение автоматического пропускания всплывающих окон

popup

Если данный метод не работает на вашем устройстве, вы можете создать pull request или создать issue для улучшения данной функции. Я покажу вам, как это сделать.

  1. Откройте uiautomatorviewer.bat
  2. Получите иерархию всплывающего окна

hierarchy

Теперь вы знаете текст кнопки и текущее имя пакета. Создайте pull request, обновив функцию disable_popups или создайте issue, если вы не знакомы с git и python.

Основные примеры использования API

Этот раздел демонстрирует, как выполнять обычные операции с устройством:

Команды оболочки

  • Выполнение кратковременной команды оболочки с защитой от зависаний (по умолчанию 60 секунд).

    Примечание: поддержка тайм-аута требует atx-agent >=0.3.3 Функция adb_shell устарела. Используйте shell вместо неё.

    Простое использование

    output, exit_code = d.shell("pwd", timeout=60) # тайм-аут 60 секунд (по умолчанию)
    # output: "/\n", exit_code: 0
    # Аналогично команде: adb shell pwd
    
    # Поскольку тип возвращаемого значения функции `shell` - `namedtuple("ShellResponse", ("output", "exit_code"))`
    # мы можем использовать некоторые хитрости
    output = d.shell("pwd").output
    exit_code = d.shell("pwd").exit_code

    Первый аргумент может быть списком. Например,

    output, exit_code = d.shell(["ls", "-l"])
    # output: "/....", exit_code: 0

    Это возвращает строку для stdout, объединённую со stderr. Если команда является блокирующей, shell также будет блокироваться до завершения команды или до срабатывания тайм-аута. В процессе выполнения команды частичный вывод не будет получен. Этот API не подходит для длительных команд. Команда оболочки выполняется в среде, аналогичной adb shell, которая имеет уровень разрешений Linux adb или shell (выше уровня разрешений приложения). Запуск долгоживущей команды оболочки

    Добавление stream=True вернет объект requests.models.Response. Дополнительная информация доступна по ссылке. ```python r = d.shell("logcat", stream=True)

    r: requests.models.Response

    deadline = time.time() + 10 # launch maximum 10 seconds try: for line in r.iter_lines(): # r.iter_lines(chunk_size=512, decode_unicode=None, delimiter=None) if time.time() > deadline: break print("Reading:", line.decode('utf-8')) finally: r.close() # this method must be called ``` Команда будет завершена при вызове r.close().

Сессия

Сессия представляет жизненный цикл приложения. Может использоваться для запуска приложения, обнаружения аварийного завершения приложения.

  • Запуск и завершение приложения

    sess = d.session("com.netease.cloudmusic") # запуск 网易云音乐
    sess.close() # остановка 网易云音乐
    sess.restart() # холодный запуск 网易云音乐
  • Использование Python with для запуска и завершения приложения

    with d.session("com.netease.cloudmusic") as sess:
        sess(text="Play").click()
  • Подключение к запущенному приложению

    # запуск приложения, если оно не запущено, пропуск запуска, если оно уже запущено
    sess = d.session("com.netease.cloudmusic", attach=True)
    
    # выбрасывает SessionBrokenError, если приложение не запущено
    sess = d.session("com.netease.cloudmusic", attach=True, strict=True)
  • Обнаружение аварийного завершения приложения

    # Когда приложение все еще работает
    sess(text="Music").click() # операция проходит нормально
    
    # Если приложение аварийно завершилось или вышло
    sess(text="Music").click() # выбрасывает SessionBrokenError
    # другие вызовы функций под сессией также выбрасывают SessionBrokenError
    # проверка, работает ли сессия.
    # Предупреждение: имя функции может измениться в будущем
    sess.running() # True или False

Получение информации о устройстве

Получение базовой информации о устройстве```python d.info


Вот пример вывода:

{ u'displayRotation': 0, u'displaySizeDpY': 640, u'displaySizeDpX': 360, u'currentPackageName': u'com.android.launcher', u'productName': u'takju', u'displayWidth': 720, u'sdkInt': 18, u'displayHeight': 1184, u'naturalOrientation': True }


Получить размер окна

```python
print(d.window_size())
# пример вывода для вертикально расположенного устройства: (1080, 1920)
# пример вывода для горизонтально расположенного устройства: (1920, 1080)

Получить информацию о текущем приложении. Для некоторых Android-устройств вывод может быть пустым (см. Пример вывода 3)

print(d.app_current())
# Пример вывода 1: {'activity': '.Client', 'package': 'com.netease.example', 'pid': 23710}
# Пример вывода 2: {'activity': '.Client', 'package': 'com.netease.example'}
# Пример вывода 3: {'activity': None, 'package': None}

Ожидать активность

d.wait_activity(".ApiDemos", timeout=10) # по умолчанию timeout 10.0 секунд
# Вывод: true или false

Получить серийный номер устройства

print(d.serial)
# пример вывода: 74aAEDR428Z9

Получить IP-адрес WLAN

print(d.wlan_ip)
# пример вывода: 10.0.0.1

Получить подробную информацию о устройстве

print(d.device_info)

Вот пример вывода:

{'udid': '3578298f-b4:0b:44:e6:1f:90-OD103',
 'version': '7.1.1',
 'serial': '3578298f',
 'brand': 'SMARTISAN',
 'model': 'OD103',
 'hwaddr': 'b4:0b:44:e6:1f:90',
 'port': 7912,
 'sdk': 25,
 'agentVersion': 'dev',
 'display': {'width': 1080, 'height': 1920},
 'battery': {'acPowered': False,
  'usbPowered': False,
  'wirelessPowered': False,
  'status': 3,
  'health': 0,
  'present': True,
  'level': 99,
  'scale': 100,
  'voltage': 4316,
  'temperature': 272,
  'technology': 'Li-ion'},
 'memory': {'total': 3690280, 'around': '4 GB'},
 'cpu': {'cores': 8, 'hardware': 'Qualcomm Technologies, Inc MSM8953Pro'},
 'presenceChangedAt': '0001-01-01T00:00:00Z',
 'usingBeganAt': '0001-01-01T00:00:00Z'}
```### Буфер обмена
Установка или получение содержимого буфера обмена

Установка или получение содержимого буфера обмена (известная проблема: с версии Android 9.0 и выше, приложения в фоновом режиме не могут получить содержимое буфера обмена)

* clipboard/set_clipboard

    ```python
    d.set_clipboard('text', 'label')
    print(d.clipboard)
    ```

### События клавиш

* Включение/выключение экрана

    ```python
    d.screen_on() # включить экран
    d.screen_off() # выключить экран
    ```

* Получить текущий статус экрана

    ```python
    d.info.get('screenOn') # требует Android >= 4.4
    ```

* Нажать физическую или программную клавишу

    ```python
    d.press("home") # нажать клавишу home, с указанием имени клавиши
    d.press("back") # нажать клавишу back, с указанием имени клавиши
    d.press(0x07, 0x02) # нажать клавишу с кодом 0x07 ('0') с меткой META ALT (0x02)
    ```

* Эти ключевые названия поддерживаются в настоящее время:

    - home
    - back
    - left
    - right
    - up
    - down
    - center
    - menu
    - search
    - enter
    - delete (или del)
    - recent (приложения недавно использованные)
    - volume_up
    - volume_down
    - volume_mute
    - camera
    - power

Вы можете найти все определения кодов клавиш на [странице Android KeyEvent](https://developer.android.com/reference/android/view/KeyEvent.html)

* Разблокировка экрана

    ```python
    d.unlock()
    # Это эквивалентно
    # 1. запуск активности: com.github.uiautomator.ACTION_IDENTIFY
    # 2. нажатие клавиши "home"
    ```

### Взаимодействие жестами с устройством
* Нажатие на экран    ```python
    d.click(x, y)
    ```

* Двойное нажатие

    ```python
    d.double_click(x, y)
    d.double_click(x, y, 0.1) # стандартное время между двумя нажатиями 0.1с
    ```

* Долгое нажатие на экран

    ```python
    d.long_click(x, y)
    d.long_click(x, y, 0.5) # долгое нажатие 0.5с (по умолчанию)
    ```

* Проведение пальцем

    ```python
    d.swipe(sx, sy, ex, ey)
    d.swipe(sx, sy, ex, ey, 0.5) # проведение пальцем 0.5с (по умолчанию)
    ```

* Расширенное проведение пальцем

    ```python
    d.swipe_ext("right") # движение пальца вправо, 4 варианта "left", "right", "up", "down"
    d.swipe_ext("right", scale=0.9) # по умолчанию 0.9, расстояние движения составляет 90% ширины экрана
    d.swipe_ext("right", box=(0, 0, 100, 100)) # движение в области (0,0) -> (100, 100)

    # Также можно использовать Direction в качестве параметра
    from uiautomator2 import Direction
    
    d.swipe_ext(Direction.FORWARD) # прокрутка страницы вниз, эквивалентна d.swipe_ext("up"), только более понятная
    d.swipe_ext(Direction.BACKWARD) # прокрутка страницы вверх
    d.swipe_ext(Direction.HORIZ_FORWARD) # горизонтальное движение страницы вправо
    d.swipe_ext(Direction.HORIZ_BACKWARD) # горизонтальное движение страницы влево
    ```

* Перетаскивание

    ```python
    d.drag(sx, sy, ex, ey)
    d.drag(sx, sy, ex, ey, 0.5) # проведение пальцем 0.5с (по умолчанию)
    ```

* Перетаскивание по точкам

    ```python
    # проведение от точки (x0, y0) до точки (x1, y1) затем до точки (x2, y2)
    # время между двумя точками составляет 0.2с
    d.swipe_points([(x0, y0), (x1, y1), (x2, y2)], 0.2)
    ```    Часто используется для разблокировки экрана с помощью 9-квадратного кода, предварительно получив относительные координаты каждой точки (здесь поддерживаются проценты),
    более подробное использование см. в этом посте [использование u2 для разблокировки экрана с помощью 9-квадратного кода](https://testerhome.com/topics/11034). Тач и драг (Бета)    Этот интерфейс является одним из базовых, поэтому он может не быть идеально завершенным, но он работает. Примечание: в этом месте не поддерживаются процентные значения.

    ```python
    d.touch.down(10, 10) # Симулировать нажатие
    time.sleep(.01) # Задержка между down и move, контролируется самостоятельно
    d.touch.move(15, 15) # Симулировать движение
    d.touch.up() # Симулировать отпускание
    ```

Примечание: операции нажатия, свайпа и драга поддерживают процентные значения позиций. Пример:

`d.long_click(0.5, 0.5)` означает долгое нажатие в центре экрана

### Экран
* Получить/Установить ориентацию устройства

    Возможные ориентации:

    -   `natural` или `n`
    -   `left` или `l`
    -   `right` или `r`
    -   `upsidedown` или `u` (не может быть установлена)

    ```python
    # получить ориентацию. Вывод может быть "natural", "left", "right" или "upsidedown"
    orientation = d.orientation

    # ВНИМАНИЕ: не проходит тестирование на моем TT-M1
    # установить ориентацию и заморозить вращение.
    # примечание: установка "upsidedown" требует Android>=4.3.
    d.set_orientation('l') # или "left"
    d.set_orientation("l") # или "left"
    d.set_orientation("r") # или "right"
    d.set_orientation("n") # или "natural"
    ```

* Заморозить/Разморозить вращение

    ```python
    # заморозить вращение
    d.freeze_rotation()
    # разморозить вращение
    d.freeze_rotation(False)
    ```

* Сделать скриншот    ```python
    # сделать скриншот и сохранить в файл на компьютере, требуется Android>=4.2.
    d.screenshot("home.jpg")
    
    # получить изображение в формате PIL.Image. Важно, что pillow должен быть установлен первым
    image = d.screenshot() # по умолчанию format="pillow"
    image.save("home.jpg") # или home.png. В настоящее время поддерживаются только png и jpg
    ```    # Получить изображение в формате OpenCV. Важно, что numpy и cv2 должны быть установлены первым
    import cv2
    image = d.screenshot(format='opencv')
    cv2.imwrite('home.jpg', image)

    # Получить сырые данные JPEG
    imagebin = d.screenshot(format='raw')
    open("some.jpg", "wb").write(imagebin)
    ```

* Выгрузить иерархию UI

    ```python
    # Получить содержимое выгрузки иерархии UI (в unicode).
    xml = d.dump_hierarchy()
    ```

* Открыть уведомления или быстрые настройки

    ```python
    d.open_notification()
    d.open_quick_settings()
    ```

### Выбор

Выбор — это удобный механизм для идентификации конкретного объекта UI в текущем окне.```python
# Выбрать объект с текстом 'Clock' и его className равен '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

Дочерние и братские элементы

  • дочерние элементы

    # Получить дочерние или внучатые элементы
    d(className="android.widget.ListView").child(text="Bluetooth")
  • братские элементы

    # Получить братские элементы
    d(text="Google").sibling(className="android.widget.ImageView")
  • дочерние элементы по тексту, описанию или инстансу ```python

    получить дочерний элемент, соответствующий условию className="android.widget.LinearLayout"

    и также его дочерние или внучатые элементы с текстом "Bluetooth"

    d(className="android.widget.ListView", resourceId="android:id/list")
    .child_by_text("Bluetooth", className="android.widget.LinearLayout")

    получить дочерние элементы, разрешив поиск при прокрутке

    d(className="android.widget.ListView", resourceId="android:id/list")
    .child_by_text( "Bluetooth", allow_scroll_search=True, className="android.widget.LinearLayout" )

    
    - `child_by_description` используется для поиска дочерних элементов, у которых есть внучатые элементы с указанным описанием. Другие параметры аналогичны `child_by_text`.
    
    - `child_by_instance` используется для поиска дочерних элементов, у которых есть дочерний элемент UI в любой точке их подиерархии, который находится на указанном инстансе. Это выполняется на видимых элементах **без прокрутки**.
    
    См. ниже ссылки для подробной информации:
    
    -   [UiScrollable](http://developer.android.com/tools/help/uiautomator/UiScrollable.html), `getChildByDescription`, `getChildByText`, `getChildByInstance`
    -   [UiCollection](http://developer.android.com/tools/help/uiautomator/UiCollection.html), `getChildByDescription`, `getChildByText`, `getChildByInstance`
    
    Вышеупомянутые методы поддерживают цепочное вызов, например, для следующей иерархии  ```xml
    <node index="0" text="" resource-id="android:id/list" class="android.widget.ListView" ...>
      <node index="0" text="WIRELESS & NETWORKS" resource-id="" class="android.widget.TextView" .../>
      <node index="1" text="" resource-id="" class="android.widget.LinearLayout" ...>
        <node index="1" text="" resource-id="" class="android.widget.RelativeLayout" ...>
          <node index="0" text="Wi-Fi" resource-id="android:id/title" class="android.widget.TextView" .../>
        </node>
        <node index="2" text="ON" resource-id="com.android.settings:id/switchWidget" class="android.widget.Switch" .../>
      </node>
      ...
    </node>

    настройки Чтобы нажать переключатель справа от TextView 'Wi-Fi', сначала нужно выбрать переключатель. Однако, согласно иерархии UI, существует более одного переключателя с почти одинаковыми свойствами. Выбор по классу не сработает. Вместо этого можно использовать следующую стратегию выбора:

    d(className="android.widget.ListView", resourceId="android:id/list") \
      .child_by_text("Wi-Fi", className="android.widget.LinearLayout") \
      .child(className="android.widget.Switch") \
      .click()
  • относительное позиционирование

    Также можно использовать методы относительного позиционирования для получения представления: left, right, top, bottom.

    • d(A).left(B), выбирает B слева от A.
    • d(A).right(B), выбирает B справа от A.
    • d(A).up(B), выбирает B выше A.
    • d(A).down(B), выбирает B ниже A.

    Таким образом, для вышеупомянутых случаев можно выбрать переключатель следующим образом:

    ## выбрать "switch" справа от "Wi-Fi"
    d(text="Wi-Fi").right(className="android.widget.Switch").click()
  • Множество экземпляров

    Иногда экран может содержать несколько представлений с одинаковыми свойствами, например, текстом, тогда вам придется использовать свойство "instance" в селекторе для выбора одного из соответствующих экземпляров, как показано ниже:

    d(text="Добавить новое", instance=0)  # что означает первый экземпляр с текстом "Добавить новое"

    Кроме того, uiautomator2 предоставляет API вроде списка (аналогичный jQuery): ```python

    получить количество просмотров с текстом "Добавить новое" на текущем экране

    d(text="Добавить новое").count

    len(d(text="Добавить новое"))
    
    # получить экземпляр по индексу
    d(text="Добавить новое")[0]
    d(text="Добавить новое")[1]
    ...
    
    # итератор
    for view in d(text="Добавить новое"):
        view.info  # ...
    

    Примечания: при использовании селекторов в блоке кода, который проходит по списку результатов, необходимо убедиться, что элементы пользовательского интерфейса на экране остаются неизменными. В противном случае, при итерации по списку может возникнуть ошибка "Элемент не найден".

Получить статус и информацию выбранного объекта пользовательского интерфейса

  • Проверить, существует ли конкретный объект пользовательского интерфейса

    d(text="Настройки").exists # True, если существует, иначе False
    d.exists(text="Настройки") # псевдоним для указанного свойства.
    
    # продвинутое использование
    d(text="Настройки").exists(timeout=3) # ждать появления Настроек в течение 3 секунд, аналогично .wait(3)
  • Получить информацию о конкретном объекте пользовательского интерфейса

    d(text="Настройки").info

    Ниже приведен пример вывода: ``` { "contentDescription": "", "checked": False, "scrollable": False, "text": "Настройки", "packageName": "com.android.launcher", "selected": False, "enabled": True, "bounds": { "top": 385, "right": 360, "bottom": 585, "left": 200}, "className": "android.widget.TextView", "focused": False, "focusable": True, "clickable": True, "chileCount": 0, "longClickable": True, "visibleBounds": { "top": 385, "right": 360, "bottom": 585, "left": 200}, "checkable": False }

    
    ```python
    d(text="Настройки").get_text()  # получить текст виджета
    d(text="Настройки").set_text("Мой текст...")  # установить текст
    d(text="Настройки").clear_text()  # очистить текст
  • Получить центральную точку виджета

    x, y = d(text="Настройки").center()
    # x, y = d(text="Настройки").center(offset=(0, 0)) # левая верхняя x, y
  • Сделать снимок экрана виджета

    im = d(text="Настройки").screenshot()
    im.save("настройки.jpg")

Выполните действие нажатия на выбранный объект пользовательского интерфейса

  • Выполните нажатие на конкретный объект

    # нажмите в центре конкретного объекта пользовательского интерфейса
    d(text="Настройки").click()
    
    # подождите появление элемента в течение 10 секунд, а затем нажмите
    d(text="Настройки").click(timeout=10)
    
    # нажмите с смещением (x_offset, y_offset)
    # click_x = x_offset * width + x_left_top
    # click_y = y_offset * height + y_left_top
    d(text="Настройки").click(offset=(0.5, 0.5)) # По умолчанию центр
    d(text="Настройки").click(offset=(0, 0)) # Нажмите в верхнем левом углу
    d(text="Настройки").click(offset=(1, 1)) # Нажмите в нижнем правом углу
    
    # нажмите, если элемент появился в течение 10 секунд, по умолчанию timeout 0 секунд
    clicked = d(text='Пропустить').click_exists(timeout=10.0)
    
    # нажмите, пока элемент не исчезнет, возвращает bool
    is_gone = d(text="Пропустить").click_gone(maxretry=10, interval=1.0) # maxretry по умолчанию 10, interval по умолчанию 1.0
    ```* Выполните долгое нажатие на конкретный объект пользовательского интерфейса
    
    ```python
    # долгое нажатие в центре конкретного объекта пользовательского интерфейса
    d(text="Настройки").long_click()

Действия жестов для конкретного объекта пользовательского интерфейса

  • Перетащите объект пользовательского интерфейса к другой точке или к другому объекту пользовательского интерфейса

    # примечание: drag не может использоваться для Android<4.3.
    # перетащите объект пользовательского интерфейса к точке экрана (x, y), за 0.5 секунды
    d(text="Настройки").drag_to(x, y, duration=0.5)
    # перетащите объект пользовательского интерфейса к (центру) другого объекта пользовательского интерфейса, за 0.25 секунды
    d(text="Настройки").drag_to(text="Часы", duration=0.25)
  • Свайп с центра объекта пользовательского интерфейса к его краю

    Свайп поддерживает 4 направления:

    • left
    • right
    • top
    • bottom
    d(text="Настройки").swipe("right")
    d(text="Настройки").swipe("left", steps=10)
    d(text="Настройки").swipe("up", steps=20) # 1 шаг приблизительно 5 мс, так что 20 шагов приблизительно 0.1с
    d(text="Настройки").swipe("down", steps=20)
  • Двухточечный жест от одной точки к другой

    d(text="Настройки").gesture((sx1, sy1), (sx2, sy2), (ex1, ey1), (ex2, ey2))
  • Двухточечный жест на конкретном объекте пользовательского интерфейса

    Поддерживает два жеста:

    • In, от края к центру
    • Out, от центра к краю ```python

    примечание: pinch не может быть установлен до Android 4.3.

    от края к центру. здесь "In" (не "in")

    d(text="Настройки").pinch_in(percent=100, steps=10)

    от центра к краю

    d(text="Настройки").pinch_out()

    
      ```python
      # подождите, пока элемент UI появится
      d(text="Настройки").wait(timeout=3.0) # возвращает bool
      # подождите, пока элемент UI исчезнет
      d(text="Настройки").wait_gone(timeout=1.0)

    По умолчанию таймаут составляет 20 секунд. Подробнее см. глобальные настройки

  • Выполните прокрутку (fling) на конкретном элементе пользовательского интерфейса (скроллируемом)

    Возможные свойства:

    • horiz или vert
    • forward или backward или toBeginning или toEnd
    # прокрутка вперед (по умолчанию) вертикально (по умолчанию)
    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()
  • Выполните скролл на конкретном элементе пользовательского интерфейса (скроллируемом)

    Возможные свойства:

    • horiz или vert
    • forward или backward или toBeginning или toEnd, или to ```python

    scroll forward (default) vertically (default)

    d(scrollable=True).scroll(steps=10)

    scroll forward horizontally

    d(scrollable=True).scroll.horiz.forward(steps=100)

    scroll backward vertically

    d(scrollable=True).scroll.vert.backward()

    scroll to beginning horizontally

    d(scrollable=True).scroll.horiz.toBeginning(steps=100, max_swipes=1000)

    scroll to end vertically

    d(scrollable=True).scroll.toEnd()

    scroll forward vertically until a specific UI element appears

    d(scrollable=True).scroll.to(text="Безопасность")

    
    

Текущий watch_context запускается с помощью threading, и каждые 2 секунды проверяется.

В настоящее время существует только одна операция триггера — click.

with d.watch_context() as ctx:
    ctx.when("^Немедленно(скачать|обновить)").when("Отмена").click() # Когда одновременно появляются кнопки "Немедленно скачать" или "Немедленно обновить" и "Отмена", нажать "Отмена"
    ctx.when("Согласен").click()
    ctx.when("Ок").click()
    # Вышеуказанные три строки кода выполняются немедленно, без ожидания

    ctx.wait_stable() # Запустить мониторинг всплывающих окон и подождать, пока интерфейс станет стабильным (отсутствие новых всплывающих окон в течение двух периодов мониторинга означает стабильность)
# Используйте функцию call для вызова обратного вызова функции
# call поддерживает два параметра, d и el, порядок параметров не важен, параметры могут не передаваться, если передаются, имена переменных не должны быть написаны неправильно
# Пример: когда есть элемент, соответствующий "仲夏之夜", нажмите кнопку "назад"
ctx.when("仲夏之夜").call(lambda d: d.press("back"))
ctx.when("确定").call(lambda el: el.click())    # Другие операции# Для удобства можно использовать встроенные логики отслеживания, заданные по умолчанию в коде

Ниже приведены встроенные логики по умолчанию. Для добавления новых логик можно обратиться в группу и обратиться к администратору группы или отправить pull request (PR)

# when("Продолжить использование").click()
# when("Переместить в управление").when("Отмена").click()
# when("^Немедленно(скачать|обновить)").when("Отмена").click()
# when("Согласиться").click()
# when("^(Хорошо|Ок)").click()

with d.watch_context(builtin=True) as ctx: # Добавить на основе существующего ctx.when("@tb:id/jview_view").when('//*[@content-desc="изображение"]').click() # Другие логики скриптов


Другой вариант записи

```python
ctx = d.watch_context()
ctx.when("Настройки").click()
ctx.wait_stable() # Ждать, пока интерфейс не будет стабилен

ctx.close()

Watcher

Рекомендуется использовать WatchContext запись более компактная

Вы можете зарегистрировать watchers для выполнения некоторых действий, когда селектор не находит совпадение.

Версии до OnClickListener 2.0.0 использовали [Watcher]((http://developer.android.com/tools/help/uiautomator/UiWatcher.html) методы из uiautomator-jar библиотеки, но в практике было замечено, что все конфигурации watcher теряются, когда uiautomator завершает работу, что недопустимо. Поэтому в настоящее время используется метод запуска отдельного потока (с использованием библиотеки threading), который периодически выгружает структуру иерархии и выполняет соответствующие действия при нахождении элементов.

Пример использования

Регистрация отслеживания

# Обычный способ регистрации анонимного отслеживания
d.watcher.when("Установить").click()

# Регистрация отслеживания с именем ANR, которое нажимает "Force Close", когда появляются ANR или Force Close
d.watcher("ANR").when(xpath="ANR").when("Force Close").click()

# Примеры других вызовов обратного вызова
d.watcher.when("Поймать красный пакет").press("back")
d.watcher.when("//*[@text = 'Out of memory']").call(lambda d: d.shell('am force-stop com.im.qq'))

# Описание обратного вызова
def click_callback(d: u2.Device):
    d.xpath("Ок").click() # Вызов в обратном вызове не активирует watcher
``````python
d.xpath("Продолжить").click() # Использование d.xpath для проверки элемента активирует watcher (не более 5 раз)

Операции отслеживания

# Удаление отслеживания ANR
d.watcher.remove("ANR")

# Удаление всех отслеживаний
d.watcher.remove()

# Запуск фонового отслеживания
d.watcher.start()
d.watcher.start(2.0) # По умолчанию интервал отслеживания 2.0 секунды

# Выполнение всех отслеживаний
d.watcher.run()

Остановка мониторинга

d.watcher.stop()

Остановка и удаление всех мониторов, обычно используется при инициализации

d.watcher.reset()


### Документация по некоторым аспектам еще не завершена, рекомендуется обратиться к исходному коду [watcher.py](uiautomator2/watcher.py)

### Глобальные настройки

```python
d.HTTP_TIMEOUT = 60 # По умолчанию 60 секунд, время ожидания HTTP-запросов

# Время ожидания устройства при отключении, действует только при TMQ=true, поддерживает настройку через переменную окружения WAIT_FOR_DEVICE_TIMEOUT
d.WAIT_FOR_DEVICE_TIMEOUT = 70 

Другие настройки в основном собраны в d.settings, в зависимости от требований могут быть добавлены или удалены.

print(d.settings)
{'operation_delay': (0, 0),
 'operation_delay_methods': ['click', 'swipe'],
 'wait_timeout': 20.0,
 'xpath_debug': False}

# Настройка задержки перед кликом в 0.5 секунд и после клика в 1 секунду
d.settings['operation_delay'] = (.5, 1)

# Изменение методов, для которых задержка вступает в силу
# double_click и long_click соответствуют click
d.settings['operation_delay_methods'] = ['click', 'swipe', 'drag', 'press']
```d.settings['xpath_debug'] = True # Включение отладочного лога для плагина xpath
d.settings['wait_timeout'] = 20.0 # По умолчанию время ожидания элемента (для нативных операций и плагина xpath)

При обновлении версий, устаревшие настройки будут отмечены как Deprecated, но не будут вызывать исключений.

```bash
>>> d.settings['click_before_delay'] = 1  
[В 200514 14:55:59 settings:72] d.settings['click_before_delay'] deprecated: Используйте operation_delay вместо

Настройки восстановления uiautomator

Внимательный читатель может заметить, что на устройстве установлено два APK, один из которых виден на экране (желтый велосипед). Второй APK с пакетом com.github.uiautomator.test работает в фоновом режиме. Оба APK подписаны одним и тем же сертификатом. APK в фоновом режиме представляет собой тестовый пакет, содержащий все тестовые коды и основные тестовые службы, запускаемые через него. Однако, для работы системы требуется, чтобы желтый велосипед был запущен (даже в фоновом режиме). Как только этот APK убивается, фоновые тестовые службы также быстро прекращают работу. Даже если ничего не делать, система быстро уничтожит этот APK (здесь бы хотелось получить совет от опытных разработчиков, как сделать так, чтобы не зависеть от желтого велосипеда, теоретически это возможно, но пока я не знаю как).~~Для того чтобы желтый велосипед работал в фоновом режиме, есть два способа: запустить приложение и оставить его в фоновом режиме (по умолчанию) или запустить фоновую службу через am startservice.~~~~Чтобы настроить это поведение, можно использовать d.settings["uiautomator_runtest_app_background"] = True. Значение True означает запуск приложения, а False — запуск службы.~~Настройки таймаута в UiAutomator (скрытые методы)

>> d.jsonrpc.getConfigurator() 
{'actionAcknowledgmentTimeout': 500,
 'keyInjectionDelay': 0,
 'scrollAcknowledgmentTimeout': 200,
 'waitForIdleTimeout': 0,
 'waitForSelectorTimeout': 0}

>> d.jsonrpc.setConfigurator({"waitForIdleTimeout": 100})
{'actionAcknowledgmentTimeout': 500,
 'keyInjectionDelay': 0,
 'scrollAcknowledgmentTimeout': 200,
 'waitForIdleTimeout': 100,
 'waitForSelectorTimeout': 0}

Чтобы предотвратить срабатывание таймаута ответа клиента, waitForIdleTimeout и waitForSelectorTimeout были установлены в 0.

Ссылки: Google uiautomator Configurator

Метод ввода

Этот метод обычно используется для ввода в случае, когда неизвестны контролы. Первым шагом является переключение на метод ввода, а затем отправка команд adb. Конкретные методы использования приведены ниже.

d.set_fastinput_ime(True) # Переключение на FastInputIME
d.send_keys("Привет123abcEFG") # Отправка команд adb
d.clear_text() # Очистка поля ввода (Требуется версия android-uiautomator.apk >= 1.0.7)
d.set_fastinput_ime(False) # Переключение на обычный метод ввода
d.send_action("search") # Моделирование действия поиска

send_action параметры

Доступные параметры: go search send next done previous

Когда следует использовать этот метод?

Иногда после ввода текста в поле EditText, вызов press("search") или press("enter") не дает никакого ответа. В этом случае следует использовать метод send_action, который использует коды IME_ACTION (см. IME_ACTION_CODE). Метод send_action отправляет команду broadcast для ввода IME, которая затем завершает общение с полем EditText.### Toast (возвращено в версии 2.2 и выше) Показать Toast

d.toast.show("Привет, мир")
d.toast.show("Привет, мир", 1.0) # Показать на 1.0 секунду, по умолчанию 1.0 секунду

Получить Toast

# [Аргументы]
# 5.0: максимальное время ожидания. По умолчанию 10.0
# 10.0: время кэширования. Возвращает кэшированный Toast, если он был показан в течение последних 10 секунд. По умолчанию 10.0 (может измениться в будущем)
# "default message": возвращаемое значение, если Toast не был получен. По умолчанию None
d.toast.get_message(5.0, 10.0, "default message")

Общее использование

assert "Короткое сообщение" in d.toast.get_message(5.0, default="")

Очистка кэшированного уведомления

d.toast.reset()

Теперь d.toast.get_message(0) равно None


### XPath
По умолчанию в Java uiautoamtor не поддерживается XPath, поэтому это расширение функциональности. Скорость не такая высокая.

Пример: содержимое одного из узлов

```xml
<android.widget.TextView
  index="2"
  text="05:19"
  resource-id="com.netease.cloudmusic:id/qf"
  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="[957,1602][1020,1636]" />

Методы локализации и использования XPath

Некоторые имена атрибутов были изменены, что следует учитывать

description -> content-desc
resourceId -> resource-id

Частые методы использования```python

ждать существования 10 секунд

d.xpath("//android.widget.TextView").wait(10.0)

найти и нажать

d.xpath("//*[@content-desc='поделиться']").click()

проверить существование

if d.xpath("//android.widget.TextView[contains(@text, 'Se')]").exists: print("существует")

получить все тексты TextView, атрибуты и центральные точки

for elem in d.xpath("//android.widget.TextView").all(): print("Текст:", elem.text) # Словарь, например: # {'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("Атрибуты:", elem.attrib) # Координаты, например: (100, 200) print("Позиция:", elem.center())


### Видеозапись
Видеозапись

Здесь не используется встроенный в телефон screenrecord-команда, а используется метод получения изображений с телефона и их объединения в видео. Поэтому требуется установка дополнительных зависимостей, таких как imageio, imageio-ffmpeg, numpy и т.д.
Поскольку некоторые зависимости могут быть достаточно большими, рекомендуется использовать зеркальную установку. Просто выполните следующую команду.

```bash
pip3 install -U "uiautomator2[image]" -i https://pypi.doubanio.com/simple

Использование

d.screenrecord('output.mp4')

time.sleep(10)
# или выполните другое действие

d.screenrecord.stop() # После остановки записи файл output.mp4 становится доступным для открытия

Во время записи можно также указать fps (текущее значение — 20), это значение должно быть ниже скорости передачи изображений minicap, и, похоже, это уже хорошо, поэтому не рекомендуется изменять его.

Изображение и соответствующие методы

Методы для работы с изображениями, перед использованием этих функций вам нужно будет установить зависимости

pip3 install -U "uiautomator2[image]" -i https://pypi.doubanio.com/simple

В настоящее время доступны два метода

imdata = "target.png" # Также может быть URL, изображение PIL или изображение, открытое с помощью OpenCV

d.image.match(imdata) 
# Соответствует изображению для поиска и немедленно возвращает результат
# Возвращает словарь, например: {"similarity": 0.9, "point": [200, 300]}
``````python
d.image.click(imdata, timeout=20.0)
# В течение 20 секунд выполняет поиск изображения с помощью match, и при similarity>0.9 выполняет действие клика

Эта функция все еще находится в стадии разработки, поэтому изображения должны быть оригинальными снимками с телефона.

Часто задаваемые вопросы

Многие вопросы, которые не указаны здесь, находятся здесь Часто задаваемые вопросы

Остановка UiAutomator

Остановка службы UiAutomator

https://github.com/openatx/uiautomator2/wiki/Common-issues

Из-за наличия atx-agent, UiAutomator будет постоянно запущен. Если он завершит работу, он будет автоматически перезапущен. Однако UiAutomator также является доминирующим, и если он запущен, вспомогательные функции на телефоне и uiautomatorviewer на компьютере не будут работать, пока UiAutomator не будет остановлен. Ниже приведены два способа остановки

Способ 1:

Просто откройте приложение UiAutomator (установленное после успешного инициализации), и нажмите Остановить UiAutomator

Способ 2:

d.service("uiautomator").stop()

# d.service("uiautomator").start() # Запуск
# d.service("uiautomator").running() # Проверка запущен ли он

Методы совместного использования ATX и Maxim AccessibilityService

Рекомендованные статьи

Рекомендованные статьи (добро пожаловать, чтобы сообщить мне об этом в QQ-группе)

* Проект переработан из <https://github.com/xiaocong/uiautomator>

## Различия между Google UiAutomator 2.0 и 1.x
https://www.cnblogs.com/insist8089/p/6898181.html## [ИЗМЕНЕНИЯ (сгенерированы pbr)](CHANGELOG)
Основные обновления

- 1.0.0

    Удалено `d.watchers.watched` (замедляет выполнение автоматизации и снижает стабильность)


## Зависимые проекты
- uiautomator守护程序 <https://github.com/openatx/atx-agent>
- uiautomator jsonrpc сервер <https://github.com/openatx/android-uiautomator-server/>

# Участники проекта
- codeskyblue ([@codeskyblue][])
- Xiaocong He ([@xiaocong][])
- Yuanyuan Zou ([@yuanyuan][])
- Qian Jin ([@QianJin2013][])
- Xu Jingjie ([@xiscoxu][])
- Xia Mingyuan ([@mingyuan-xia][])
- Artem Iglikov, Google Inc. ([@artikz][])

[@codeskyblue]: https://github.com/codeskyblue
[@xiaocong]: https://github.com/xiaocong
[@yuanyuan]: https://github.com/yuanyuanzou
[@QianJin2013]: https://github.com/QianJin2013
[@xiscoxu]: https://github.com/xiscoxu
[@mingyuan-xia]: https://github.com/mingyuan-xia
[@artikz]: https://github.com/artikz

Другие [участники](../../graphs/contributors)

uiautomator守护程序 переводится как "uiautomator守护程序" (так как это название проекта, оставляем его без изменений).## Другие замечательные проекты
- [google/mobly](https://github.com/google/mobly) Внутренний тестовый фреймворк Google, хотя я не очень в нем разбираюсь, но он выглядит полезным.
- https://www.appetizer.io/ Включает удобный IDE для быстрого написания скриптов, а также возможность встраивания для сбора данных о производительности.
- https://github.com/atinfo/awesome-test-automation Сборник всех замечательных тестовых фреймворков, охватывает все аспекты.
- http://www.sikulix.com/ Автоматизированный тестовый фреймворк на основе распознавания изображений, очень старый.
- http://airtest.netease.com/ Предшественник данного проекта, позже он был принят и продолжил развиваться командой из NetEase Guangzhou. Реализует удобный IDE.

## Лицензия
[MIT](LICENSE)

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Автоматизация Android с использованием uiautomator Развернуть Свернуть
MIT
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/supernatural-fork-uiautomator2.git
git@api.gitlife.ru:oschina-mirror/supernatural-fork-uiautomator2.git
oschina-mirror
supernatural-fork-uiautomator2
supernatural-fork-uiautomator2
master