# AppiumExtended  

Представляем вам библиотеку расширяющую возможности фреймворка [Appium-Python-Client](https://github.com/appium/python-client). С AppiumExtended вам будут доступны новые удобные функции и возможности, которые позволят более эффективно и легко автоматизировать ваши тесты. Позвольте вашим разработчикам сосредоточиться на более сложных задачах, а наша библиотека облегчит взаимодействие с Appium и сделает процесс автоматизации более приятным и эффективным. Дайте вашим тестам возможность раскрыть свой полный потенциал с помощью этого интуитивного расширения для [Appium-Python-Client](https://pypi.org/project/Appium-Python-Client/).

### ВНИМАНИЕ !

**Вероятно библиотека не установится с первого раза,** из за **Pillow** и его зависимости **zlib**. Попробуйте ввести команду:
```
pip cache purge
```
И повторить установку.
# Системные требования

Для успешной установки и работы с AppiumExtended вам могут понадобиться некоторые системные зависимости.
### Установка Appium

Требуется установить [Appium](https://github.com/appium/appium) с плагинами: appium-device-farm, appium-dashboard.  

```
npm i -g appium@next  
appium driver install uiautomator2  
appium plugin install --source=npm appium-device-farm  
appium plugin install --source=npm appium-dashboard
```

# Установка AppiumExtended

Существует три способа установки AppiumExtended.

1. Установка из [PyPi](https://pypi.org/), как ['AppiumExtended'](https://pypi.org/project/AppiumExtended/).
    
    ```shell
    pip install AppiumExtended
    ```
    
    Историю выпусков можно посмотреть [здесь](https://pypi.org/project/AppiumExtended/#history)
    
2. Установка исходного кода, через [PyPi](https://pypi.org/). Из ['AppiumExtended'](https://pypi.org/project/AppiumExtended/), скачайте и разархивируйте исходный архив (AppiumExtended-X.X.tar.gz).
    
    ```shell
    tar -xvf AppiumExtended-X.X.tar.gz
    cd AppiumExtended-X.X
    python setup.py install
    ```
    
3. Установка исходного кода из [GitHub](https://github.com/molokov-klim/appium_extended).
    
    ```shell
    git clone https://github.com/molokov-klim/appium_extended.git
    cd appium_extended
    python setup.py install
    ```

# Содержание

### [class `AppiumExtended`](https://github.com/molokov-klim/appium_extended#class-appiumextended)

- [connect](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-connect)
- [disconnect](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-disconnect)
- [is_running](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_running)
- [get_element](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_element)
- [find_and_get_element](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-find_and_get_element)
- [get_elements](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_elements)
- [get_image_coordinates](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_image_coordinates)
- [get_inner_image_coordinates](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_inner_image_coordinates)
- [get_many_coordinates_of_image](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_many_coordinates_of_image)
- [get_text_coordinates](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_text_coordinates)
- [get_screenshot_as_base64_decoded](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_screenshot_as_base64_decoded)
- [get_element_contains](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_element_contains)
- [get_elements_contains](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_elements_contains)
- [is_element_within_screen](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_element_within_screen)
- [is_text_on_screen](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_text_on_screen)
- [is_image_on_the_screen](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_image_on_the_screen)
- [tap](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-tap)
- [swipe](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-swipe)
- [swipe_top_to_bottom](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-swipe_top_to_bottom)
- [swipe_bottom_to_top](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-swipe_bottom_to_top)
- [swipe_right_to_left](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-swipe_right_to_left)
- [swipe_left_to_right](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-swipe_left_to_right)
- [wait_for](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-wait_for)
- [wait_for_not](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-wait_for_not)
- [wait_return_true](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-wait_return_true)
- [draw_by_coordinates](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-draw_by_coordinates)
- [input_by_virtual_keyboard](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_by_virtual_keyboard)

### [class `WebElementExtended`](https://github.com/molokov-klim/appium_extended#class-webelementextended)

- [get_element](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_element-1)
- [get_attributes](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_attributes)
- [click](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-click)
- [double_click](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-double_click)
- [click_and_move](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-click_and_move)
- [adb_tap](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-adb_tap)
- [adb_multi_tap](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-adb_multi_tap)
- [adb_swipe](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-adb_swipe)
- [tap](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-tap-1)
- [double_tap](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-double_tap)
- [tap_and_move](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-tap_and_move)
- [get_elements](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_elements-1)
- [scroll_down](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-scroll_down)
- [scroll_up](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-scroll_up)
- [scroll_to_bottom](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-scroll_to_bottom)
- [scroll_to_top](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-scroll_to_top)
- [scroll_until_find](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-scroll_until_find)
- [get_parent](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_parent)
- [get_parents](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_parents)
- [get_sibling](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_sibling)
- [get_siblings](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_siblings)
- [get_cousin](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_cousin)
- [get_cousins](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_cousins)
- [is_contains](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_contains)
- [zoom](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-zoom)
- [unzoom](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-unzoom)
- [get_center](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_center)
- [get_coordinates](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_coordinates)

### [class `AppiumServer`](https://github.com/molokov-klim/appium_extended#class-appiumserver)

- [start](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-start)
- [is_alive](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_alive)
- [stop](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-stop)
- [wait_until_alive](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-wait_until_alive)

### [class `AppiumNavigator`](https://github.com/molokov-klim/appium_extended#class-appiumnavigator)

- [add_page](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-add_page)
- [navigate](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-navigate)
- [find_path](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-find_path)
- [perform_navigation](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-perform_navigation)

### [class `Aapt`](https://github.com/molokov-klim/appium_extended#class-aapt)

- [get_package_name](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_package_name)
- [get_launchable_activity](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_launchable_activity)

### [class `Terminal`](https://github.com/molokov-klim/appium_extended#class-terminal)

- [adb_shell](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-adb_shell)
- [push](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-push)
- [pull](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-pull)
- [start_activity](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-start_activity)
- [get_current_app_package](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_current_app_package)
- [close_app](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-close_app)
- [reboot_app](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-reboot_app)
- [uninstall_app](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-uninstall_app)
- [is_app_installed](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_app_installed)
- [press_home](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-press_home)
- [press_back](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-press_back)
- [press_menu](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-press_menu)
- [input_keycode_num](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_keycode_num_)
- [input_keycode](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_keycode)
- [input_by_virtual_keyboard](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_by_virtual_keyboard-1)
- [input_text](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_text)
- [tap](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-tap-2)
- [swipe](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-swipe-1)
- [check_vpn](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-check_vpn)
- [stop_logcat](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-stop_logcat)
- [know_pid](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-know_pid)
- [is_process_exist](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_process_exist)
- [run_background_process](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-run_background_process)
- [kill_by_pid](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-kill_by_pid)
- [kill_all](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-kill_all)
- [delete_files_from_internal_storage](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-delete_files_from_internal_storage)
- [delete_file_from_internal_storage](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-delete_file_from_internal_storage)
- [record_video](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-record_video)
- [stop_video](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-stop_video)
- [reboot](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-reboot)
- [get_screen_resolution](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_screen_resolution)


### [class `Adb`](https://github.com/molokov-klim/appium_extended#class-adb)

1. [install_app](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-install_app-1)
2. [is_app_installed](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_app_installed-1)
3. [uninstall_app](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-uninstall_app-1)
4. [get_device_model](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_device_model)
5. [push](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-push-1)
6. [pull](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-pull-1)
7. [start_activity](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-start_activity-1)
8. [close_app](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-close_app-1)
9. [reboot_app](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-reboot_app-1)
10. [press_home](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-press_home-1)
11. [press_back](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-press_back-1)
12. [press_menu](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-press_menu-1)
13. [input_keycode_num](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_keycode_num_-1)
14. [input_keycode](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_keycode-1)
15. [input_by_virtual_keyboard](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_by_virtual_keyboard-2)
16. [input_text](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-input_text-1)
17. [tap](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-tap-3)
18. [swipe](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-swipe-2)
19. [get_current_app_package](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_current_app_package-1)
20. [check_vpn](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-check_vpn-1)
21. [stop_logcat](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-stop_logcat-1)
22. [reload_adb](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-reload_adb)
23. [know_pid](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-know_pid-1)
25. [is_process_exist](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-is_process_exist-1)
26. [run_background_process](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-run_background_process-1)
27. [kill_by_pid](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-kill_by_pid-1)
28. [kill_by_name](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-kill_by_name)
29. [kill_all](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-kill_all-1)
30. [delete_files_from_internal_storage](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-delete_files_from_internal_storage-1)
31. [pull_video](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-pull_video)
32. [stop_video](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-stop_video-1)
33. [record_video](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-record_video-1)
34. [reboot](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-reboot-1)
35. [get_screen_resolution](https://github.com/molokov-klim/appium_extended#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-get_screen_resolution-1)

# class AppiumExtended
Основной класс расширяющий Appium-Python-Client.  

## Метод: `connect()`

Метод `connect` выполняет подключение к устройству на основе заданных возможностей или свойств, передаваемых в формате словаря.

### Параметры

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

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

```python
app = AppiumExtended()

capabilities_with_install = {  
"platformName": "android",  
"appium:automationName": "uiautomator2",  
"appium:deviceName": device_model,  
"appium:udid": device_uuid,  
"appium:app": path_to_apk,  
"appium:appPackage": package,  
"appium:appWaitActivity": activity_launchable,  
"appium: autoGrantPermissions": True,  
}

capabilities_without_install = {  
"platformName": "android",  
"appium:automationName": "uiautomator2",  
"appium:deviceName": device_model,  
"appium:udid": device_uuid,  
"appium:noReset": True,  
"appium: autoGrantPermissions": True,  
}

app.connect(capabilities=self.capabilities_without_install)
```

### Детали реализации

Метод включает следующие основные этапы:

1. Сохранение переданных возможностей в свойстве объекта `self.capabilities`.
2. Запуск локального сервера Appium, если не используется прокси и сервер ещё не запущен. Для запуска сервера используется задержка в 10 секунд, чтобы дать ему время для инициализации.
3. Инициализация драйвера `webdriver.Remote` с заданными возможностями и адресом сервера. Сохранение драйвера в свойстве объекта `self.driver`.
4. Инициализация объекта `AppiumImage` с созданным драйвером.
5. Запись в лог информации о подключении и номере сессии драйвера.

### Исключения

Метод не генерирует исключения напрямую, но может пробросить исключения, сгенерированные внутренними вызовами, такими как ошибка запуска сервера Appium или ошибки, связанные с `webdriver.Remote`.

### Дополнительная информация

В связи с использованием appium-device-farm указывать device udid необязательно.
```python
capabilities = {  
"platformName": "android",  
"appium:automationName": "uiautomator2",   
}
```
	

## Метод: `disconnect()`

Метод `disconnect` отвечает за отключение от устройства. 

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

```python
app.disconnect()
```

### Детали реализации

1. Проверка, установлен ли драйвер (`self.driver`). Если драйвер установлен, то выполняется его завершение с помощью метода `quit()` и затем драйвер обнуляется. В процессе выполнения этих операций в лог записывается информация о номере сессии, от которой происходит отключение.
2. Если не установлено значение `self.keep_alive_server`, то останавливается работа сервера с помощью метода `stop()`.

### Исключения

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


## Метод: `is_running()`

Метод `is_running` проверяет, активна ли текущая сессия драйвера.

### Возвращаемое значение

Возвращает `True` если текущая сессия драйвера активна, и `False` в противном случае.

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

```python
if device.is_running():
    print("Устройство активно")
else:
    print("Устройство не активно")
```

### Исключения

Метод может генерировать исключения, в случае если `self.driver` не инициализирован. Также исключения могут быть сгенерированы внутренними вызовами метода `is_running` из объекта `self.driver`, например, при проблемах сети или сервера.


## Метод: `get_element()`

Этот метод обеспечивает поиск элемента в текущей структуре DOM. Метод должен получать либо локатор, либо значения `by` и `value`.

### Параметры

`locator`: Определяет локатор элемента. Это может быть:
- кортеж - локатор в виде ('стратегия поиска', 'значение')
- объект WebElement
- словарь, содержащий пары атрибут: значение искомого элемента
- строка - путь до файла с изображением элемента.

`by`: Тип локатора для поиска элемента (всегда в связке с `value`). Может быть типом MobileBy, AppiumBy, By, или строкой.

`value`: Значение локатора, если используется AppiumBy.XPATH. Может быть строкой, словарём или `None`.

`timeout_elem`: Время ожидания элемента в секундах.

`timeout_method`: Время ожидания метода поиска элемента в секундах.

`elements_range`: Ограничивает поиск элемента в указанном диапазоне. Используется при поиске по изображению. Может быть кортежем, списком, словарём или `None`.

`contains`: Используется для поиска по словарю. Если `True`, ищет элемент, содержащий фрагмент значения.

### Возвращаемое значение

Возвращает объект WebElementExtended или `None`, если элемент не был найден.

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

```python
element = app.get_element(locator=("id", "foo"))
element = app.get_element(element)
element = app.get_element(locator={'text': 'foo'})
element = app.get_element(locator='/path/to/file/pay_agent.png')
element = app.get_element(locator=part_image, elements_range={'class':'android.widget.FrameLayout', 'package':'ru.app.debug'})
element = app.get_element(by="id", value="ru.sigma.app.debug:id/backButton")
element = app.get_element(by=MobileBy.ID, value="ru.sigma.app.debug:id/backButton")
element = app.get_element(by=AppiumBy.ID, value="ru.sigma.app.debug:id/backButton")
element = app.get_element(by=By.ID, value="ru.sigma.app.debug:id/backButton")
```

### Исключения

Метод может генерировать исключения, в случае если введены некорректные аргументы или возникают ошибки при обработке элементов (например, `NoSuchElementException`, `TimeoutException` или `WebDriverException`).

## Метод: `find_and_get_element()`

Этот метод используется для поиска элемента. Если элемент не найден, метод будет скроллить все скроллируемые элементы, пока не найдет искомый элемент или пока не будет проскроллено все доступное пространство.

### Параметры

- `locator` (Union[Tuple, WebElement, 'WebElementExtended', Dict[str, str], str]): Это местоположение или определение элемента, который нужно найти. Это может быть кортеж, экземпляр WebElement, словарь или строка.

- `timeout` (int, опционально): Это максимальное время ожидания для поиска элемента. По умолчанию это 10 секунд.

### Возвращаемое значение

Метод возвращает экземпляр `WebElementExtended`, если элемент найден. Если элемент не найден после прокрутки всей доступной страницы, возвращается `None`.

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

```python
element = app.find_and_get_element(locator={'id': 'element_id'})
```

### Дополнительная информация

Внутри этого метода сначала проверяется, виден ли элемент на экране с помощью `is_element_within_screen()`. Если это так, то элемент возвращается с помощью `get_element()`.

Если элемент не виден на экране, то метод производит поиск во всех доступных для прокрутки элементах страницы. Если элемент найден в каком-то из этих элементов, он возвращается. Если элемент не найден после прокрутки всей доступной страницы, метод возвращает `None`.



## Метод: `get_elements()`

Этот метод обеспечивает поиск элементов в текущей структуре DOM. Метод может получать либо локатор, либо пару значений `by` и `value`.

### Параметры

- `locator`: Определяет локатор элементов. Это может быть:
  - Кортеж - локатор в виде ('атрибут', 'значение')
  - Список объектов WebElement
  - Словарь, содержащий пары атрибут: значение
  - Строка - путь до файла с изображением элемента.
- `by`: Тип локатора для поиска элемента (всегда используется в связке с `value`). Может быть типом MobileBy, AppiumBy, By, или строкой.
- `value`: Значение локатора или словарь аргументов, если используется AppiumBy.XPATH. Может быть строкой, словарём или `None`.
- `timeout_elements`: Время ожидания в секундах для появления каждого элемента.
- `timeout_method`: Общее время ожидания в секундах для выполнения всего метода.
- `elements_range`: Ограничивает поиск элементов в указанном диапазоне. Используется при поиске по изображению. Может быть кортежем, списком, словарём или `None`.
- `contains`: Используется для поиска по словарю. Если `True`, ищет элементы, содержащие фрагмент значения.

### Возвращаемое значение

Возвращает список объектов WebElementExtended, или `None`, если элементы не были найдены.

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

```python
elements = app.get_elements(locator=("id", "foo"))
elements = app.get_elements(locator={'text': 'foo'})
elements = app.get_elements(locator='/path/to/file/pay_agent.png')
elements = app.get_elements(locator=part_image, elements_range={'class':'android.widget.FrameLayout', 'package':'ru.app.debug'})
elements = app.get_elements(by="id", value="ru.sigma.app.debug:id/backButton")
elements = app.get_elements(by=MobileBy.ID, value="ru.sigma.app.debug:id/backButton")
elements = app.get_elements(by=AppiumBy.ID, value="ru.sigma.app.debug:id/backButton")
elements = app.get_elements(by=By.ID, value="ru.sigma.app.debug:id/backButton")
```

### Исключения

Метод может генерировать исключения, в случае если введены некорректные аргументы или возникают ошибки при обработке элементов (например, `NoSuchElementException`, `TimeoutException` или `WebDriverException`).


## Метод: `get_image_coordinates()`

Этот метод находит координаты наиболее вероятного совпадения частичного изображения в полном изображении. Используется для поиска элементов или участков интерфейса на экране по изображению.

### Параметры

- `image`: Путь к файлу частичного изображения, которое нужно найти внутри полного изображения. Может быть байтами, массивом `np.ndarray`, объектом `Image.Image`, или строкой (путь к файлу).
    
- `full_image`: Путь к файлу полного изображения. Может быть байтами, массивом `np.ndarray`, объектом `Image.Image`, или строкой (путь к файлу). Если `None`, то будет использовано текущее скриншотное изображение.
    
- `threshold`: Минимальный порог совпадения, необходимый для считывания совпадения допустимым. По умолчанию равно 0.7.
    

### Возвращаемое значение

Возвращает кортеж с координатами наиболее вероятного совпадения в формате (x1, y1, x2, y2) или `None`, если совпадение не найдено.

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

```python
coords = app.get_image_coordinates(image="/path/to/partial/image.png", full_image="/path/to/full/image.png", threshold=0.8)
```

### Дополнительная информация

Этот метод использует декоратор `retry`, который выполняет функцию до тех пор, пока она не вернет результат, отличный от `None` или `False`, или пока не будет достигнуто максимальное количество попыток (3 попытки по умолчанию). После каждой неудачной попытки происходит пауза на 1 секунду.

### Исключения

Метод может генерировать исключения при обработке изображений или при работе с файлами.

## Метод: `get_inner_image_coordinates()`

Этот метод сначала находит изображение на экране (внешнее изображение), а затем находит другое изображение (внутреннее изображение) внутри обнаруженного изображения.

### Параметры

- `outer_image_path`: Путь к файлу с изображением, которое нужно найти на экране. Может быть байтами, массивом `np.ndarray`, объектом `Image.Image`, или строкой (путь к файлу).

- `inner_image_path`: Путь к файлу с изображением, которое нужно найти внутри внешнего изображения. Может быть байтами, массивом `np.ndarray`, объектом `Image.Image`, или строкой (путь к файлу).

- `threshold`: Пороговое значение сходства для шаблонного сопоставления. По умолчанию 0.9.

### Возвращаемое значение

Возвращает координаты внутреннего изображения относительно экрана в формате ((x1, y1), (x2, y2)). Если внутреннее изображение не найдено, возвращает `None`.

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

```python
coords = app.get_inner_image_coordinates(outer_image_path="/path/to/outer/image.png", inner_image_path="/path/to/inner/image.png", threshold=0.8)
```

### Дополнительная информация

Этот метод использует декоратор `retry`, который выполняет функцию до тех пор, пока она не вернет результат, отличный от `None` или `False`, или пока не будет достигнуто максимальное количество попыток (3 попытки по умолчанию). После каждой неудачной попытки происходит пауза на 1 секунду.

### Исключения

Метод может генерировать исключения при обработке изображений или при работе с файлами.


## Метод: `get_many_coordinates_of_image()`

Этот метод находит все вхождения частичного изображения внутри полного изображения.

### Параметры

- `image`: Путь к файлу частичного изображения, которое нужно найти внутри полного изображения. Может быть байтами, массивом `np.ndarray`, объектом `Image.Image`, или строкой (путь к файлу).

- `full_image`: Путь к файлу полного изображения. Может быть байтами, массивом `np.ndarray`, объектом `Image.Image`, или строкой (путь к файлу). Если `None`, то будет сделан скриншот экрана и использован как полное изображение.

- `cv_threshold`: Минимальный порог совпадения, необходимый для считывания совпадения допустимым. По умолчанию равно 0.7.

- `coord_threshold`: Целое число, представляющее максимальное различие между значениями x и y двух кортежей, чтобы они считались слишком близкими друг к другу. По умолчанию равно 5.

### Возвращаемое значение

Возвращает список кортежей, содержащий расположение каждого найденного совпадения. Если совпадений не найдено, возвращается `None`.

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

```python
matches = app.get_many_coordinates_of_image(image="/path/to/image.png", full_image="/path/to/full/image.png", cv_threshold=0.7, coord_threshold=5)
```

### Дополнительная информация

Этот метод использует декоратор `retry`, который выполняет функцию до тех пор, пока она не вернет результат, отличный от `None` или `False`, или пока не будет достигнуто максимальное количество попыток (3 попытки по умолчанию). После каждой неудачной попытки происходит пауза на 1 секунду.


### Исключения

Метод может генерировать исключения при обработке изображений или при работе с файлами.


## Метод: `get_text_coordinates()`

Этот метод возвращает координаты области, содержащей указанный текст на предоставленном изображении или снимке экрана. 

### Параметры

- `text`: Искомый текст.

- `language`: Язык для распознавания текста. По умолчанию 'rus'.

- `image`: Изображение, на котором осуществляется поиск текста. Может быть байтами, строкой (путь к файлу), объектом `Image.Image` или массивом `np.ndarray`. Если не указано, будет использован снимок экрана. По умолчанию `None`.

- `ocr`: Булев флаг, определяющий, следует ли использовать распознавание оптических символов (OCR) для извлечения текста из изображения. По умолчанию `True`.

### Возвращаемое значение

Возвращает кортеж из четырех целых чисел, представляющих координаты области с текстом (верхний левый угол и нижний правый угол). Если текст не найден, возвращается `None`.

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

```python
coordinates = app.get_text_coordinates(text="Hello, world!", language="eng", image="/path/to/image.png", ocr=True)
```

### Дополнительная информация

Если флаг `ocr` установлен в `False`, метод будет использовать внутреннюю реализацию поиска элемента для извлечения координат области, содержащей искомый текст.


## Метод: `get_screenshot_as_base64_decoded()`

Этот метод возвращает текущий снимок экрана в браузере, декодированный из формата base64 в байты.

### Параметры

Метод не требует никаких параметров.

### Возвращаемое значение

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

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

```python
screenshot = app._get_screenshot_as_base64_decoded()
```

### Дополнительная информация

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


## Метод: `get_element_contains()`

Этот метод пока не реализован. Ожидается, что он будет использоваться для поиска и возврата родительского элемента, который содержит определённый дочерний элемент.

### Параметры

На данный момент в методе нет параметров.

### Возвращаемое значение

На данный момент метод возвращает ошибку `NotImplementedError` при вызове, так как он ещё не реализован.

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

```python
# Этот метод еще не реализован, поэтому его нельзя вызвать.
```

### Дополнительная информация

В текущей реализации метод возвращает исключение `NotImplementedError` с сообщением "This method is not implemented yet". Это означает, что метод ещё не реализован. Предполагается, что в будущем он будет реализован для поиска и возврата родительского элемента, содержащего определённый дочерний элемент.



## Метод: `get_elements_contains()`

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

### Параметры

На данный момент в методе нет параметров.

### Возвращаемое значение

На данный момент метод возвращает ошибку `NotImplementedError` при вызове, так как он ещё не реализован.

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

```python
# Этот метод еще не реализован, поэтому его нельзя вызвать.
```

### Дополнительная информация

В текущей реализации метод возвращает исключение `NotImplementedError` с сообщением "This method is not implemented yet". Это означает, что метод ещё не реализован. Предполагается, что в будущем он будет реализован для поиска и возврата всех родительских элементов, содержащих определённые дочерние элементы.


## Метод: `is_element_within_screen()`

Этот метод проверяет, находится ли заданный элемент полностью на экране.

### Параметры

- `locator` (`Union[Tuple, WebElement, 'WebElementExtended', Dict[str, str], str]`): Локатор или элемент, который нужно проверить. Может быть кортежем, объектом WebElement, объектом WebElementExtended, словарем или строкой.
- `timeout` (`int`, необязательный): Время ожидания появления элемента в секундах. По умолчанию равно 10.

### Возвращаемое значение

- `bool`: Возвращает `True`, если элемент находится на видимой части экрана, и `False` в противном случае.

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

```python
# Допустим, мы хотим проверить, находится ли элемент с id 'some_id' на видимой части экрана.
is_visible = app.is_element_within_screen(locator=('id', 'some_id'))
```

### Дополнительная информация

Метод сначала получает размеры экрана, затем ищет элемент с помощью предоставленного локатора. Если элемент не найден или не отображается, метод возвращает `False`. Если элемент найден и отображается, метод проверяет, находятся ли координаты элемента в пределах размеров экрана. Если элемент находится за пределами экрана, метод возвращает `False`. В противном случае, если элемент находится в пределах видимой области экрана, метод возвращает `True`.


## Метод: `is_text_on_screen()`

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

### Параметры

- `text` (`str`): Текст, который нужно найти на экране.
- `ocr` (`bool`, необязательный): Определяет, производить ли поиск текста на изображении или в DOM. Если `True`, распознавание текста производится с помощью библиотеки `pytesseract`. Если `False`, производится поиск элемента по xpath. Значение по умолчанию: `True`.
- `language` (`str`, необязательный): Язык для распознавания текста. По умолчанию 'rus'.

### Возвращаемое значение

- `bool`: Возвращает `True`, если заданный текст найден на экране. В противном случае возвращает `False`.

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

```python
# Допустим, мы хотим проверить, находится ли текст 'Hello' на экране.
is_present = app.is_text_on_screen(text='Hello')
```

### Дополнительная информация

Метод использует разные подходы в зависимости от значения параметра `ocr`. Если `ocr=True`, то он использует библиотеку `pytesseract` для распознавания текста на изображении экрана. Если `ocr=False`, то он производит поиск элемента по xpath, используя текст как значение атрибута 'text' элемента.


## Метод: `is_image_on_the_screen()`

Этот метод сравнивает, присутствует ли заданное изображение на экране.

### Параметры

- `image` (`Union[bytes, np.ndarray, Image.Image, str]`): Изображение для поиска. Это может быть имя файла, байтовый поток, массив numpy или объект PIL Image.
- `threshold` (`float`, необязательный): Пороговое значение схожести части изображения со снимком экрана. По умолчанию 0.9.

### Возвращаемое значение

- `bool`: Возвращает `True`, если изображение найдено на экране. В противном случае возвращает `False`.

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

```python
# Допустим, мы хотим проверить, находится ли изображение 'button.png' на экране.
is_present = app._is_image_on_the_screen(image='button.png')
```

### Дополнительная информация

Метод сначала делает снимок текущего экрана, затем преобразует его и искомое изображение в оттенки серого для лучшего сопоставления. Затем используется метод `cv2.matchTemplate` для сопоставления мелкого изображения и снимка экрана. Затем используется `cv2.minMaxLoc` для извлечения максимального коэффициента схожести и его координат. Если максимальное значение превышает заданный порог, метод возвращает `True`, в противном случае `False`.

## Метод: `tap()`

Этот метод выполняет действие "тап" или "клик" по определенным координатам, элементу или изображению на экране.

### Параметры

- `locator` (`Union[Tuple[str, str], WebElementExtended, WebElement, Dict[str, str], str]`, необязательный): Элемент или локатор, на который нужно нажать.
- `x` (`int`, необязательный): X координата точки, по которой следует нажать.
- `y` (`int`, необязательный): Y координата точки, по которой следует нажать.
- `image` (`Union[bytes, np.ndarray, Image.Image, str]`, необязательный): Изображение, на котором следует нажать.
- `duration` (`Optional[int]`, необязательный): Продолжительность нажатия в миллисекундах.
- `timeout` (`int`, необязательный): Время ожидания в секундах перед тем как метод вернет `None`, если изображение не найдено на экране. По умолчанию равно 5.

### Возвращаемое значение

- `Union['AppiumExtended', None]`: Возвращает экземпляр класса `AppiumExtended`, если действие "тап" или "клик" успешно выполнено. В противном случае возвращает `None`.

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

```python
# Нажатие на элемент с указанным локатором
app.tap(locator=('id', 'button'))

# Нажатие по координатам
app.tap(x=100, y=200)

# Нажатие на изображение
app.tap(image='button.png')
```

### Дополнительная информация

Этот метод использует внутренний метод `_extract_point_coordinates_by_typing()` для получения координат точки, по которой следует нажать, если был передан `locator` или `image`. Если указано изображение, метод будет ожидать его появления на экране в течение указанного времени ожидания, прежде чем выполнить действие "тап". Затем вызывается внутренний метод `_tap()` для выполнения действия "тап" по заданным координатам.

## Метод: `swipe()`

Этот метод выполняет свайп (перетаскивание) элемента или изображения на экране.

### Параметры

- `start_position`: Позиция начала свайпа. Может быть задана в различных форматах:
  - Если `start_position` является кортежем и оба его элемента являются строками, то он представляет собой локатор элемента. В этом случае будет выполнен поиск элемента и используется его позиция.
  - Если `start_position` является словарем, то считается, что это локатор элемента, основанный на атрибутах. Например, {'text': 'some text'} или {'class': 'SomeClass', 'visible': 'true'}. В этом случае будет выполнен поиск элемента по указанным атрибутам, и используется его позиция.
  - Если `start_position` является экземпляром класса WebElement или WebElementExtended, то используется его позиция.
  - Если `start_position` является строкой, массивом байтов (bytes), массивом NumPy (np.ndarray) или объектом класса Image.Image, то считается, что это изображение. В этом случае будет вычислен центр изображения и используется его позиция.
  - Если `start_position` является кортежем, и оба его элемента являются целыми числами, то считается, что это координаты в формате (x_coordinate, y_coordinate).
- `end_position`: Позиция конца свайпа. Принимает те же форматы, что и `start_position`. По умолчанию None.
- `direction`: Направление свайпа. Принимает значения от 0 до 360 градусов. Если указано направление, то будет вычислена конечная точка свайпа на основе текущего размера окна и указанного расстояния. По умолчанию None.
- `distance`: Расстояние свайпа. Принимается в пикселях. Используется только в сочетании с параметром `direction`. По умолчанию None.
- `duration`: Продолжительность свайпа в миллисекундах. По умолчанию 0.

### Возвращаемое значение

- `AppiumExtended`: Экземпляр класса AppiumExtended.

### Примечания

- В качестве конечной позиции свайпа должен быть указан `end_position` или пара `direction, distance`.
- `str` принимается как путь к изображению на экране и вычисляется его центр, а не как локатор элемента

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

```python
# Свайп элемента на экране по указанным координатам
app.swipe(start_position=(100, 200), end_position=(300, 400))

# Свайп по направлению и расстоянию
app.swipe(start_position=('xpath', '//button[@id="submit"]'), direction=90, distance=100)

# Свайп изображения
app.swipe(start_position='image.png', end_position=(300, 400))
```

### Дополнительная информация

Метод обязательно должен принимать либо end_postition, либо direction и distance

## Метод: `swipe_top_to_bottom()`

Этот метод выполняет свайп (перетаскивание) с верхней части экрана к нижней.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

- `None`

### Примечания

- Метод использует функцию `adb.get_screen_resolution()` для определения размера экрана.
- Позиция начала свайпа (`start_position`) вычисляется как 10% от высоты экрана.
- Позиция конца свайпа (`end_position`) вычисляется как 90% от высоты экрана.

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

```python
# Свайп сверху вниз на экране
app.swipe_top_to_bottom()
```

## Метод: `swipe_bottom_to_top()`

Этот метод выполняет свайп (перетаскивание) с нижней части экрана к верхней.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

- `None`

### Примечания

- Метод использует функцию `adb.get_screen_resolution()` для определения размера экрана.
- Позиция начала свайпа (`start_position`) вычисляется как 90% от высоты экрана.
- Позиция конца свайпа (`end_position`) вычисляется как 10% от высоты экрана.
- Может использоваться для выдвигания шторки.

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

```python
# Свайп снизу вверх на экране
app.swipe_bottom_to_top()
```


## Метод: `swipe_right_to_left()`

Этот метод выполняет свайп (перетаскивание) с правой части экрана к левой.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

- `None`

### Примечания

- Метод использует функцию `adb.get_screen_resolution()` для определения размера экрана.
- Позиция начала свайпа (`start_position`) вычисляется как 90% от ширины экрана.
- Позиция конца свайпа (`end_position`) вычисляется как 10% от ширины экрана.

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

```python
# Свайп справа налево на экране
app.swipe_right_to_left()
```

## Метод: `swipe_left_to_right()`

Этот метод выполняет свайп (перетаскивание) с левой части экрана к правой.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

- `None`

### Примечания

- Метод использует функцию `adb.get_screen_resolution()` для определения размера экрана.
- Позиция начала свайпа (`start_position`) вычисляется как 10% от ширины экрана.
- Позиция конца свайпа (`end_position`) вычисляется как 90% от ширины экрана.

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

```python
# Свайп слева направо на экране
app.swipe_left_to_right()
```


## Метод: `wait_for()`

Этот метод ожидает появления на экране указанного локатора или изображения.

### Параметры

- `locator`: Локатор(ы), которые нужно ожидать. Может быть одним локатором или списком локаторов. Принимает форматы, аналогичные `start_position` в методе `swipe()`. По умолчанию None.
- `image`: Изображение(я), которые нужно ожидать. Может быть одним изображением или списком изображений. Принимает строку, массив байтов (bytes), массив NumPy (np.ndarray) или объект класса Image.Image. По умолчанию None.
- `timeout`: Максимальное время ожидания в секундах. По умолчанию 10.
- `contains`: Если True, проверяет, содержит ли элемент указанный локатор. Если False, проверяет, точно ли соответствует элемент указанному локатору. По умолчанию True.
- `full_image`: Основное изображение, на котором будет искаться `image`. Принимает строку, массив байтов (bytes), массив NumPy (np.ndarray) или объект класса Image.Image. По умолчанию None.

### Возвращаемое значение

- `bool`: True, если элемент(ы) или изображение(я) найдены в течение периода ожидания, иначе False.

### Примечания

- Этот метод использует приватный метод `_wait_for()`, который реализует основную логику ожидания.

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

```python
# Ожидание появления элемента по локатору
app.wait_for(locator=('xpath', '//button[@id="submit"]'), timeout=30)

# Ожидание появления изображения
app.wait_for(image='image.png', timeout=20)

# Ожидание появления нескольких элементов и изображений
app.wait_for(locator=[('id', 'button1'), ('id', 'button2')], image=['image1.png', 'image2.png'], timeout=40)
```


## Метод: `wait_for_not()`

Этот метод ожидает, пока указанный локатор или изображение не исчезнет с экрана или из DOM.

### Параметры

- `locator`: Локатор(ы), которые нужно ожидать. Может быть одним локатором или списком локаторов. Принимает форматы, аналогичные `start_position` в методе `swipe()`. По умолчанию None.
- `image`: Изображение(я), которые нужно ожидать. Может быть одним изображением или списком изображений. Принимает строку, массив байтов (bytes), массив NumPy (np.ndarray) или объект класса Image.Image. По умолчанию None.
- `timeout`: Максимальное время ожидания в секундах. По умолчанию 10.
- `contains`: Если True, проверяет, содержит ли элемент указанный локатор. Если False, проверяет, точно ли соответствует элемент указанному локатору. По умолчанию True.

### Возвращаемое значение

- `bool`: True, если элемент(ы) или изображение(я) исчезли в течение периода ожидания, иначе False.

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

```python
# Ожидание исчезновения элемента по локатору
app.wait_for_not(locator=('xpath', '//button[@id="submit"]'), timeout=30)

# Ожидание исчезновения изображения
app.wait_for_not(image='image.png', timeout=20)

# Ожидание исчезновения нескольких элементов и изображений
app.wait_for_not(locator=[('id', 'button1'), ('id', 'button2')], image=['image1.png', 'image2.png'], timeout=40)
```


## Метод: `wait_return_true()`

Этот метод ожидает, когда другой метод вернет True.

### Параметры

- `method`: ссылка на метод, который мы ожидаем.
- `timeout`: максимальное время ожидания в секундах. По умолчанию равно 10.

### Возвращаемое значение

- `bool`: возвращает True, если метод возвращает True в течение периода времени, указанного в timeout. В противном случае возвращает False.

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

```python
# Ожидаем, когда метод `check_login_status` вернет True в течение 20 секунд
result = AppiumExtended.wait_return_true(obj.check_login_status, timeout=20)

# Если `check_login_status` вернет True в течение 20 секунд, тогда `result` будет True, иначе `result` будет False.

app.wait_return_true(obj.is_connected, timeout=30)
```

Обратите внимание, что это статический метод, что означает, что он принадлежит классу, а не экземпляру класса. Это значит, что вам не нужен экземпляр класса, чтобы вызвать этот метод. Вы можете просто вызвать его на самом классе, как показано в примере выше.


## Метод: `draw_by_coordinates()`

Этот метод рисует прямоугольник на указанном изображении или скриншоте экрана. Прямоугольник задается координатами или верхней левой и нижней правой точками. Результирующее изображение сохраняется по указанному пути.

### Параметры

- `image`: Изображение, на котором будет рисоваться прямоугольник. Может быть представлено в форматах bytes, str (путь к файлу) или PIL Image. Если не указано, используется скриншот экрана. По умолчанию равно None.
- `coordinates`: Координаты прямоугольника в виде кортежа (x1, y1, x2, y2). По умолчанию равно None.
- `top_left`: Координаты верхней левой точки прямоугольника в виде кортежа (x, y). По умолчанию равно None.
- `bottom_right`: Координаты нижней правой точки прямоугольника в виде кортежа (x, y). По умолчанию равно None.
- `path`: Путь для сохранения результирующего изображения. По умолчанию равно None.

### Возвращаемое значение

- `AppiumExtended`: Возвращает экземпляр класса `AppiumExtended` для дальнейших вызовов методов.

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

```python
appium_extended = AppiumExtended(driver)
image = driver.get_screenshot_as_base64().encode('utf-8')
appium_extended.draw_by_coordinates(image=image, coordinates=(123, 123, 123, 123), path='pictures')
```

В этом примере мы делаем скриншот экрана, рисуем на нем прямоугольник с указанными координатами и сохраняем полученное изображение в директории "pictures".


## Метод: `input_by_virtual_keyboard()`

Этот метод пока не реализован. Ожидается, что он будет использоваться для поиска и возврата родительского элемента, который содержит определённый дочерний элемент.

### Параметры

На данный момент в методе нет параметров.

### Возвращаемое значение

На данный момент метод возвращает ошибку `NotImplementedError` при вызове, так как он ещё не реализован.

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

```python
# Этот метод еще не реализован, поэтому его нельзя вызвать.
```

### Дополнительная информация

В текущей реализации метод возвращает исключение `NotImplementedError` с сообщением "This method is not implemented yet". Это означает, что метод ещё не реализован. Предполагается, что в будущем он будет реализован для ввода данных с помощью виртуальной клавиатуры.


# class WebElementExtended

`WebElementExtended` - это класс, расширяющий базовый класс `WebElement` дополнительными возможностями. Он объединяет несколько классов, предоставляя различные методы взаимодействия с веб-элементами.
Инициализируется в AppiumExtended.

## Метод: `get_element()`

Этот метод извлекает элемент из другого элемента. Должен принимать как минимум либо локатор, либо значения параметров by и value.

### Параметры

- `locator`: Определяет локатор элемента. Может быть кортежем, WebElement, словарем или строкой.
    - Кортеж: Локатор в форме ('стратегия', 'значение'), например, ('xpath', '//*'), ('id', 'elem_id') и т.д.
    - WebElement / WebElementExtended: Объект веб-элемента.
    - Словарь: Содержит пары атрибут: значение элемента, например, {'text':'foo', 'enabled':'true'}.
    - Строка: Путь до файла с изображением элемента.
    - По умолчанию: None.
- `by`: Тип локатора для поиска элемента. Используется в связке с параметром `value`. Может быть MobileBy, AppiumBy, By или строкой. По умолчанию: None.
- `value`: Значение локатора или словарь аргументов, если используется AppiumBy.XPATH. Может быть строкой, словарем или None. По умолчанию: None.
- `timeout_elem`: Максимальное время ожидания элемента в секундах. По умолчанию: 10.
- `timeout_method`: Максимальное время ожидания выполнения метода поиска элемента в секундах. По умолчанию: 600.
- `elements_range`: Ограничивает поиск элемента в указанном диапазоне (для поиска по изображению). Может быть кортежем, списком, словарем или None. По умолчанию: None.
- `contains`: Если True, проверяет, содержит ли элемент указанные атрибуты. Если False, проверяет, точно ли соответствует элемент указанным атрибутам. По умолчанию: True.

### Возвращаемое значение

- `WebElementExtended` или `None`: Возвращает WebElementExtended, если элемент был найден в течение указанного времени ожидания, в противном случае возвращает None.

### Примечания

- Этот метод использует внутренний метод для реализации основной логики поиска элементов.

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

```python
# Ожидание появления элемента по локатору
inner_element = element.get_element(locator=("id", "foo"), timeout_elem=30)

# Ожидание появления элемента по WebElement
inner_element = element.get_element(locator=element, timeout_elem=20)

# Ожидание появления нескольких элементов и изображений
inner_element = element.get_element(locator={'text': 'foo'}, elements_range={'class':'android.widget.FrameLayout', 'package':'ru.app.debug'}, timeout_elem=40)
```

## Метод: `get_attributes()`

Этот метод получает атрибуты элемента. Если хотя бы один из желаемых атрибутов не найден, метод возвращает все атрибуты элемента.

### Параметры

- `desired_attributes`: Список названий атрибутов, которые нужно получить. Если параметр не указан, метод вернет все атрибуты элемента. По умолчанию: None.

### Возвращаемое значение

- `dict`: Словарь, содержащий атрибуты элемента и их значения. Если указан `desired_attributes` и соответствующие атрибуты найдены у элемента, возвращает словарь только с запрашиваемыми атрибутами. Если `desired_attributes` не указан или желаемый атрибут не найден, возвращает словарь со всеми атрибутами.

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

```python
# Получение атрибутов 'text', 'bounds', 'class' у элемента
attributes = element.get_attributes(['text', 'bounds', 'class'])

# Получение всех атрибутов элемента
all_attributes = element.get_attributes()
```

## Метод: `click()`

Этот метод осуществляет нажатие на заданный элемент.

### Параметры

- `duration`: Время нажатия в секундах. Если параметр равен нулю, осуществляется обычное нажатие, иначе происходит нажатие с удержанием на указанное количество секунд. По умолчанию равно 0.
- `decorator_args`: Параметры для декоратора, включая время ожидания нового окна (`timeout_window`) и количество попыток нажатия (`tries`). Используется только при `wait = True`. По умолчанию None.
- `wait`: Флаг, указывающий, следует ли ожидать изменения окна после нажатия. Если `True`, будет использован метод `_click_to_element_and_wait()`, иначе `_click_to_element()`. По умолчанию False.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

### Примечания

- В случае, если указан `wait = True` и не предоставлены `decorator_args`, используются стандартные параметры декоратора: `timeout_window` равно 5 и `tries` равно 5.

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

```python
# Нажатие на элемент с ожиданием изменения окна и кастомными параметрами декоратора
decorator_args = {"timeout_window": 5, "tries": 5}
element.click(duration=0, wait=True, decorator_args=decorator_args)
```

## Метод: `double_click()`

Этот метод выполняет двойное нажатие (double click) на заданный элемент.

### Параметры

- `decorator_args`: Параметры для декоратора, включая время ожидания нового окна (`timeout_window`) и количество попыток нажатия (`tries`). Используется только при `wait = True`. По умолчанию `timeout_window` равно 5 и `tries` равно 5.
- `wait`: Флаг, указывающий, следует ли ожидать изменения окна после нажатия. Если `True`, будет использован метод `_double_click_to_element_and_wait()`, иначе `_double_click_to_element()`. По умолчанию False.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

### Примечания

- В случае, если указан `wait = True` и не предоставлены `decorator_args`, используются стандартные параметры декоратора: `timeout_window` равно 5 и `tries` равно 5.

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

```python
# Двойное нажатие на элемент без ожидания изменения окна
element.double_click(wait=False)

# Двойное нажатие на элемент с ожиданием изменения окна и кастомными параметрами декоратора
decorator_args = {"timeout_window": 7, "tries": 3}
element.double_click(wait=True, decorator_args=decorator_args)
```

## Метод: `click_and_move()`

Этот метод нажимает левую кнопку мыши, перемещает курсор к указанной цели и отпускает кнопку.

### Параметры

- `locator`: Локатор для поиска целевого элемента на веб-странице. Он может быть кортежем, `WebElement`, `WebElementExtended`, словарем или строкой. Не обязательный параметр.
- `x`: Абсолютная координата по оси X для перемещения курсора. Не обязательный параметр.
- `y`: Абсолютная координата по оси Y для перемещения курсора. Не обязательный параметр.
- `direction`: Направление в градусах для перемещения курсора, где 0/360 - вверх, 90 - вправо, 180 - вниз, 270 - влево. Не обязательный параметр.
- `distance`: Расстояние в пикселях для перемещения курсора. Не обязательный параметр.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Кликнуть и переместить к элементу, найденному по локатору
element.click_and_move(locator="//button[@id='submit']")

# Кликнуть и переместить на указанные координаты
element.click_and_move(x=100, y=200)

# Кликнуть и переместить в указанном направлении на указанное расстояние
element.click_and_move(direction=90, distance=100)
```

### Примечание

Целью перемещения может быть WebElement, абсолютные координаты (x, y) или направление и расстояние. Если предоставлены направление и расстояние, функция вычисляет целевую позицию на основе вектора, определенного этими значениями. Если предоставлены абсолютные координаты (x, y), курсор перемещается в указанные позиции. Если предоставлен локатор, функция перемещается к найденному элементу на веб-странице.

## Метод: `adb_tap()`

Deprecated!
Метод устарел. Будет удален в следующих версиях.
Вместо него будет реализован метод выполняющий нажатие через driver.execute_script()

Этот метод выполняет нажатие на элемент, используя ADB (Android Debug Bridge).


### Параметры

- `decorator_args`: Дополнительные аргументы для использования в декораторе. Это словарь, который может содержать следующие ключи:
  - `timeout_window`: Время ожидания нового окна (умножается на количество попыток).
  - `tries`: Количество попыток нажатия (по умолчанию 3).
  Этот параметр не обязателен.
- `wait`: Флаг, указывающий, нужно ли ожидать изменения окна. Необязательный параметр, по умолчанию False.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Нажать на элемент с помощью ADB и не ожидать изменения окна
element.adb_tap()

# Нажать на элемент с помощью ADB и ожидать изменения окна
element.adb_tap(wait=True)

# Нажать на элемент с помощью ADB, ожидать изменения окна и установить время ожидания и количество попыток
element.adb_tap(decorator_args={"timeout_window": 5, "tries": 5}, wait=True)
```

### Примечание

ADB (Android Debug Bridge) - это инструмент командной строки, который используется для взаимодействия с устройством. В данном контексте он используется для симуляции взаимодействия пользователя с интерфейсом Android.

## Метод: `adb_multi_tap()`

Этот метод выполняет многократные нажатия (обычно два или три) на элемент, используя ADB (Android Debug Bridge). 

### Аргументы

- `decorator_args (dict, optional)`: Дополнительные аргументы для декоратора. Если `None`, то будут преобразованы в `decorator_args = {"timeout_window": 5, "tries": 5}`, где `timeout_window` - время ожидания изменения окна в секундах, а `tries` - количество попыток выполнения метода для изменения окна.
- `wait (bool, optional)`: Флаг, указывающий, нужно ли ожидать изменение окна после нажатия. По умолчанию `False`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Выполнить многократные нажатия на элемент с помощью ADB
element.adb_multi_tap(decorator_args={"timeout_window": 10, "tries": 3}, wait=True)
```

### Примечание

ADB (Android Debug Bridge) - это инструмент командной строки, который используется для взаимодействия с устройством. В данном контексте он используется для симуляции взаимодействия пользователя с интерфейсом Android. Многократные нажатия могут быть полезны для выделения текста или активации специальных функций в приложении.

## Метод: `adb_swipe()`

Этот метод выполняет свайп (прокрутку) на элементе или по определенному направлению, используя ADB (Android Debug Bridge). 

### Аргументы

- `locator (Union[Tuple, WebElement, 'WebElementExtended', Dict[str, str], str], optional)`: Локатор элемента, к которому необходимо прокрутить. Это может быть `Tuple`, `WebElement`, `WebElementExtended`, словарь с `str` или просто `str`. Если `None`, прокрутка производится от центра корневого элемента. 
- `x (int, optional)`: Координата X целевой позиции прокрутки. 
- `y (int, optional)`: Координата Y целевой позиции прокрутки. 
- `direction (int, optional)`: Направление прокрутки в градусах (от 0 до 360). 
- `distance (int, optional)`: Расстояние прокрутки в пикселях. 
- `duration (int, optional)`: Длительность прокрутки в секундах. По умолчанию равна 1. 
- `contains (bool, optional)`: Флаг, указывающий, должен ли локатор содержать текст элемента. По умолчанию `True`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Прокрутить до элемента с текстом "Submit"
element.adb_swipe(locator="Submit", duration=2)

# Прокрутить вниз на 500 пикселей за 1 секунду
element.adb_swipe(direction=180, distance=500, duration=1)
```

### Примечание

ADB (Android Debug Bridge) - это инструмент командной строки, который используется для взаимодействия с устройством. В данном контексте он используется для симуляции взаимодействия пользователя с интерфейсом Android. Прокрутка может быть полезной для навигации по странице или меню приложения.

## Метод: `tap()`

Этот метод выполняет нажатие (tap) на центре данного веб-элемента.

### Аргументы

- `duration (int, optional)`: Длительность нажатия в миллисекундах. По умолчанию равна 0 (моментальное нажатие). 
- `decorator_args (dict, optional)`: Дополнительные аргументы для использования в декораторе. По умолчанию равно `None`. Если необходимо ожидание результата после нажатия, в словаре можно указать "timeout_window" - время ожидания изменения окна, и "tries" - количество попыток для изменения окна.
- `wait (bool, optional)`: Флаг, указывающий, следует ли ожидать результат после нажатия. По умолчанию равно `False`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Моментальное нажатие на элемент
element.tap()

# Нажатие на элемент на протяжении 500 миллисекунд
element.tap(duration=500)

# Нажатие на элемент с ожиданием изменения окна в течение 5 секунд
element.tap(duration=500, decorator_args={"timeout_window": 5, "tries": 5}, wait=True)
```

### Примечание

Методы `_tap`, `_tap_to_element_and_wait`, `_tap_to_element` и `__tap` используются внутри этого метода для выполнения нажатия и обработки различных сценариев, связанных с ожиданием результатов и обработкой исключений.

## Метод: `double_tap()`

Этот метод выполняет двойное нажатие (double tap) на центре данного веб-элемента.

### Аргументы

- `decorator_args (dict, optional)`: Дополнительные аргументы для использования в декораторе. По умолчанию равно `None`. Если необходимо ожидание результата после нажатия, в словаре можно указать "timeout_window" - время ожидания изменения окна, и "tries" - количество попыток для изменения окна.
- `wait (bool, optional)`: Флаг, указывающий, следует ли ожидать результат после нажатия. По умолчанию равно `False`.
- `pause (float, optional)`: Пауза между двумя нажатиями в секундах. По умолчанию равно 0.2.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Двойное нажатие на элемент с паузой в 0.3 секунды между нажатиями
element.double_tap(pause=0.3)

# Двойное нажатие на элемент с ожиданием изменения окна в течение 5 секунд
element.double_tap(decorator_args={"timeout_window": 5, "tries": 5}, wait=True, pause=0.3)
```

### Примечание

Методы `_double_tap`, `_double_tap_to_element_and_wait`, `_double_tap_to_element` и `__double_tap` используются внутри этого метода для выполнения двойного нажатия и обработки различных сценариев, связанных с ожиданием результатов и обработкой исключений.

## Метод: `tap_and_move()`

Этот метод выполняет операцию "нажать и переместить" на веб-элементе или на указанных координатах.

### Аргументы

- `locator (Union[Tuple, WebElement, 'WebElementExtended', Dict[str, str], str], optional)`: Локатор элемента, на который будет выполнено нажатие и перемещение. По умолчанию равно `None`.
- `x (int, optional)`: Координата X для нажатия и перемещения. По умолчанию равно `None`.
- `y (int, optional)`: Координата Y для нажатия и перемещения. По умолчанию равно `None`.
- `direction (int, optional)`: Направление перемещения в градусах (0 - вверх, 90 - вправо, 180 - вниз, 270 - влево). По умолчанию равно `None`.
- `distance (int, optional)`: Расстояние перемещения в пикселях. По умолчанию равно `None`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий элемент, на котором было произведено действие.
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Нажатие и перемещение на элемент с локатором
element.tap_and_move(locator=("xpath", "//div[@class='target']"))

# Нажатие и перемещение к координатам (50, 100)
element.tap_and_move(x=50, y=100)

# Нажатие и перемещение на расстояние 200 пикселей вниз
element.tap_and_move(direction=180, distance=200)
```

### Примечание

Метод `_tap_and_move` используется внутри этого метода для выполнения нажатия и перемещения, обработки различных сценариев в зависимости от предоставленных аргументов и обработки исключений.

## Метод: `get_elements()`

Этот метод обеспечивает поиск элементов в элементе.

### Аргументы

- `locator (Union[Tuple, List[WebElement], Dict[str, str], str], optional)`: Локатор элементов. Может быть кортежем, списком Веб-Элементов, словарем с атрибутом и значением, или строкой как путь до файла с изображением элемента. По умолчанию равно `None`.
- `by (Union[MobileBy, AppiumBy, By, str], optional)`: Тип локатора для поиска элемента (всегда в связке с `value`). По умолчанию равно `None`.
- `value (Union[str, Dict, None], optional)`: Значение локатора или словарь аргументов, если используется `AppiumBy.XPATH`. По умолчанию равно `None`.
- `timeout_elements (int, optional)`: Время ожидания для поиска каждого отдельного элемента. По умолчанию равно `10`.
- `timeout_method (int, optional)`: Общее время ожидания метода. По умолчанию равно `600`.
- `elements_range (Union[Tuple, List[WebElement], Dict[str, str], None], optional)`: Диапазон для поиска элементов. По умолчанию равно `None`.
- `contains (bool, optional)`: Если `True`, то поиск будет осуществляться по фрагменту текста или атрибута, а не их полному соответствию. По умолчанию равно `True`.

### Возвращаемое значение

- Возвращает список экземпляров `WebElementExtended`, представляющих найденные элементы. В случае, если элементы не найдены, возвращает пустой список.

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

```python
# Поиск элементов по ID
elements = app.get_elements(locator=("id", "foo"))

# Поиск элементов по тексту
elements = app.get_elements(locator={'text': 'foo'})

# Поиск элементов по изображению
elements = app.get_elements(locator='/path/to/file/pay_agent.png')

# Поиск элементов с использованием типа локатора и значения
elements = app.get_elements(by="id", value="ru.sigma.app.debug:id/backButton")
```

## Метод: `scroll_down()`

Этот метод выполняет скроллинг элемента вниз. Тап и ведение от нижнего внутреннего элемента до верхнего внутреннего элемента.

### Аргументы

- `locator (Union[Tuple, WebElementExtended, Dict[str, str], str], optional)`: Локатор или элемент для прокрутки. Может быть кортежем, экземпляром `WebElementExtended`, словарем с атрибутом и значением, или строкой. Если не указан, то будет вычислен автоматически. По умолчанию равно `None`.
- `duration (int, optional)`: Продолжительность прокрутки в миллисекундах. Если не указана, прокрутка будет произведена без задержки. По умолчанию равно `None`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, если скроллинг выполнен успешно. 
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Скроллинг элемента с заданным локатором
app.scroll_down(locator=("id", "foo"), duration=1000)

# Скроллинг конкретного элемента
element = app.get_element(locator=("id", "foo"))
app.scroll_down(locator=element, duration=1000)

# Скроллинг элемента с заданным атрибутом и значением
app.scroll_down(locator={'class': 'foo'}, duration=1000)
```

## Метод: `scroll_up()`

Этот метод выполняет скроллинг элемента вверх.  Тап и ведение от верхнего внутреннего элемента до нижнего внутреннего элемента.

### Аргументы

- `locator (Union[Tuple, WebElementExtended, Dict[str, str], str], optional)`: Локатор или элемент для прокрутки. Может быть кортежем, экземпляром `WebElementExtended`, словарем с атрибутом и значением, или строкой. Если не указан, то будет вычислен автоматически. По умолчанию равно `None`.
- `duration (int, optional)`: Продолжительность прокрутки в миллисекундах. Если не указана, прокрутка будет произведена без задержки. По умолчанию равно `None`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, если скроллинг выполнен успешно. 
- В случае, если не удалось выполнить действие, генерируется AssertionError.

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

```python
# Скроллинг элемента с заданным локатором вверх
app.scroll_up(locator=("id", "foo"), duration=1000)

# Скроллинг конкретного элемента вверх
element = app.get_element(locator=("id", "foo"))
app.scroll_up(locator=element, duration=1000)

# Скроллинг элемента с заданным атрибутом и значением вверх
app.scroll_up(locator={'class': 'foo'}, duration=1000)
```

## Метод: `scroll_to_bottom()`

Этот метод выполняет скроллинг элемента до самого нижнего положения.

### Аргументы

- `locator (Union[Tuple, WebElementExtended, Dict[str, str], str], optional)`: Локатор или элемент для прокрутки. Может быть кортежем, экземпляром `WebElementExtended`, словарем с атрибутом и значением, или строкой. По умолчанию равно `None`.
- `timeout_method (int, optional)`: Время ожидания выполнения метода в секундах. Если время ожидания истекает, а скроллинг не достигает нижнего положения, метод возвращает ошибку. По умолчанию равно `120`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, если скроллинг выполнен успешно. В случае ошибки выбрасывает исключение AsserionError.

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

```python
# Скроллинг элемента с заданным локатором до нижнего положения
app.scroll_to_bottom(locator=("id", "foo"), timeout_method=120)

# Скроллинг конкретного элемента до нижнего положения
element = app.get_element(locator=("id", "foo"))
app.scroll_to_bottom(locator=element, timeout_method=120)

# Скроллинг элемента с заданным атрибутом и значением до нижнего положения
app.scroll_to_bottom(locator={'class': 'foo'}, timeout_method=120)
```

## Метод: `scroll_to_top()`

Этот метод выполняет скроллинг элемента до самого верхнего положения.

### Аргументы

- `locator (Union[Tuple, WebElementExtended, Dict[str, str], str], optional)`: Локатор или элемент для прокрутки. Может быть кортежем, экземпляром `WebElementExtended`, словарем с атрибутом и значением, или строкой. По умолчанию равно `None`.
- `timeout_method (int, optional)`: Время ожидания выполнения метода в секундах. Если время ожидания истекает, а скроллинг не достигает верхнего положения, метод возвращает ошибку. По умолчанию равно `120`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, если скроллинг выполнен успешно. В случае ошибки выбрасывает исключение AssertionError.

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

```python
# Скроллинг элемента с заданным локатором до верхнего положения
app.scroll_to_top(locator=("id", "foo"), timeout_method=120)

# Скроллинг конкретного элемента до верхнего положения
element = app.get_element(locator=("id", "foo"))
app.scroll_to_top(locator=element, timeout_method=120)

# Скроллинг элемента с заданным атрибутом и значением до верхнего положения
app.scroll_to_top(locator={'class': 'foo'}, timeout_method=120)
```


## Метод: `scroll_until_find()`

Этот метод выполняет скроллинг элемента вниз и вверх, пока не найдет элемент, указанный в аргументе `locator`, или пока не истечет таймаут.

### Аргументы

- `locator (Union[Tuple, WebElementExtended, Dict[str, str], str])`: Локатор или элемент, который следует найти. Может быть кортежем, экземпляром `WebElementExtended`, словарем с атрибутом и значением, или строкой.
- `roll_locator (Union[Tuple, WebElementExtended, Dict[str, str], str], optional)`: Локатор или элемент, который следует прокручивать. Если не указан, прокручивается первый дочерний элемент. Может быть кортежем, экземпляром `WebElementExtended`, словарем с атрибутом и значением, или строкой. По умолчанию равно `None`.
- `timeout_method (int, optional)`: Время ожидания выполнения метода в секундах. Если время ожидания истекает, а элемент не найден, метод возвращает `None`. По умолчанию равно `120`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, если элемент найден. Возвращает `None`, если элемент не найден в течение заданного времени.

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

```python
# Поиск элемента с заданным локатором, прокручивая элемент с другим локатором
app.scroll_until_find(locator=("id", "target"), roll_locator=("id", "foo"), timeout_method=120)

# Поиск конкретного элемента, прокручивая другой конкретный элемент
element_to_find = app.get_element(locator=("id", "target"))
element_to_scroll = app.get_element(locator=("id", "foo"))
app.scroll_until_find(locator=element_to_find, roll_locator=element_to_scroll, timeout_method=120)

# Поиск элемента с заданным атрибутом и значением, прокручивая элемент с другим атрибутом и значением
app.scroll_until_find(locator={'class': 'target'}, roll_locator={'class': 'foo'}, timeout_method=120)
```

## Метод: `get_parent()

Этот метод возвращает первый родительский элемент текущего элемента в дереве DOM.

### Аргументы

Метод не принимает никаких аргументов.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, который представляет родительский элемент.

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

```python
# Получение родительского элемента
parent_element = app.get_parent()
```

## Метод: `get_parents()

Этот метод возвращает все родительские элементы текущего элемента в дереве DOM, начиная от ближайшего и до корневого элемента.

### Аргументы

Метод не принимает никаких аргументов.

### Возвращаемое значение

- Возвращает список экземпляров `WebElementExtended`, каждый из которых представляет родительский элемент на различных уровнях вверх по дереву DOM.

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

```python
# Получение всех родительских элементов
parent_elements = app.get_parents()
```

## Метод: `get_sibling()

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

### Аргументы

- `attributes` (`dict`): Словарь, содержащий атрибуты и их значения, которые должны быть найдены у искомого соседнего элемента. Например, `{'class': 'myClass', 'name': 'myName'}` ищет элемент, у которого атрибут `class` равен `myClass` и `name` равен `myName`.

- `contains` (`bool`, необязательный): Флаг, указывающий, использовать ли функцию `contains` XPath для атрибутов. Если `True`, метод будет искать элементы, значение атрибута которых содержит указанное значение (а не полное совпадение). По умолчанию равно `True`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий найденный соседний элемент. Если такой элемент не найден, возвращается `None`.

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

```python
# Получение соседнего элемента с классом 'myClass'
sibling_element = app.get_sibling({'class': 'myClass'})

# Получение соседнего элемента, имя которого содержит 'myName'
sibling_element = app.get_sibling({'name': 'myName'}, contains=True)
```

## Метод: `get_siblings()

Этот метод возвращает все соседние (родственные) элементы текущего элемента. Возвращаются только непосредственные соседи (братья или сестры) в пределах того же родительского элемента.

### Аргументы

Метод не требует аргументов.

### Возвращаемое значение

- Возвращает список экземпляров `WebElementExtended`, каждый из которых представляет одного из родственных элементов текущего элемента. Если таких элементов не найдено, возвращается пустой список.

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

```python
# Получение всех соседних элементов текущего элемента
sibling_elements = app.get_siblings()
```

## Метод: `get_cousin()

Этот метод предназначен для поиска "кузена" текущего элемента в дереве DOM. Кузен в данном контексте определяется как элемент, находящийся на одинаковом уровне вложенности от общего предка.

### Аргументы

- `ancestor` - Предок, относительно которого определяется "кузенство". Может быть представлен в виде кортежа (списка атрибутов и их значений), экземпляра WebElement или WebElementExtended, словаря (атрибутов и их значений) или строки (XPath выражения).

- `cousin` - Словарь атрибутов, определяющий искомого кузена. Ключи словаря - это названия атрибутов, значения - соответствующие значения этих атрибутов.

- `contains` - Булевый флаг, который определяет, следует ли использовать функцию `contains` при формировании XPath выражения для поиска кузена. Если `True`, то будет искаться частичное совпадение атрибутов. Если `False`, то будет искаться полное совпадение. По умолчанию `True`.

### Возвращаемое значение

- Возвращает экземпляр `WebElementExtended`, представляющий кузена текущего элемента. Если кузен не найден, возвращается `None`.

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

```python
# Ищем кузена текущего элемента, имеющего класс 'desired-class' и находящегося на одинаковой глубине вложенности от общего предка с классом 'parent-class'
cousin_element = app.get_cousin(ancestor={'class': 'parent-class'}, cousin={'class': 'desired-class'})
```

## Метод: `get_cousins()

Этот метод предназначен для поиска "кузенов" текущего элемента в дереве DOM. Кузен в данном контексте определяется как элемент, находящийся на одинаковом уровне вложенности от общего предка.

### Аргументы

- `ancestor` - Предок, относительно которого определяется "кузенство". Может быть представлен в виде кортежа (списка атрибутов и их значений), экземпляра WebElement или WebElementExtended, словаря (атрибутов и их значений) или строки (XPath выражения).

- `cousin` - Словарь атрибутов, определяющий искомого кузена. Ключи словаря - это названия атрибутов, значения - соответствующие значения этих атрибутов.

- `contains` - Булевый флаг, который определяет, следует ли использовать функцию `contains` при формировании XPath выражения для поиска кузенов. Если `True`, то будет искаться частичное совпадение атрибутов. Если `False`, то будет искаться полное совпадение. По умолчанию `True`.

### Возвращаемое значение

- Возвращает список экземпляров `WebElementExtended`, представляющих кузенов текущего элемента. Если кузены не найдены, возвращается пустой список.

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

```python
# Ищем кузенов текущего элемента, имеющих класс 'desired-class' и находящихся на одинаковой глубине вложенности от общего предка с классом 'parent-class'
cousin_elements = app.get_cousins(ancestor={'class': 'parent-class'}, cousin={'class': 'desired-class'})
```

## Метод: `is_contains()

Этот метод проверяет, содержит ли текущий элемент другой элемент, определенный локатором `locator`. 

### Аргументы

- `locator` - Локатор дочернего элемента. Может быть представлен в виде кортежа (списка атрибутов и их значений), экземпляра WebElement или WebElementExtended, словаря (атрибутов и их значений) или строки (XPath выражения).

- `contains` - Булевый флаг, который определяет, следует ли использовать функцию `contains` при формировании XPath выражения для поиска элемента. Если `True`, то будет искаться частичное совпадение атрибутов. Если `False`, то будет искаться полное совпадение. По умолчанию `True`.

### Возвращаемое значение

- Возвращает `True`, если текущий элемент содержит искомый дочерний элемент, и `False` в противном случае.

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

```python
# Проверяем, содержит ли текущий элемент дочерний элемент с классом 'child-class'
if app.is_contains(locator={'class': 'child-class'}):
    print("Child element is present")
else:
    print("Child element is not present")
```

## Метод: `zoom()`

Вызывает `NotImplementedError` так как метод не реализован.
Этот метод в будущем реализует функцию увеличения (zoom) на элементе страницы.

### Аргументы

- `hold` - Булевый параметр, который определяет, следует ли удерживать увеличение после его выполнения. Если `True`, увеличение будет удерживаться. Если `False`, увеличение не будет удерживаться после выполнения действия.

### Возвращаемое значение

- Вызывает `NotImplementedError` так как метод не реализован.

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

```python
Метод не реализован
```

## Метод: `unzoom()`

Вызывает `NotImplementedError` так как метод не реализован.
Этот метод в будущем реализует функцию увеличения (zoom) на элементе страницы.

### Аргументы

- `hold` - Булевый параметр, который определяет, следует ли удерживать увеличение после его выполнения. Если `True`, увеличение будет удерживаться. Если `False`, увеличение не будет удерживаться после выполнения действия.

### Возвращаемое значение

- Вызывает `NotImplementedError` так как метод не реализован.

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

```python
Метод не реализован
```

## Метод: `get_center() 

Этот метод вычисляет координаты центра текущего элемента страницы.

### Возвращаемое значение

- Возвращает кортеж в формате `(x, y)`, где `x` и `y` - это координаты центра элемента. Если во время выполнения произошла ошибка, метод вернёт `None`.

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

```python
# Получаем координаты центра элемента
center_coordinates = element.get_center()

# Печатаем координаты центра
if center_coordinates is not None:
    print("The center of the element is located at: ", center_coordinates)
else:
    print("An error occurred while getting the center of the element.")
```

## Метод: `get_coordinates()

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

### Возвращаемое значение

- Возвращает кортеж в формате `(left, top, right, bottom)`, где:
  - `left` - расстояние от левого края окна браузера до левого края элемента,
  - `top` - расстояние от верхнего края окна браузера до верхнего края элемента,
  - `right` - расстояние от левого края окна браузера до правого края элемента,
  - `bottom` - расстояние от верхнего края окна браузера до нижнего края элемента.
  
  Если во время выполнения произошла ошибка, метод вернёт `None`.

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

```python
# Получаем координаты элемента
element_coordinates = element.get_coordinates()

# Печатаем координаты элемента
if element_coordinates is not None:
    print("The coordinates of the element are: ", element_coordinates)
else:
    print("An error occurred while getting the coordinates of the element.")
```


# class AppiumServer

## Описание класса

Класс `AppiumServer` предназначен для управления сервером Appium. Он позволяет запускать и останавливать сервер Appium с заданными параметрами, проверять его доступность и логировать процесс.

## Атрибуты

- `logger`: Объект для записи логов, основанный на настройках, указанных в `config.APPIUM_LOG_NAME`.
    
- `port`: Порт, на котором будет запущен сервер Appium. По умолчанию равен `4723`.
    
- `log_level`: Уровень детализации логирования. По умолчанию равен `'error'`.
    

## Конструктор

### `__init__()`

Инициализирует новый экземпляр класса `AppiumServer`.

**Параметры:**

- `port: int` - Порт, на котором будет запущен сервер Appium. По умолчанию равен `4723`.
    
- `log_level: str` - Уровень детализации логирования. По умолчанию равен `'error'`.

## Метод: `start()`

Этот метод запускает сервер Appium.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

- `bool`: Возвращает `True`, если сервер Appium был успешно запущен. В противном случае возвращает `False`.

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

```python
# Запустить сервер Appium
is_started = app.start()
```

### Дополнительная информация

Метод запускает команду `appium server` с рядом параметров в отдельном подпроцессе, используя `subprocess.Popen`. Если процесс запуска успешен, метод возвращает `True`. В случае исключения типа `subprocess.CalledProcessError` или `OSError`, метод записывает ошибку в лог и возвращает `False`.

## Метод: `is_alive()`

Этот метод проверяет статус сервера Appium.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

- `bool`: Возвращает `True`, если сервер Appium доступен и готов к использованию. В противном случае возвращает `False`.

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

```python
# Проверить статус сервера Appium
is_ready = app.is_alive()
```

### Дополнительная информация

Метод отправляет GET-запрос на "http://127.0.0.1:4723/wd/hub/sessions" для проверки статуса сервера Appium. Если сервер отвечает с кодом статуса 200, метод возвращает `True`. Если сервер отвечает с другим кодом статуса, метод записывает предупреждение в лог и возвращает `False`. В случае исключения `requests.exceptions.RequestException`, метод записывает ошибку в лог и возвращает `False`.

## Метод: `stop()`

Этот метод останавливает сервер Appium.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

- `bool`: Возвращает `True`, если сервер Appium был успешно остановлен. В противном случае возвращает `False`.

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

```python
# Остановить сервер Appium
is_stopped = app.stop()
```

### Дополнительная информация

Метод запускает команду 'taskkill /F /IM node.exe' в подпроцессе, используя `subprocess.check_output`. Если процесс остановки успешен, метод возвращает `True`. В случае исключения типа `subprocess.CalledProcessError`, метод возвращает `False`.

## Метод: `wait_until_alive()`

Этот метод ожидает, пока сервер Appium не станет доступным.

### Параметры

- `timeout` (`int`, необязательный): Максимальное время ожидания в секундах, в течение которого метод будет проверять статус сервера. Значение по умолчанию: `60`.
- `poll` (`int`, необязательный): Интервал времени в секундах между проверками статуса сервера. Значение по умолчанию: `2`.

### Возвращаемое значение

- `bool`: Возвращает `True`, если сервер Appium стал доступным в течение заданного времени ожидания. В противном случае возвращает `False`.

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

```python
# Ожидать, пока сервер Appium не станет доступным в течение 60 секунд с интервалом проверки 2 секунды
is_ready = app.wait_until_alive(timeout=60, poll=2)
```

### Дополнительная информация

Метод использует вспомогательный метод `is_alive()` для проверки статуса сервера. Он будет продолжать проверку статуса сервера каждые `poll` секунд в течение `timeout` секунд или до тех пор, пока сервер не станет доступным. Если сервер становится доступным в течение времени ожидания, метод возвращает `True`. Если сервер так и не становится доступным после истечения времени ожидания, метод возвращает `False`.


## class `AppiumNavigator`

Этот класс предоставляет функционал навигации для приложения, управляемого через сервер Appium.

### Атрибуты

- `app` (`AppiumExtended`): Экземпляр класса `AppiumExtended`, который предоставляет API для взаимодействия с сервером Appium.
- `graph_manager` (`AppiumGraph`): Объект для управления графом приложения.
- `logger` (`logging.Logger`): Логгер для записи логов.
- `image` (`AppiumImage`): Объект для работы с изображениями в контексте Appium.

## Конструктор

### `__init__()`

Инициализирует новый экземпляр класса `AppiumNavigator`.

**Параметры:**

- `app` (`AppiumExtended`): Экземпляр класса `AppiumExtended`, который предоставляет API для взаимодействия с сервером Appium.

## Метод: `add_page()`

Этот метод добавляет вершину в граф навигации приложения.

### Параметры

- `page` (`str`): Название страницы (экрана или окна), которую нужно добавить в граф.
- `edges` (`List[str]`): Список страниц (экранов или окон), к которым можно перейти с текущей страницы. Страницы представлены их названиями.

### Возвращаемое значение

Метод не возвращает значения.

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

```python
# Добавить новую страницу в граф навигации приложения
navigator.add_page(page='HomePage', edges=['SettingsPage', 'ProfilePage'])
```

### Дополнительная информация

Метод использует `graph_manager` для добавления новой вершины в граф навигации приложения. Вершина представляет собой страницу (экран / окно) в приложении. Метод принимает название страницы и список других страниц, к которым можно перейти с текущей страницы.

## Метод: `navigate()`

Этот метод выполняет навигацию от текущей страницы к указанной целевой странице в приложении.

### Параметры

- `current_page` (`Type[YourPageClass]`): Класс текущей страницы, на которой находится пользователь.
- `destination_page` (`Type[YourPageClass]`): Класс целевой страницы, на которую пользователь хочет перейти.
- `timeout` (`int`, необязательный): Максимальное время ожидания перехода, по умолчанию 55 секунд.

### Возвращаемое значение

Метод не возвращает значения.

### Исключения

- `ValueError`: Если не удается найти путь от текущей страницы к целевой странице.

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

```python
# Перейти с главной страницы на страницу настроек
navigator.navigate(current_page=HomePage, destination_page=SettingsPage)
```

### Дополнительная информация

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

Вначале метод находит путь от текущей страницы к целевой с использованием `find_path()`. Если путь не найден, генерируется исключение `ValueError`. После того как путь найден, метод `perform_navigation()` выполняет навигацию, следуя найденному пути.

Примечание: `YourPageClass` в параметрах `current_page` и `destination_page` следует заменить на конкретные классы страниц в вашем приложении.

## Метод: `find_path()`

Этот метод использует поиск в ширину (BFS) для нахождения пути от стартовой страницы до целевой. 

### Параметры

- `start_page` (`Any`): Начальная страница поиска пути.
- `target_page` (`Any`): Целевая страница, которую нужно достичь.

### Возвращаемое значение

- `Optional[List[Any]]`: Список страниц, образующих путь от стартовой до целевой страницы. Если путь не найден, возвращает `None`.

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

```python
# Найти путь от главной страницы до страницы настроек
path = navigator.find_path(start_page=HomePage, target_page=SettingsPage)
```

### Дополнительная информация

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

Вначале метод создает множество для отслеживания посещенных страниц и очередь для выполнения поиска в ширину. Затем, пока очередь не пуста, метод извлекает текущую страницу и путь от стартовой страницы до нее. Получает переходы (соседние страницы) для текущей страницы и проверяет каждую соседнюю страницу. Если соседняя страница является целевой, возвращает полный путь. Если соседняя страница не была посещена, добавляет ее в очередь для дальнейшего поиска. Если путь не найден, возвращает `None`.

Примечание: `start_page` и `target_page` должны быть конкретными классами страниц в вашем приложении.

## Метод: `perform_navigation()`

Этот метод выполняет навигацию по заданному пути.

### Параметры

- `path` (`List[Any]`): Список страниц, образующих путь для навигации. Каждый элемент списка представляет страницу, а порядок элементов в списке определяет последовательность переходов от одной страницы к другой.
- `timeout` (`int`, необязательный): Максимальное время ожидания перехода, по умолчанию 55 секунд.

### Возвращаемое значение

- `None`

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

```python
# Предположим, мы уже нашли путь от главной страницы до страницы настроек
path = [HomePage, MenuPage, SettingsPage]
# Выполняем навигацию по этому пути
navigator.perform_navigation(path)
```

### Дополнительная информация

Метод принимает список страниц, который представляет собой путь для навигации. Он выполняет переходы между соседними страницами, чтобы достичь целевой страницы. Проходит по пути и выполняет переходы между соседними страницами. Если метод перехода между текущей и следующей страницами не найден, выводит сообщение об ошибке. После выполнения каждого перехода ожидает появления изображения целевой страницы.

Примечания: 
- Элементы списка `path` должны быть конкретными классами страниц в вашем приложении.
- Рекомендуется вместо него использовать метод navigate()

# Пример карты приложения
`#app_map.py`
```python
from pages.page_1 import page_1
from pages.page_2 import page_2
from pages.page_3 import page_3
class ExampleAppMap(AppiumExtended):

	def __init__(self, logger: logging.Logger):  
		super().__init__(logger=logger) 

		# Инициализация страниц (PageObjects)
	    self.page_1 = Page1(self)
	    self.page_2 = Page2(self)
	    self.page_3 = Page3(self)
	    
		self.driver = None  
		self.navigator: AppiumNavigator = None  
		self.image: AppiumImage = None  
		self.keyboard: KeyboardMain = None  
		self.current_path = os.path.dirname(os.path.abspath(inspect.getframeinfo(inspect.currentframe()).filename))  
		self.page_images_path = os.path.join(self.current_path, ConstMapPath.FOLDER_TRANSACTION_IMAGES)  
		self.pages_ndarray_images = None
			  
	def connect(self,  
		capabilities: dict,  
		server_ip: str = '0.0.0.0',  
		server_port: int = 4723,  
		server_log_level: str = 'error',  
		remote: bool = False,  
		keep_alive_server: bool = True) -> None:
		super().connect(capabilities=capabilities,  
						server_ip=server_ip,  
						server_port=server_port,  
						server_log_level=server_log_level,  
						remote=remote,  
						keep_alive_server=keep_alive_server)   
						
		# Инициализация необходимых объектов 
		self.navigator = AppiumNavigator(app=self, logger=self.logger)  
		self.keyboard = KeyboardMain(app=self, logger=self.logger)  
		self.image = self.helper

		# Установка граней   
		self.page_1.edges = {  
		    self.page_2: self.go_1_2,  
		}  
		self.page_2.edges = {  
		    self.page_1: self.go_2_1,
		    self.page_3: self.go_2_3  
		}
		self.page_3.edges = {
			self.page_2 = self.go_3_2
		}
		# Добавление страниц и граней в граф  
		self.navigator.add_page(page=self.page_1,  
		                        edges=self.page_1.edges)  
		self.navigator.add_page(page=self.page_2,  
		                        edges=self.page_2.edges)  
		self.navigator.add_page(page=self.page_3,  
		                        edges=self.page_3.edges)
		self.pages_ndarray_images = {  
		    self.page_1: self._get_ndarray_images(self.page_1.page_images),  
		    self.page_2: self._get_ndarray_images(self.page_2.page_images),  
		    self.page_3: self._get_ndarray_images(self.page_3.page_images),
			}

	def go_1_2(self):
		...

	def go_2_1(self):
		...

	def go_2_3(self):
		...

	def go_3_2(self):
		...
```

Структура файлов page:
-pages
  -page_1
    -action_images
      action_image_1.png
      action_image_2.png
    -images
      current_page_fragment_image_1.png
      current_page_fragment_image_2.png
    page_1.py

`#page_1.py`
```python
class Page1(PageBase):  
    edges: list  
  
    def __init__(self, app):  
        super().__init__(app)  
        self.app = app  
        self.current_path = os.path.dirname(os.path.abspath(inspect.getframeinfo(inspect.currentframe()).filename))  
        self.page_images_path = os.path.join(self.current_path, 'images')  
        self.page_action_images_path = os.path.join(self.current_path, 'action_images')  
        self.page_images = self._get_page_images(self.page_images_path)  
    
    def is_current_page(self) -> bool:  
        return self._is_current_page(self.page_images)

	def some_logic_on_page(self):
		...
```

`#page_base.py`

  ```python
class PageBase(object):
    def __init__(self, app):
        self.app: AppiumExtended = app
        self.page_images_path: str
        self.page_images: list[str]
        self.logger = logging.getLogger(config.LOGGER_NAME)

    def _is_current_page(self, page_images, max_attempts=3) -> bool:
        attempts = 0

        while attempts < max_attempts:
            if len(page_images) == 0:
                return False

            all_images_found = True  # Предполагаем, что все изображения найдены  

            for image in page_images:
                if not self.app.image._is_image_on_the_screen(image=image):
                    all_images_found = False
                    break  # Прерываем цикл, если хотя бы одно изображение не найдено  

            if all_images_found:
                return True

            attempts += 1
            time.sleep(1)  # Подождать 1 секунду перед следующей попыткой  

        return False

    @staticmethod
    def _get_page_images(page_images_path):
        page_images = []
        if os.path.exists(page_images_path):
            page_images = os.listdir(page_images_path)
        for index, image_name in enumerate(page_images):
            page_images[index] = os.path.join(page_images_path, image_name)
        return page_images
```


# class Aapt
Класс 


## Метод: `get_package_name()`

Статический метод, получает название пакета APK-файла с помощью команды aapt. Используется для извлечения информации о пакете из файла APK.

### Параметры

- `path_to_apk`: Путь до APK-файла, из которого требуется извлечь название пакета. Должен быть строкой, содержащей путь к файлу.

### Возвращаемое значение

Возвращает строку, содержащую название пакета, извлеченное из APK-файла. Если название пакета не может быть извлечено, возвращается `None`.

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

```python
package_name = get_package_name(path_to_apk="/path/to/apk/file.apk")
print(package_name)
```

### Дополнительная информация

Этот метод выполняет системную команду с использованием утилиты `aapt` (Android Asset Packaging Tool). В процессе работы создаются логи, которые сохраняются с использованием модуля `logging`.

### Исключения

Метод может генерировать исключения, если указанный файл APK не найден, не может быть прочитан или не содержит ожидаемой информации о пакете. Все такие исключения должны быть обработаны в вызывающем коде. Дополнительно, если утилита `aapt` не установлена или не доступна для вызова в системе, метод может не работать корректно.

## Метод: `get_launchable_activity()`

Статический метод, получает название запускаемой активности из APK-файла с помощью команды `aapt`. Используется для извлечения информации о запускаемой активности из файла APK.

### Параметры

- `path_to_apk`: Путь до APK-файла, из которого требуется извлечь название запускаемой активности. Должен быть строкой, содержащей путь к файлу.

### Возвращаемое значение

Возвращает строку, содержащую название запускаемой активности, извлеченное из APK-файла. Если название активности не может быть извлечено, возвращается `None`.

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

```python
launchable_activity = YourClassName.get_launchable_activity(path_to_apk="/path/to/apk/file.apk")
print(launchable_activity)
```

### Дополнительная информация

Этот метод выполняет системную команду с использованием утилиты `aapt` (Android Asset Packaging Tool). В процессе работы создаются логи, которые сохраняются с использованием модуля `logging`.

### Исключения

Метод может генерировать исключения, если указанный файл APK не найден, не может быть прочитан или не содержит ожидаемой информации о запускаемой активности. Все такие исключения должны быть обработаны в вызывающем коде. Дополнительно, если утилита `aapt` не установлена или не доступна для вызова в системе, метод может не работать корректно.

Пожалуйста, замените `YourClassName` на имя вашего класса.



# class Terminal
Класс отвечает за работу с устройством, командами adb подаваемыми через Appium server.

## Метод: `adb_shell()`

Этот метод класса `Terminal` позволяет выполнить команду adb shell через драйвер Appium. Используется для взаимодействия с устройством на уровне adb.

### Параметры

- `command`: Команда adb shell, которую требуется выполнить. Должна быть строкой, представляющей собой команду adb shell.

- `args`: Аргументы команды adb shell. Должны быть представлены в виде строки. По умолчанию, значение этого параметра — пустая строка.

### Возвращаемое значение

Возвращает значение, возвращаемое драйвером Appium при выполнении скрипта. Тип возвращаемого значения может зависеть от конкретной команды adb shell, но, как правило, это строка, содержащая вывод выполненной команды.

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

```python
output = Terminal(driver).adb_shell(command="pm list packages", args="-3")
print(output)
```

### Дополнительная информация

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

### Исключения

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

## Метод: `push()`

Этот метод класса `Terminal` позволяет копировать файл или директорию с локальной машины на подключенное устройство через Appium сервер.

### Параметры

- `source`: Путь к копируемому файлу или директории на локальной машине. Должен быть представлен в виде строки.

- `destination`: Путь назначения на устройстве, куда будет скопирован файл или директория. Должен быть представлен в виде строки.

### Возвращаемое значение

Возвращает `True`, если файл или директория были успешно скопированы. В противном случае возвращается `False`.

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

```python
terminal = Terminal(driver)
copy_result = terminal.push(source="/local/path/to/file.txt", destination="/device/path/to/file.txt")
if copy_result:
    print("File was successfully copied.")
else:
    print("File copying failed.")
```

### Дополнительная информация

Этот метод использует возможности драйвера Appium для копирования файлов или директорий на подключенное устройство. В случае возникновения ошибок в процессе копирования (например, если исходный файл не существует или назначение недоступно), метод возвращает `False` и записывает информацию об ошибке в лог.

### Исключения

Метод может генерировать исключение `IOError`, если возникают проблемы с чтением исходного файла или записью в целевую директорию на устройстве. Это исключение обрабатывается внутри метода, и информация о нем записывается в лог.

## Метод: `pull()`

Этот метод класса `Terminal` позволяет извлекать файл с подключенного устройства и сохранять его на локальной машине через Appium сервер.

### Параметры

- `source`: Путь к файлу на устройстве, который требуется извлечь. Должен быть представлен в виде строки.

- `destination`: Путь, по которому файл должен быть сохранен на локальной машине. Должен быть представлен в виде строки.

### Возвращаемое значение

Возвращает `True`, если файл успешно извлечен и сохранен на локальной машине. В противном случае возвращается `False`.

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

```python
terminal = Terminal(driver)
pull_result = terminal.pull(source="/device/path/to/file.txt", destination="/local/path/to/file.txt")
if pull_result:
    print("File was successfully pulled.")
else:
    print("File pulling failed.")
```

### Дополнительная информация

Этот метод использует возможности драйвера Appium для извлечения файлов с подключенного устройства. Сначала он извлекает файл с устройства в виде строки в формате base64, затем декодирует эту строку и записывает полученные данные в файл по указанному локальному пути. Если в процессе возникают ошибки (например, если исходный файл не существует или назначение недоступно), метод возвращает `False` и записывает информацию об ошибке в лог.

### Исключения

Метод может генерировать исключение `IOError`, если возникают проблемы с записью файла на локальной машине. Это исключение обрабатывается внутри метода, и информация о нем записывается в лог.

## Метод: `start_activity()`

Этот метод класса `Terminal` предназначен для запуска определенной активности в приложении на подключенном устройстве с использованием adb shell команды.

### Параметры

- `package`: Название пакета приложения, в котором находится активность. Должен быть представлен в виде строки.

- `activity`: Название активности, которую нужно запустить. Должно быть представлено в виде строки.

### Возвращаемое значение

Возвращает `True`, если активность была успешно запущена. В противном случае возвращается `False`.

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

```python
terminal = Terminal(driver)
activity_started = terminal.start_activity(package="com.example", activity=".MainActivity")
if activity_started:
    print("Activity was successfully started.")
else:
    print("Activity starting failed.")
```

### Дополнительная информация

Метод использует adb shell команду `am start` для запуска активности. В случае успешного выполнения команды метод возвращает `True`. Если команда не может быть выполнена (например, если указанное приложение или активность не существуют), метод возвращает `False` и записывает информацию об ошибке в лог.

### Исключения

Метод может генерировать исключение `KeyError`, если в процессе выполнения adb shell команды возникают проблемы. Это исключение обрабатывается внутри метода, и информация о нем записывается в лог.

## Метод: `get_current_app_package()`

Метод класса `Terminal` предназначен для получения имени пакета текущего запущенного приложения на подключенном устройстве.

### Возвращаемое значение

Возвращает строку, содержащую имя пакета текущего запущенного приложения. В случае ошибки возвращает `None`.

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

```python
terminal = Terminal(driver)
current_app_package = terminal.get_current_app_package()
if current_app_package:
    print(f"The current running app package is {current_app_package}.")
else:
    print("Failed to get the current running app package.")
```

### Дополнительная информация

Метод использует команду adb shell `dumpsys window windows` для получения информации о текущем активном окне на устройстве. Эта информация анализируется, и из неё извлекается имя пакета запущенного приложения. Если информацию не удалось извлечь (например, если нет активного окна или приложения), метод возвращает `None`.

### Исключения

Метод может генерировать исключение `KeyError`, если в процессе выполнения команды adb shell возникают проблемы. Это исключение обрабатывается внутри метода, и информация о нем записывается в лог.

## Метод: `close_app()`

Метод класса `Terminal`, который принудительно закрывает приложение на подключенном устройстве с помощью указанного имени пакета.

### Параметры

- `package`: Строка, содержащая имя пакета приложения, которое необходимо закрыть.

### Возвращаемое значение

Возвращает `True`, если приложение было успешно закрыто, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.close_app("com.example.myapp"):
    print("The app was successfully closed.")
else:
    print("Failed to close the app.")
```

### Дополнительная информация

Метод использует команду adb shell `am force-stop`, чтобы принудительно остановить приложение с указанным именем пакета.

### Исключения

Метод может генерировать исключение `KeyError`, если в процессе выполнения команды adb shell возникают проблемы. Это исключение обрабатывается внутри метода, и информация о нем записывается в лог.

## Метод: `reboot_app()`

Метод класса `Terminal`, который перезапускает указанное приложение, сначала принудительно закрывая его, а затем запуская указанную активность.

### Параметры

- `package`: Строка, содержащая имя пакета приложения, которое необходимо перезапустить.

- `activity`: Строка, содержащая имя активности приложения, которую необходимо запустить.

### Возвращаемое значение

Возвращает `True`, если перезапуск приложения выполнен успешно, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.reboot_app("com.example.myapp", "com.example.myapp.MainActivity"):
    print("The app was successfully rebooted.")
else:
    print("Failed to reboot the app.")
```

### Дополнительная информация

Этот метод сначала закрывает приложение с использованием метода `close_app()`, а затем пытается его перезапустить с использованием метода `start_activity()`. Если какой-либо из этих методов возвращает `False`, метод `reboot_app()` также вернет `False`.

### Исключения

Метод может генерировать исключение, если в процессе его выполнения возникают проблемы. В частности, если методы `close_app()` или `start_activity()` возвращают `False`, метод `reboot_app()` также вернет `False`.

## Метод: `uninstall_app()`

Метод класса `Terminal`, который удаляет указанное приложение с помощью ADB (Android Debug Bridge).

### Параметры

- `package`: Строка, содержащая имя пакета приложения, которое необходимо удалить.

### Возвращаемое значение

Возвращает `True`, если приложение успешно удалено, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.uninstall_app("com.example.myapp"):
    print("The app was successfully uninstalled.")
else:
    print("Failed to uninstall the app.")
```

### Дополнительная информация

Этот метод использует метод `remove_app()` из `driver` для удаления приложения. Если удаление успешно, метод `remove_app()` не возвращает значение, в противном случае он может вызвать исключение.

### Исключения

Метод может генерировать исключение, если в процессе его выполнения возникают проблемы. Если метод `remove_app()` вызывает исключение, это исключение будет логироваться, а метод `uninstall_app()` вернет `False`.

## Метод: `install_app()`

Метод класса `Terminal`, который устанавливает указанное приложение с помощью Appium.

### Параметры

- `app_path`: Строка, содержащая путь до APK-файла приложения, которое необходимо установить.

### Возвращаемое значение

Возвращает `True`, если приложение успешно установлено, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.install_app("/path/to/myapp.apk"):
    print("The app was successfully installed.")
else:
    print("Failed to install the app.")
```

### Дополнительная информация

Этот метод использует метод `install_app()` из `driver` для установки приложения. Если установка успешна, метод `install_app()` не возвращает значение, в противном случае он может вызвать исключение.

### Исключения

Метод может генерировать исключение, если в процессе его выполнения возникают проблемы. Если метод `install_app()` вызывает исключение, это исключение будет логироваться, а метод `install_app()` вернет `False`.

## Метод: `is_app_installed()`

Метод класса `Terminal`, предназначенный для проверки установки указанного пакета приложения с помощью Appium.

### Параметры

- `package` (тип: `str`): Имя пакета приложения, для которого нужно проверить установку.

### Возвращаемое значение

Возвращает значение `True`, если указанный пакет приложения установлен на устройстве, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.is_app_installed("com.example.myapp"):
    print("The app is installed.")
else:
    print("The app is not installed.")
```

### Дополнительная информация

Метод `is_app_installed()` использует команду `pm list packages` для получения списка установленных пакетов приложений. Затем он фильтрует список и проверяет, содержится ли указанный пакет среди установленных. Если пакет найден в списке, метод вернет `True`, в противном случае вернет `False`.

### Исключения

Метод может вызывать исключение типа `KeyError`, если в процессе выполнения возникли проблемы с доступом к списку пакетов. В случае возникновения исключения, оно будет залогировано, и метод `is_app_installed()` вернет значение `False`.

**Примечание:** Для корректной работы метода `is_app_installed()`, убедитесь, что устройство подключено к Appium и правильно настроено для выполнения команд через ADB.

## Метод: `press_home()`

Метод класса `Terminal`, который эмулирует нажатие кнопки "Домой" на устройстве, используя Android Debug Bridge (ADB).

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Возвращает `True`, если команда была успешно выполнена, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.press_home():
    print("Home button was successfully pressed.")
else:
    print("Failed to press the home button.")
```

### Дополнительная информация

Этот метод отправляет команду `input_keycode` с кодом "KEYCODE_HOME" к драйверу Appium. Если команда выполнена успешно, метод `input_keycode` не возвращает значение, в противном случае он может вызвать исключение.

### Исключения

Метод может вызвать исключение, если возникают проблемы при выполнении его. Если метод `input_keycode` вызывает исключение, это исключение будет залогировано, а метод `press_home()` вернет `False`.

## Метод: `press_back()`

Метод класса `Terminal`, который эмулирует нажатие кнопки "Назад" на устройстве, используя Android Debug Bridge (ADB).

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Возвращает `True`, если команда была успешно выполнена, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.press_back():
    print("Back button was successfully pressed.")
else:
    print("Failed to press the back button.")
```

### Дополнительная информация

Этот метод отправляет команду `input_keycode` с кодом "KEYCODE_BACK" к драйверу Appium. Если команда выполнена успешно, метод `input_keycode` не возвращает значение, в противном случае он может вызвать исключение.

### Исключения

Метод может вызвать исключение, если возникают проблемы при выполнении его. Если метод `input_keycode` вызывает исключение, это исключение будет залогировано, а метод `press_back()` вернет `False`.

## Метод: `press_menu()`

Метод класса `Terminal`, который эмулирует нажатие кнопки "Меню" на устройстве, используя Android Debug Bridge (ADB).

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Возвращает `True`, если команда была успешно выполнена, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.press_menu():
    print("Menu button was successfully pressed.")
else:
    print("Failed to press the menu button.")
```

### Дополнительная информация

Этот метод отправляет команду `input_keycode` с кодом "KEYCODE_MENU" к драйверу Appium. Если команда выполнена успешно, метод `input_keycode` не возвращает значение, в противном случае он может вызвать исключение.

### Исключения

Метод может вызвать исключение, если возникают проблемы при выполнении его. Если метод `input_keycode` вызывает исключение, это исключение будет залогировано, а метод `press_menu()` вернет `False`.

## Метод: `input_keycode_num_()`

Этот метод класса `Terminal` имитирует нажатие клавиши на числовой клавиатуре устройства с использованием Android Debug Bridge (ADB).

### Параметры

Метод принимает следующие параметры:

- `num (int)`: числовое значение нажимаемой клавиши.

### Возвращаемое значение

Возвращает `True`, если команда была успешно выполнена, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.input_keycode_num_(5):
    print("Клавиша с числом 5 была успешно нажата.")
else:
    print("Не удалось нажать клавишу с числом 5.")
```

### Дополнительная информация

Этот метод отправляет команду `adb_shell` с командой `input` и аргументом `keyevent KEYCODE_NUMPAD_{num}` в драйвер Appium. Если команда успешно выполнена, метод `adb_shell` не возвращает значение, в противном случае, он может вызвать исключение.

### Исключения

Метод может вызвать исключение, если при его выполнении возникли проблемы. Если метод `adb_shell` вызывает исключение, это исключение будет залогировано, и метод `input_keycode_num_()` вернет `False`.

## Метод: `input_keycode()`

Метод класса `Terminal`, который имитирует ввод указанного кода клавиши на устройстве с помощью Android Debug Bridge (ADB).

### Параметры

Метод принимает следующий параметр:

- `keycode (str)`: код клавиши для ввода. Это может быть любой код клавиши, поддерживаемый ADB, включая, но не ограничиваясь, такими как "KEYCODE_HOME", "KEYCODE_BACK", "KEYCODE_MENU" и т. д.

### Возвращаемое значение

Метод возвращает `True`, если команда была успешно выполнена, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.input_keycode("KEYCODE_HOME"):
    print("Клавиша Home была успешно нажата.")
else:
    print("Не удалось нажать клавишу Home.")
```

### Дополнительная информация

Метод отправляет команду `adb_shell` с командой `input` и аргументом `keyevent {keycode}` в драйвер Appium. Если команда успешно выполнена, метод `adb_shell` не возвращает значение, в противном случае, он может вызвать исключение.

### Исключения

Метод может вызвать исключение `KeyError`, если при его выполнении возникли проблемы. Если метод `adb_shell` вызывает исключение, это исключение будет залогировано, и метод `input_keycode()` вернет `False`.

## Метод: `input_by_virtual_keyboard()`

Метод класса `Terminal`, который эмулирует ввод строки символов с помощью виртуальной клавиатуры на устройстве.

### Параметры

Метод принимает следующие параметры:

- `key (str)`: Строка символов, которые требуется ввести.
- `keyboard (dict)`: Словарь, отображающий символы на координаты нажатия на экране. Ключами словаря являются символы, а значениями - кортежи, содержащие координаты x и y на экране для каждого символа.

### Возвращаемое значение

Метод возвращает `True`, если ввод символов был выполнен успешно, и `False` в противном случае.

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

```python
keyboard_mapping = {
    "a": (100, 200),
    "b": (120, 220),
    ...
}
terminal = Terminal(driver)
if terminal.input_by_virtual_keyboard("abc", keyboard_mapping):
    print("Ввод символов 'abc' выполнен успешно.")
else:
    print("Ошибка при вводе символов 'abc'.")
```

### Дополнительная информация

В данном методе используется функция `tap()`, которая выполняет нажатие на указанные координаты на экране. Для каждого символа во входной строке метод вызывает функцию `tap()` с координатами, соответствующими этому символу.

### Исключения

Метод может вызвать исключение `KeyError`, если при его выполнении возникли проблемы, например, если указанный символ отсутствует в словаре `keyboard`. Если метод `tap()` вызывает исключение, это исключение будет залогировано, и метод `input_by_virtual_keyboard()` вернет `False`.

## Метод: `input_text()`

Метод класса `Terminal`, который эмулирует ввод указанного текста на устройстве с использованием ADB (Android Debug Bridge).

### Параметры

Метод принимает следующий параметр:

- `text (str)`: Строка текста, которую нужно ввести на устройстве.

### Возвращаемое значение

Метод возвращает `True`, если команда была успешно выполнена, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.input_text("Hello, world!"):
    print("Текст 'Hello, world!' успешно введен.")
else:
    print("Ошибка при вводе текста 'Hello, world!'.")
```

### Дополнительная информация

В данном методе используется функция `adb_shell()`, которая отправляет ADB команду в shell Android устройства. С помощью ADB команды "input text" мы можем ввести текст на устройстве.

### Исключения

Метод может вызвать исключение `KeyError`, если при его выполнении возникли проблемы. Если возникает исключение, оно будет залогировано, и метод `input_text()` вернет `False`.

## Метод: `tap()`

Это метод класса `Terminal`, который эмулирует нажатие на указанные координаты на устройстве с использованием ADB (Android Debug Bridge).

### Параметры

Метод принимает следующие параметры:

- `x (int)`: Координата по оси X точки, по которой нужно нажать.
- `y (int)`: Координата по оси Y точки, по которой нужно нажать.

### Возвращаемое значение

Метод возвращает `True`, если команда была успешно выполнена, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.tap(200, 300):
    print("Нажатие на координаты (200, 300) успешно выполнено.")
else:
    print("Ошибка при нажатии на координаты (200, 300).")
```

### Дополнительная информация

В данном методе используется функция `adb_shell()`, которая отправляет ADB команду в shell Android устройства. С помощью ADB команды "input tap" мы можем выполнить нажатие на определенные координаты экрана.

### Исключения

Метод может вызвать исключение `KeyError`, если при его выполнении возникли проблемы. Если возникает исключение, оно будет залогировано, и метод `tap()` вернет `False`.

## Метод: `swipe()`

Это метод класса `Terminal`, который эмулирует жест свайпа (или перетаскивания) с одной точки на экране до другой на устройстве с использованием ADB (Android Debug Bridge).

### Параметры

Метод принимает следующие параметры:

- `start_x (Union[str, int])`: Координата по оси X начальной точки свайпа.
- `start_y (Union[str, int])`: Координата по оси Y начальной точки свайпа.
- `end_x (Union[str, int])`: Координата по оси X конечной точки свайпа.
- `end_y (Union[str, int])`: Координата по оси Y конечной точки свайпа.
- `duration (int)`: Длительность свайпа в миллисекундах. По умолчанию равна 300 мс.

### Возвращаемое значение

Метод возвращает `True`, если команда была успешно выполнена, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.swipe(200, 300, 400, 500, 1000):
    print("Свайп с координат (200, 300) до координат (400, 500) выполнен успешно.")
else:
    print("Ошибка при выполнении свайпа.")
```

### Дополнительная информация

В данном методе используется функция `adb_shell()`, которая отправляет ADB команду в shell Android устройства. С помощью ADB команды "input swipe" мы можем выполнить свайп по экрану от одних координат до других.

### Исключения

Метод может вызвать исключение `KeyError`, если при его выполнении возникли проблемы. Если возникает исключение, оно будет залогировано, и метод `swipe()` вернет `False`.

## Метод: `check_vpn()`

Это метод класса `Terminal`, который проверяет, активно ли VPN-соединение на устройстве, используя ADB (Android Debug Bridge).

### Параметры

Метод принимает следующий параметр:

- `ip_address (str)`: IP-адрес для проверки VPN-соединения. Если он не указан, то используется значение по умолчанию.

### Возвращаемое значение

Метод возвращает `True`, если VPN-соединение активно, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.check_vpn('192.168.0.1'):
    print("VPN-соединение активно.")
else:
    print("VPN-соединение не активно.")
```

### Дополнительная информация

В данном методе используется функция `adb_shell()`, которая отправляет ADB команду в shell Android устройства. С помощью команды "netstat" мы можем проверить состояние сетевых соединений устройства.

### Исключения

Метод может вызвать исключение `KeyError`, если при его выполнении возникли проблемы. Если возникает исключение, оно будет залогировано, и метод `check_vpn()` вернет `False`.

## Метод: `stop_logcat()`

Это метод класса `Terminal`, который останавливает выполнение logcat на устройстве, используя ADB (Android Debug Bridge).

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает `True`, если выполнение logcat остановлено успешно, и `False` в противном случае.

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

```python
terminal = Terminal(driver)
if terminal.stop_logcat():
    print("logcat остановлен успешно.")
else:
    print("Не удалось остановить logcat.")
```

### Дополнительная информация

Метод `stop_logcat()` сначала получает список всех выполняющихся процессов на устройстве с помощью команды `ps`. Затем он проходит через этот список и отправляет сигнал `SIGINT` каждому процессу `logcat`, который он находит, чтобы остановить его.

### Исключения

Метод может вызвать исключение `KeyError`, если при его выполнении возникли проблемы. Если возникает исключение, оно будет залогировано, и метод `stop_logcat()` вернет `False`.

## Метод: `know_pid()`

Это метод класса `Terminal`, который ищет и возвращает идентификатор процесса (PID) по его имени с помощью команды `adb shell ps`.

### Параметры

* `name (str)`: Имя процесса, PID которого необходимо найти.

### Возвращаемое значение

Метод возвращает `int` или `None`. Если процесс с указанным именем найден, метод возвращает его PID (как целое число). Если процесс не найден, метод возвращает `None`.

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

```python
terminal = Terminal(driver)
pid = terminal.know_pid("com.example.app")
if pid is not None:
    print(f"PID процесса 'com.example.app': {pid}")
else:
    print("Процесс 'com.example.app' не найден.")
```

### Дополнительная информация

Метод `know_pid()` получает список всех выполняющихся процессов на устройстве с помощью команды `adb shell ps`, затем проходит по этому списку и ищет процесс с указанным именем. Если такой процесс найден, метод возвращает его PID. Если процесс не найден, метод возвращает `None`.

### Исключения

Метод не обрабатывает исключения и, таким образом, может вызвать любое исключение, которое может вызвать `adb_shell(command)`.


## Метод: `is_process_exist()`

Это метод класса `Terminal`, который проверяет, существует ли процесс с указанным именем, используя команду `adb shell ps`.

### Параметры

* `name (str)`: Имя процесса, которое требуется проверить на существование.

### Возвращаемое значение

Метод возвращает `bool`. Если процесс с указанным именем существует, метод возвращает `True`. В противном случае, если процесс не найден, метод возвращает `False`.

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

```python
terminal = Terminal(driver)
if terminal.is_process_exist("com.example.app"):
    print("Процесс 'com.example.app' существует.")
else:
    print("Процесс 'com.example.app' не существует.")
```

### Дополнительная информация

Метод `is_process_exist(name)` получает список всех выполняющихся процессов на устройстве с помощью команды `adb shell ps`, затем проверяет, есть ли процесс с указанным именем в этом списке. Если процесс с заданным именем найден, метод возвращает `True`, иначе возвращает `False`.

### Исключения

Метод не обрабатывает исключения и, таким образом, может вызвать любое исключение, которое может возникнуть при выполнении `adb_shell(command)`.

**Примечание:** В описании метода `is_process_exist(name)` вместо `is_process_exist() > True` и `is_process_exist() > False`, используются логгеры для вывода отладочной информации. В реальной реализации эти строки не будут отображаться. Они присутствуют в данном контексте только для демонстрации логгирования.

## Метод: `run_background_process()`

Это метод класса `Terminal`, который запускает процесс в фоновом режиме на устройстве Android.

### Параметры

* `command (str)`: Команда для выполнения на устройстве.
* `args (str)`: Дополнительные аргументы для команды. По умолчанию `""`.
* `process (str)`: Название процесса, который будет запущен. По умолчанию `""`. Если значение `process` равно `""`, то не будет проверяться его запуск в системе.

### Возвращаемое значение

Метод возвращает `bool`. Если процесс был успешно запущен, метод возвращает `True`. В противном случае, если процесс не удалось запустить или указанный процесс не был найден, метод возвращает `False`.

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

```python
terminal = Terminal(driver)
command_to_run = "my_background_command arg1 arg2"
if terminal.run_background_process(command_to_run, args="--option"):
    print("Процесс был успешно запущен.")
else:
    print("Произошла ошибка при запуске процесса или процесс не найден.")
```

### Дополнительная информация

Метод `run_background_process(command, args="", process="")` выполняет переданную команду `command` на устройстве Android с дополнительными аргументами `args`. Команда запускается в фоновом режиме с использованием `nohup` и перенаправлением вывода в `/dev/null` для игнорирования вывода в консоль.

Если параметр `process` не равен пустой строке, метод после запуска процесса проверяет его существование через метод `is_process_exist(name=process)`. Если процесс не найден, метод вернет `False`. В противном случае, если процесс успешно запущен или параметр `process` равен пустой строке, метод вернет `True`.

Метод может вызывать исключение `KeyError`, и в таком случае он будет логировать ошибку и возвращать `False`.


## Метод: `kill_by_pid()`

Это метод класса `Terminal`, который посылает сигнал SIGINT процессу с указанным идентификатором процесса (PID), используя команду `adb shell kill`.

### Параметры

* `pid (int)`: Идентификатор процесса (PID), который нужно остановить.

### Возвращаемое значение

Метод возвращает `bool`. Если команда выполнена успешно и процесс остановлен, возвращается `True`. В противном случае - `False`.

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

```python
terminal = Terminal(driver)
pid = terminal.know_pid("com.example.app")
if pid is not None:
    if terminal.kill_by_pid(pid):
        print(f"Процесс с PID {pid} успешно остановлен.")
    else:
        print(f"Не удалось остановить процесс с PID {pid}.")
else:
    print("Процесс 'com.example.app' не найден.")
```

### Дополнительная информация

Метод `kill_by_pid()` отправляет команду `kill -s SIGINT {pid}` на устройство через `adb shell` для остановки процесса с указанным идентификатором процесса.

### Исключения

Метод обрабатывает исключение `KeyError`, которое может быть вызвано методом `adb_shell(command, args)`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `kill_all()`

Этот метод класса `Terminal` предназначен для остановки всех процессов, соответствующих заданному имени или шаблону имени, с помощью команды `adb shell pkill`.

### Параметры

* `name (str)`: Имя или шаблон имени процесса, который необходимо остановить.

### Возвращаемое значение

Метод возвращает `bool`. Если команда выполнена успешно и все процессы остановлены, возвращается `True`. В противном случае - `False`.

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

```python
terminal = Terminal(driver)
if terminal.kill_all("com.example.app"):
    print("Все процессы 'com.example.app' успешно остановлены.")
else:
    print("Не удалось остановить все процессы 'com.example.app'.")
```

### Дополнительная информация

Метод `kill_all()` отправляет команду `pkill -f {name}` на устройство через `adb shell` для остановки всех процессов, соответствующих заданному имени или шаблону имени.

### Исключения

Метод обрабатывает исключение `KeyError`, которое может быть вызвано методом `adb_shell(command, args)`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `delete_files_from_internal_storage()`

Этот метод класса `Terminal` предназначен для удаления файлов из внутреннего хранилища устройства с помощью команды `adb shell rm`.

### Параметры

* `path (str)`: Путь к папке во внутреннем хранилище, из которой необходимо удалить файлы.

### Возвращаемое значение

Метод возвращает `bool`. Если команда выполнена успешно и файлы удалены, возвращается `True`. В противном случае - `False`.

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

```python
terminal = Terminal(driver)
if terminal.delete_files_from_internal_storage("/sdcard/Download/"):
    print("Файлы успешно удалены из '/sdcard/Download/'.")
else:
    print("Не удалось удалить файлы из '/sdcard/Download/'.")
```

### Дополнительная информация

Метод `delete_files_from_internal_storage()` отправляет команду `rm -rf {path}*` на устройство через `adb shell` для удаления всех файлов в указанном каталоге.

### Исключения

Метод обрабатывает исключение `KeyError`, которое может быть вызвано методом `adb_shell(command, args)`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `delete_file_from_internal_storage()`

Этот метод класса `Terminal` предназначен для удаления конкретного файла из внутреннего хранилища устройства с помощью команды `adb shell rm`.

### Параметры

* `path (str)`: Путь к папке во внутреннем хранилище, из которой необходимо удалить файл.
* `filename (str)`: Имя файла, который необходимо удалить.

### Возвращаемое значение

Метод возвращает `bool`. Если команда выполнена успешно и файл удален, возвращается `True`. В противном случае - `False`.

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

```python
terminal = Terminal(driver)
if terminal.delete_file_from_internal_storage("/sdcard/Download/", "myfile.txt"):
    print("Файл 'myfile.txt' успешно удален из '/sdcard/Download/'.")
else:
    print("Не удалось удалить файл 'myfile.txt' из '/sdcard/Download/'.")
```

### Дополнительная информация

Метод `delete_file_from_internal_storage()` отправляет команду `rm -rf {path}/{filename}` на устройство через `adb shell` для удаления указанного файла в указанном каталоге.

### Исключения

Метод обрабатывает исключение `KeyError`, которое может быть вызвано методом `adb_shell(command, args)`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `record_video()`

Этот метод класса `Terminal` предназначен для начала записи видео с экрана устройства.

### Параметры

* `**options (Any)`: Опциональные аргументы для настройки записи видео. Обратитесь к документации Appium для получения полного списка доступных параметров.

### Возвращаемое значение

Метод возвращает `bool`. Если запись видео успешно начата, возвращается `True`. В противном случае - `False`.

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

```python
terminal = Terminal(driver)
if terminal.record_video():
    print("Запись видео успешно начата.")
else:
    print("Не удалось начать запись видео.")
```

### Дополнительная информация

Метод `record_video()` использует метод `start_recording_screen()` из библиотеки Appium для начала записи видео.

### Исключения

Метод обрабатывает исключение `KeyError`, которое может быть вызвано методом `start_recording_screen()`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `stop_video()`

Этот метод класса `Terminal` предназначен для остановки записи видео с экрана устройства и возвращения записанного видео в формате base64.

### Параметры

* `**options (Any)`: Опциональные аргументы для настройки остановки записи видео. Эти могут включать параметры, такие как 'withFile' и другие. Обратитесь к документации Appium для получения полного списка доступных параметров.

### Возвращаемое значение

Метод возвращает `Union[bytes, None]`. Если запись видео успешно остановлена, возвращается видео в виде декодированных из base64 байтов. В противном случае возвращается `None`.

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

```python
terminal = Terminal(driver)
video_bytes = terminal.stop_video()
if video_bytes is not None:
    with open('output.mp4', 'wb') as f:
        f.write(video_bytes)
    print("Видео успешно остановлено и сохранено.")
else:
    print("Не удалось остановить запись видео.")
```

### Дополнительная информация

Метод `stop_video()` использует метод `stop_recording_screen()` из библиотеки Appium для остановки записи видео. Этот метод возвращает видео в виде строки, закодированной в base64. Метод `stop_video()` затем декодирует эту строку в байты и возвращает их.

### Исключения

Метод обрабатывает исключение `KeyError`, которое может быть вызвано методом `stop_recording_screen()`. Если исключение возникает, оно логируется и метод возвращает `None`.

## Метод: `reboot()`

Этот метод класса `Terminal` предназначен для перезагрузки устройства с использованием ADB.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает `bool`. Если перезагрузка устройства успешно запущена, возвращается `True`. В противном случае возвращается `False`.

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

```python
terminal = Terminal(driver)
if terminal.reboot():
    print("Устройство успешно перезагружено.")
else:
    print("Не удалось запустить перезагрузку устройства.")
```

### Дополнительная информация

Метод `reboot()` использует команду `reboot` ADB для перезагрузки устройства.

### Исключения

Метод обрабатывает исключение `KeyError`, которое может быть вызвано методом `adb_shell()`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `get_screen_resolution()`

Этот метод класса `Terminal` предназначен для получения разрешения экрана устройства с использованием ADB.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает кортеж из двух целых чисел (`tuple[int, int]`) или `None`. Кортеж содержит ширину и высоту экрана в пикселях. Если происходит ошибка, возвращается `None`.

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

```python
terminal = Terminal(driver)
resolution = terminal.get_screen_resolution()
if resolution:
    print(f"Разрешение экрана устройства: {resolution[0]}x{resolution[1]}")
else:
    print("Не удалось получить разрешение экрана.")
```

### Дополнительная информация

Метод `get_screen_resolution()` использует команду `wm size` ADB для получения разрешения экрана устройства.

### Исключения

Метод обрабатывает исключение `KeyError`, которое может быть вызвано методом `adb_shell()`. Если исключение возникает, оно логируется и метод возвращает `None`.


# class Adb
Предназначен для взаимодействия с Android Debug Bridge (ADB). Этот класс будет использовать для выполнения различных команд на устройстве Android.

## Метод: `install_app()`

Этот метод класса `Adb` предназначен для установки приложения на устройство с использованием ADB.

### Параметры

Метод принимает следующие параметры:

1. `apk_path (str)`: Путь к APK-файлу приложения на компьютере.

### Возвращаемое значение

Метод возвращает `True` (`bool`), если приложение успешно установлено, и `False` в противном случае.

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

```python
adb = Adb()
if adb.install_app("path_to_apk"):
    print("Приложение успешно установлено.")
else:
    print("Не удалось установить приложение.")
```

### Дополнительная информация

Метод `install_app()` использует команду `adb install` для установки APK-файла на устройство.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может быть вызвано методом `subprocess.check_output()`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `is_app_installed()`

Этот метод класса `Adb` предназначен для проверки, установлено ли указанное приложение на подключенном устройстве Android с использованием ADB.

### Параметры

Метод принимает следующий параметр:

- `package` (`str`): Имя пакета приложения, которое нужно проверить.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если приложение установлено на устройстве.
- `False` - если приложение не установлено на устройстве или произошла ошибка при проверке.

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

```python
adb = Adb()
is_installed = adb.is_app_installed("com.example.app")
if is_installed:
    print("Приложение установлено на устройстве.")
else:
    print("Приложение не установлено на устройстве.")
```

### Дополнительная информация

Метод `is_app_installed()` использует команду `adb shell pm list packages` для получения списка всех установленных приложений на устройстве. Затем он проверяет, присутствует ли имя пакета в этом списке.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может быть вызвано методом `subprocess.check_output()`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `uninstall_app()`

Этот метод класса `Adb` предназначен для удаления приложения на подключенном устройстве Android.

### Параметры

Метод принимает следующий параметр:

- `package` (`str`): Имя пакета приложения, которое вы хотите удалить.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если приложение было успешно удалено с устройства.
- `False` - если произошла ошибка при удалении приложения.

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

```python
adb = Adb()
success = adb.uninstall_app("com.example.app")
if success:
    print("Приложение успешно удалено с устройства.")
else:
    print("Не удалось удалить приложение с устройства.")
```

### Дополнительная информация

Метод `uninstall_app()` использует команду `adb uninstall` для удаления указанного приложения.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду удаления приложения. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `get_device_model()`

Этот метод класса `Adb` предназначен для получения модели подключенного устройства Android с использованием ADB.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает модель устройства в виде строки (`str`) или `None`, если происходит ошибка при получении модели устройства.

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

```python
adb = Adb()
model = adb.get_device_model()
if model:
    print(f"Модель устройства: {model}")
else:
    print("Не удалось получить модель устройства.")
```

### Дополнительная информация

Метод `get_device_model()` использует команду `adb shell getprop ro.product.model` для получения модели устройства.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может быть вызвано методом `subprocess.check_output()`. Если исключение возникает, оно логируется и метод возвращает `None`.

## Метод: `push()`

Этот метод класса `Adb` предназначен для копирования файла или директории с вашего компьютера на подключенное устройство Android с использованием ADB.

### Параметры

Метод принимает следующие параметры:

- `source` (`str`): Путь на вашем компьютере к файлу или директории, который вы хотите скопировать.
- `destination` (`str`): Путь назначения на устройстве, куда вы хотите скопировать файл или директорию.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если файл или директория были успешно скопированы на устройство.
- `False` - если произошла ошибка при копировании файла или директории.

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

```python
adb = Adb()
success = adb.push("/path/to/local/file.txt", "/path/to/device/file.txt")
if success:
    print("Файл успешно скопирован на устройство.")
else:
    print("Не удалось скопировать файл на устройство.")
```

### Дополнительная информация

Метод `push()` использует команду `adb push` для копирования файла или директории на устройство.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может быть вызвано методом `subprocess.run()`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `pull()`

Этот метод класса `Adb` предназначен для копирования файла или директории с подключенного устройства Android на ваш компьютер с использованием ADB.

### Параметры

Метод принимает следующие параметры:

- `source` (`str`): Путь на устройстве к файлу или директории, которые вы хотите скопировать.
- `destination` (`str`): Путь назначения на вашем компьютере, куда вы хотите скопировать файл или директорию.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если файл или директория были успешно скопированы с устройства.
- `False` - если произошла ошибка при копировании файла или директории.

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

```python
adb = Adb()
success = adb.pull("/path/to/device/file.txt", "/path/to/local/file.txt")
if success:
    print("Файл успешно скопирован с устройства.")
else:
    print("Не удалось скопировать файл с устройства.")
```

### Дополнительная информация

Метод `pull()` использует команду `adb pull` для копирования файла или директории с устройства.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может быть вызвано методом `subprocess.run()`. Если исключение возникает, оно логируется и метод возвращает `False`.


## Метод: `start_activity()`

Этот метод класса `Adb` предназначен для запуска конкретной активности на подключенном устройстве Android с использованием ADB.

### Параметры

Метод принимает следующие параметры:

- `package` (`str`): Имя пакета активности, которую вы хотите запустить.
- `activity` (`str`): Имя активности, которую вы хотите запустить.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если активность была успешно запущена на устройстве.
- `False` - если произошла ошибка при запуске активности.

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

```python
adb = Adb()
success = adb.start_activity("com.example.app", "com.example.app.MainActivity")
if success:
    print("Активность успешно запущена на устройстве.")
else:
    print("Не удалось запустить активность на устройстве.")
```

### Дополнительная информация

Метод `start_activity()` использует команду `adb shell am start` для запуска активности на устройстве. Параметр `-n` используется для указания имени активности в формате `[package]/[activity]`.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может быть вызвано методом `subprocess.check_output()`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `close_app()`

Этот метод класса `Adb` предназначен для принудительного завершения указанного пакета на подключенном устройстве Android с использованием ADB.

### Параметры

Метод принимает следующие параметры:

- `package` (`str`): Имя пакета приложения, которое вы хотите закрыть.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если приложение было успешно закрыто на устройстве.
- `False` - если произошла ошибка при закрытии приложения.

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

```python
adb = Adb()
success = adb.close_app("com.example.app")
if success:
    print("Приложение успешно закрыто на устройстве.")
else:
    print("Не удалось закрыть приложение на устройстве.")
```

### Дополнительная информация

Метод `close_app()` использует команду `adb shell am force-stop` для принудительного завершения указанного пакета на устройстве.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может быть вызвано методом `subprocess.run()`. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `reboot_app()`

Этот метод класса `Adb` предназначен для перезапуска приложения на подключенном устройстве Android. Он делает это, закрывая приложение, а затем запуская указанную активность.

### Параметры

Метод принимает следующие параметры:

- `package` (`str`): Имя пакета приложения, которое вы хотите перезапустить.
- `activity` (`str`): Имя активности внутри пакета приложения, которую вы хотите запустить после закрытия приложения.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если приложение было успешно перезапущено на устройстве.
- `False` - если произошла ошибка при перезапуске приложения.

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

```python
adb = Adb()
success = adb.reboot_app("com.example.app", "com.example.app.MainActivity")
if success:
    print("Приложение успешно перезапущено на устройстве.")
else:
    print("Не удалось перезапустить приложение на устройстве.")
```

### Дополнительная информация

Метод `reboot_app()` использует методы `close_app()` и `start_activity()` класса `Adb` для выполнения своей функции.

### Исключения

Метод не обрабатывает исключения напрямую, но вызываемые им методы `close_app()` и `start_activity()` обрабатывают исключения `subprocess.CalledProcessError`. Если эти методы возвращают `False`, что указывает на появление исключения, то `reboot_app()` также возвращает `False`.

## Метод: `press_home()`

Этот метод класса `Adb` предназначен для отправки события нажатия кнопки Home на подключенном устройстве Android.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если событие нажатия кнопки Home было успешно отправлено на устройство.
- `False` - если произошла ошибка при отправке события.

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

```python
adb = Adb()
success = adb.press_home()
if success:
    print("Событие нажатия кнопки Home успешно отправлено.")
else:
    print("Не удалось отправить событие нажатия кнопки Home.")
```

### Дополнительная информация

Метод `press_home()` использует команду `adb shell input keyevent KEYCODE_HOME` для отправки события нажатия кнопки Home.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду отправки события. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `press_back()`

Этот метод класса `Adb` предназначен для отправки события нажатия кнопки Back на подключенном устройстве Android.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если событие нажатия кнопки Back было успешно отправлено на устройство.
- `False` - если произошла ошибка при отправке события.

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

```python
adb = Adb()
success = adb.press_back()
if success:
    print("Событие нажатия кнопки Back успешно отправлено.")
else:
    print("Не удалось отправить событие нажатия кнопки Back.")
```

### Дополнительная информация

Метод `press_back()` использует команду `adb shell input keyevent KEYCODE_BACK` для отправки события нажатия кнопки Back.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду отправки события. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `press_menu()`

Этот метод класса `Adb` предназначен для отправки события нажатия кнопки Menu на подключенном устройстве Android.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если событие нажатия кнопки Menu было успешно отправлено на устройство.
- `False` - если произошла ошибка при отправке события.

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

```python
adb = Adb()
success = adb.press_menu()
if success:
    print("Событие нажатия кнопки Menu успешно отправлено.")
else:
    print("Не удалось отправить событие нажатия кнопки Menu.")
```

### Дополнительная информация

Метод `press_menu()` использует команду `adb shell input keyevent KEYCODE_MENU` для отправки события нажатия кнопки Menu.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду отправки события. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `input_keycode_num_()`

Этот метод класса `Adb` предназначен для отправки события нажатия числовой клавиши на подключенном устройстве Android.

### Параметры

- `num` (int): Числовое значение клавиши для нажатия. Допустимые значения: от 0 до 9 и специальные символы (ADD, COMMA, DIVIDE, DOT, ENTER, EQUALS).

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если событие нажатия числовой клавиши было успешно отправлено на устройство.
- `False` - если произошла ошибка при отправке события.

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

```python
adb = Adb()
success = adb.input_keycode_num_(5)
if success:
    print("Событие нажатия числовой клавиши успешно отправлено.")
else:
    print("Не удалось отправить событие нажатия числовой клавиши.")
```

### Дополнительная информация

Метод `input_keycode_num_()` использует команду `adb shell input keyevent KEYCODE_NUMPAD_{num}` для отправки события нажатия числовой клавиши.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду отправки события. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `input_keycode()`

Этот метод класса `Adb` предназначен для ввода определенного кода клавиши на подключенном устройстве Android.

### Параметры

- `keycode` (str): Код клавиши для ввода. Примеры допустимых значений: "KEYCODE_HOME", "KEYCODE_BACK", "KEYCODE_VOLUME_UP" и т.д.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если команда ввода клавиши была успешно выполнена.
- `False` - если произошла ошибка при выполнении команды.

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

```python
adb = Adb()
success = adb.input_keycode("KEYCODE_HOME")
if success:
    print("Команда ввода клавиши успешно выполнена.")
else:
    print("Не удалось выполнить команду ввода клавиши.")
```

### Дополнительная информация

Метод `input_keycode()` использует команду `adb shell input keyevent {keycode}` для ввода кода клавиши на устройстве.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду ввода клавиши. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `input_by_virtual_keyboard()`

Этот метод класса `Adb` предназначен для ввода строки символов с помощью виртуальной клавиатуры на подключенном устройстве Android.

### Параметры

- `text` (str): Строка символов для ввода.
- `keyboard` (dict): Словарь с маппингом символов на координаты нажатий на виртуальной клавиатуре. Каждому символу в словаре соответствует кортеж из двух чисел, представляющих координаты нажатия (x, y).

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если ввод выполнен успешно.
- `False` - если произошла ошибка при вводе символов.

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

```python
keyboard_mapping = {
    'a': (100, 200),
    'b': (150, 200),
    # ...
}
adb = Adb()
success = adb.input_by_virtual_keyboard("ab", keyboard_mapping)
if success:
    print("Ввод символов выполнен успешно.")
else:
    print("Не удалось выполнить ввод символов.")
```

### Дополнительная информация

Метод `input_by_virtual_keyboard()` использует функцию `tap()` класса `Adb` для ввода каждого символа, проходя по всем символам в заданной строке `text`.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке ввода символа. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `input_text()`

Этот метод класса `Adb` предназначен для ввода текста на подключенном устройстве Android.

### Параметры

- `text` (str): Текст для ввода на устройстве.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если команда была успешно выполнена.
- `False` - если произошла ошибка при выполнении команды.

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

```python
adb = Adb()
success = adb.input_text("Hello, World!")
if success:
    print("Ввод текста выполнен успешно.")
else:
    print("Не удалось выполнить ввод текста.")
```

### Дополнительная информация

Метод `input_text()` использует команду `adb shell input text` для ввода текста на устройстве Android. Пожалуйста, убедитесь, что текст, который вы хотите ввести, не содержит специальных символов, которые могут нарушить работу команды ADB.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `tap()`

Этот метод класса `Adb` предназначен для совершения нажатия на экран устройства в заданных координатах.

### Параметры

- `x` (str, int): Координата по оси X, где требуется произвести нажатие. Может быть как числом, так и строкой.
- `y` (str, int): Координата по оси Y, где требуется произвести нажатие. Может быть как числом, так и строкой.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если команда была успешно выполнена.
- `False` - если произошла ошибка при выполнении команды.

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

```python
adb = Adb()
success = adb.tap(100, 200)
if success:
    print("Нажатие выполнено успешно.")
else:
    print("Не удалось выполнить нажатие.")
```

### Дополнительная информация

Метод `tap()` использует команду `adb shell input tap` для совершения нажатия на экране устройства в указанных координатах.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `swipe()`

Этот метод класса `Adb` предназначен для выполнения свайпа (перетаскивания) на экране устройства.

### Параметры

- `start_x` (str, int): Координата X начальной точки свайпа. Может быть как числом, так и строкой.
- `start_y` (str, int): Координата Y начальной точки свайпа. Может быть как числом, так и строкой.
- `end_x` (str, int): Координата X конечной точки свайпа. Может быть как числом, так и строкой.
- `end_y` (str, int): Координата Y конечной точки свайпа. Может быть как числом, так и строкой.
- `duration` (int, optional): Длительность свайпа в миллисекундах. По умолчанию равна 300.

### Возвращаемое значение

Метод возвращает логическое значение `bool`:
- `True` - если команда была успешно выполнена.
- `False` - если произошла ошибка при выполнении команды.

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

```python
adb = Adb()
success = adb.swipe(100, 200, 300, 400)
if success:
    print("Свайп выполнен успешно.")
else:
    print("Не удалось выполнить свайп.")
```

### Дополнительная информация

Метод `swipe()` использует команду `adb shell input swipe` для выполнения свайпа на экране устройства от начальной точки к конечной.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `get_current_app_package()`

Этот метод класса `Adb` предназначен для получения названия пакета текущего запущенного приложения на устройстве.

### Параметры

Метод не требует параметров.

### Возвращаемое значение

Метод возвращает строку, представляющую название пакета текущего запущенного приложения, или `None`, если произошла ошибка.

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

```python
adb = Adb()
package = adb.get_current_app_package()
if package:
    print(f"Текущее приложение: {package}")
else:
    print("Не удалось определить текущее приложение.")
```

### Дополнительная информация

Метод `get_current_app_package()` использует команду `adb shell dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp' | grep -e 'mFo'` для получения информации о текущем запущенном приложении. Затем он анализирует результат этой команды, чтобы извлечь название пакета приложения.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, оно логируется и метод возвращает `None`.

## Метод: `check_vpn()`

Этот метод класса `Adb` предназначен для проверки, установлено ли VPN-соединение на устройстве.

### Параметры

- `ip_address` (str, по умолчанию `''`): IP-адрес для проверки VPN-соединения. Если параметр не указан, используется значение из конфигурации.

### Возвращаемое значение

Метод возвращает булевое значение: `True`, если VPN-соединение активно, и `False` в противном случае.

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

```python
adb = Adb()
vpn_status = adb.check_vpn('192.168.1.1')
if vpn_status:
    print("VPN-соединение активно.")
else:
    print("VPN-соединение не активно.")
```

### Дополнительная информация

Метод `check_vpn()` использует команду `adb shell netstat | grep -w -e [ip_address]` для проверки активности VPN-соединения. Если в выводе команды присутствует слово "ESTABLISHED", метод возвращает `True`, что означает, что VPN-соединение активно.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `stop_logcat()`

Этот метод класса `Adb` предназначен для остановки выполнения `logcat` на устройстве.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

Метод возвращает булевое значение: `True`, если выполнение `logcat` остановлено успешно, и `False` в противном случае.

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

```python
adb = Adb()
logcat_status = adb.stop_logcat()
if logcat_status:
    print("logcat успешно остановлен.")
else:
    print("Не удалось остановить logcat.")
```

### Дополнительная информация

Метод `stop_logcat()` сначала использует команду `adb shell ps | grep logcat` для получения списка процессов `logcat`. Затем, для каждого найденного процесса, он отправляет сигнал `SIGINT`, используя команду `adb shell kill -s SIGINT [pid]`.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, оно логируется и метод возвращает `False`.

## Метод: `reload_adb()`

Этот метод класса `Adb` предназначен для перезапуска adb-сервера на устройстве.

### Параметры

Метод не принимает параметров.

### Возвращаемое значение

Метод возвращает булевое значение: `True`, если adb-сервер успешно перезапущен, и `False` в противном случае.

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

```python
adb = Adb()
adb_status = adb.reload_adb()
if adb_status:
    print("adb-сервер успешно перезапущен.")
else:
    print("Не удалось перезапустить adb-сервер.")
```

### Дополнительная информация

Метод `reload_adb()` сначала использует команду `adb kill-server` для остановки adb-сервера. Затем, после паузы в три секунды, используется команда `adb start-server` для перезапуска adb-сервера.

### Исключения

Метод обрабатывает исключение `subprocess.CalledProcessError`, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, оно логируется и метод возвращает `False`.


## Метод: `know_pid()`

Этот метод находит Process ID (PID) процесса по его имени, используя `adb shell ps`.

### Параметры

Метод принимает следующие параметры:

- `name`: Имя процесса, PID которого нужно найти.

### Возвращаемое значение

Метод возвращает PID процесса, если он найден, или `None`, если процесс не найден.

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

```python
adb = Adb()
process_pid = adb.know_pid("my_process")
if process_pid:
    print("PID процесса 'my_process' найден.")
else:
    print("Процесс 'my_process' не найден.")
```

### Дополнительная информация

Метод `know_pid()` выполняет команду `adb shell ps` и затем проходит через вывод, пытаясь найти строку, которая содержит имя указанного процесса. Если такая строка найдена, метод извлекает PID из этой строки и возвращает его.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`. Также, если процесс с указанным именем не найден, метод возвращает `None`.

## Метод: `know_pid()`

Этот метод находит Process ID (PID) процесса по его имени, используя `adb shell ps`.

### Параметры

Метод принимает следующие параметры:

- `name` (str): Имя процесса, PID которого нужно найти.

### Возвращаемое значение

Метод возвращает PID процесса, если он найден, или `None`, если процесс не найден.

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

```python
adb = Adb()
process_pid = adb.know_pid("my_process")
if process_pid:
    print("PID процесса 'my_process' найден.")
else:
    print("Процесс 'my_process' не найден.")
```

### Дополнительная информация

Метод `know_pid()` выполняет команду `adb shell ps` и затем проходит через вывод, пытаясь найти строку, которая содержит имя указанного процесса. Если такая строка найдена, метод извлекает PID из этой строки и возвращает его.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`. Также, если процесс с указанным именем не найден, метод возвращает `None`.

### Метод: `is_process_exist()`

Проверяет, запущен ли процесс, используя `adb shell ps`.

#### Параметры

- `name` (str): Имя процесса.

#### Возвращаемое значение

Метод возвращает `True`, если процесс с указанным именем существует, и `False` в ином случае.

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

```python
adb = Adb()
if adb.is_process_exist("my_process"):
    print("Процесс 'my_process' существует.")
else:
    print("Процесс 'my_process' не существует.")
```

Данный метод `is_process_exist()` используется внутри метода `know_pid()` для определения наличия процесса с заданным именем.


## Метод: `run_background_process()`

Запускает процесс в фоновом режиме на устройстве Android с использованием ADB.

### Параметры

- `command` (str): Команда для выполнения на устройстве.
- `process` (str): Название процесса, который будет запущен. По умолчанию пустая строка (`""`). Если `process == ""`, то не будет проверяться его запуск в системе.

### Возвращаемое значение

Метод возвращает `True`, если процесс был успешно запущен, и `False` в противном случае.

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

```python
adb = Adb()
command = "my_script.sh"
process_name = "my_process"
if adb.run_background_process(command, process_name):
    print(f"Процесс '{process_name}' был успешно запущен.")
else:
    print(f"Не удалось запустить процесс '{process_name}'.")
```

### Дополнительная информация

Метод `run_background_process()` запускает процесс в фоновом режиме на устройстве Android с использованием команды `adb shell` и `nohup` для выполнения команды без привязки к текущей сессии терминала. Вывод команды перенаправляется в `/dev/null`, чтобы не создавать логов в текущей сессии.

Если указан аргумент `process`, метод проверяет наличие процесса с указанным именем, используя метод `is_process_exist(name)`, чтобы убедиться, что процесс был успешно запущен.

В случае возникновения исключения при выполнении команды, метод возвращает `False`, а также логирует информацию об ошибке.


## Метод: `kill_by_pid()`

Этот метод отправляет сигнал SIGINT для остановки процесса по указанному идентификатору PID с помощью ADB.

### Параметры

Метод принимает следующий параметр:

- `pid`: Идентификатор PID процесса для остановки.

### Возвращаемое значение

Метод возвращает `True`, если процесс успешно остановлен, и `False` в противном случае.

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

```python
adb = Adb()
process_status = adb.kill_by_pid("1234")
if process_status:
    print("Процесс с PID '1234' успешно остановлен.")
else:
    print("Не удалось остановить процесс с PID '1234'.")
```

### Дополнительная информация

Метод `kill_by_pid()` выполняет команду `adb shell kill -s SIGINT <pid>`, чтобы отправить сигнал SIGINT указанному процессу. Этот сигнал останавливает процесс.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`.

## Метод: `kill_by_name()`

Этот метод останавливает все процессы с указанным именем на устройстве с помощью ADB.

### Параметры

Метод принимает следующий параметр:

- `name`: Имя процесса для остановки.

### Возвращаемое значение

Метод возвращает `True`, если все процессы успешно остановлены, и `False` в противном случае.

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

```python
adb = Adb()
process_status = adb.kill_by_name("my_process")
if process_status:
    print("Все процессы с именем 'my_process' успешно остановлены.")
else:
    print("Не удалось остановить процессы с именем 'my_process'.")
```

### Дополнительная информация

Метод `kill_by_name()` выполняет команду `adb shell pkill -l SIGINT <name>`, чтобы остановить все процессы с указанным именем.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`.

## Метод: `kill_all()`

Этот метод останавливает все процессы, соответствующие указанному имени или шаблону имени, на устройстве с помощью ADB.

### Параметры

Метод принимает следующий параметр:

- `name`: Имя процесса или шаблон имени для остановки.

### Возвращаемое значение

Метод возвращает `True`, если все процессы успешно остановлены, и `False` в противном случае.

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

```python
adb = Adb()
process_status = adb.kill_all("my_process")
if process_status:
    print("Все процессы, соответствующие имени 'my_process', успешно остановлены.")
else:
    print("Не удалось остановить процессы, соответствующие имени 'my_process'.")
```

### Дополнительная информация

Метод `kill_all()` выполняет команду `adb shell pkill -f <name>`, чтобы остановить все процессы, соответствующие указанному имени или шаблону имени.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`.

## Метод: `delete_files_from_internal_storage()`

Этот метод удаляет файлы из внутреннего хранилища устройства с помощью ADB.

### Параметры

Метод принимает следующий параметр:

- `path`: Путь к файлам для удаления.

### Возвращаемое значение

Метод возвращает `True`, если файлы успешно удалены, и `False` в противном случае.

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

```python
adb = Adb()
delete_status = adb.delete_files_from_internal_storage("/sdcard/MyFiles/")
if delete_status:
    print("Файлы успешно удалены из '/sdcard/MyFiles/'.")
else:
    print("Не удалось удалить файлы из '/sdcard/MyFiles/'.")
```

### Дополнительная информация

Метод `delete_files_from_internal_storage()` выполняет команду `adb shell rm -rf <path>*` для удаления всех файлов в указанной директории.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`.

## Метод: `pull_video()`

Этот метод копирует видеофайлы с устройства на компьютер с помощью ADB.

### Параметры

Метод принимает следующие параметры:

- `wherefrom` (необязательный): Путь к исходной директории на устройстве, откуда нужно скопировать видеофайлы. Если не указан, по умолчанию используется путь '/sdcard/Movies/'.
- `destination`: Путь для сохранения скопированных видеофайлов на компьютере.
- `delete` (необязательный): Флаг, указывающий, следует ли удалять видеофайлы после копирования с устройства. По умолчанию значение `True`.

### Возвращаемое значение

Метод возвращает `True`, если видеофайлы успешно скопированы, и `False` в противном случае.

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

```python
adb = Adb()
copy_status = adb.pull_video("/sdcard/MyVideos/", "/home/user/Videos/")
if copy_status:
    print("Видеофайлы успешно скопированы в '/home/user/Videos/'.")
else:
    print("Не удалось скопировать видеофайлы в '/home/user/Videos/'.")
```

### Дополнительная информация

Метод `pull_video()` сначала выполняет команду `adb pull <wherefrom> <destination>` для копирования видеофайлов из указанной директории на устройстве в указанную директорию на компьютере. Если флаг `delete` установлен в `True`, после копирования видеофайлы удаляются из исходной директории на устройстве командой `adb shell rm -rf <wherefrom>*`.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команды ADB. Если исключение возникает при выполнении любой из команд, информация об ошибке логируется и метод возвращает `False`.

## Метод: `stop_video()`

Этот метод останавливает запись видео на устройстве с помощью ADB.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает `True`, если запись видео успешно остановлена, и `False` в противном случае.

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

```python
adb = Adb()
stop_status = adb.stop_video()
if stop_status:
    print("Запись видео успешно остановлена.")
else:
    print("Не удалось остановить запись видео.")
```

### Дополнительная информация

Метод `stop_video()` выполняет команду `adb shell pkill -l SIGINT screenrecord` для остановки записи видео.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`.

## Метод: `record_video()`

Этот метод начинает запись видео на устройстве с помощью ADB.

### Параметры

- `filename` (`str`): Имя файла, в который будет сохранено видео на устройстве.

### Возвращаемое значение

Метод возвращает `True`, если запись видео успешно начата, и `False` в противном случае.

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

```python
adb = Adb()
record_status = adb.record_video("test_video.mp4")
if record_status:
    print("Запись видео успешно начата.")
else:
    print("Не удалось начать запись видео.")
```

### Дополнительная информация

Метод `record_video()` выполняет команду `adb shell screenrecord /sdcard/Movies/{filename}`, чтобы начать запись видео.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`.

## Метод: `reboot()`

Этот метод перезагружает устройство с помощью ADB.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает `True`, если перезагрузка устройства успешно запущена, и `False` в противном случае.

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

```python
adb = Adb()
reboot_status = adb.reboot()
if reboot_status:
    print("Перезагрузка устройства успешно запущена.")
else:
    print("Не удалось запустить перезагрузку устройства.")
```

### Дополнительная информация

Метод `reboot()` выполняет команду `adb shell reboot`, чтобы перезагрузить устройство.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `False`.

## Метод: `get_screen_resolution()`

Этот метод возвращает разрешение экрана устройства с использованием ADB.

### Параметры

Метод не принимает никаких параметров.

### Возвращаемое значение

Метод возвращает кортеж с двумя целыми числами, представляющими ширину и высоту экрана в пикселях. Если при выполнении возникает ошибка, метод возвращает `None`.

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

```python
adb = Adb()
screen_resolution = adb.get_screen_resolution()
if screen_resolution:
    width, height = screen_resolution
    print(f"Разрешение экрана устройства: {width}x{height}.")
else:
    print("Не удалось получить разрешение экрана устройства.")
```

### Дополнительная информация

Метод `get_screen_resolution()` выполняет команду `adb shell wm size`, чтобы получить физическое разрешение экрана устройства.

### Исключения

Метод обрабатывает исключение, которое может возникнуть при попытке выполнить команду ADB. Если исключение возникает, информация об ошибке логируется и метод возвращает `None`.
