anhelper


Nameanhelper JSON
Version 0.1.6 PyPI version JSON
download
home_pagehttps://github.com/zlolss/AnHelper
Summaryscreencap, touch, remote control for android devices via adb
upload_time2024-01-07 12:15:35
maintainer
docs_urlNone
authorzlols
requires_python>=3.0.0
licenseMIT license
keywords test
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 说明
用于android设备远程实时控制的工具整合包。
- 封装了[minicap](https://github.com/bbsvip/minicap_minitouch_prebuilt/tree/main) 、 [minicap_sdk32](https://github.com/UrielCh/minicap-prebuilt)、 [minitouch](https://github.com/bbsvip/minicap_minitouch_prebuilt/tree/main) 、[ADBKeyboard](https://github.com/senzhk/ADBKeyBoard) 的预编译包
- 支持多线程(threading)中资源自动分配,但应避免在多进程(multiprocessing)中使用
- 支持多设备连接
- 支持安卓设备的实时截图(延迟约30~40ms)
- 支持修改分辨率
- 支持监听屏幕旋转
- 支持监听输入框弹出
- 内置触控点坐标变换
- 支持中文输入
- 包含一个远程控制demo
- 支持安卓系统版本android<=12, sdk<=32

# 适用场景
- 有一定实时性要求的安卓游戏自动控制项目
- 需要从不同线程控制、获取屏幕内容的多线程项目

# 安装

```shell
pip install anhelper
```

# Demo
运行demo需要确保已经通过adb连接安卓设备

```shell
anhelper-demo
```

# 已知问题
- 实体机上可能存在输入设备写入权限问题,导致minitouch无法运行。需要adb获取root权限。
- 部分机器需要手动在设置中开启ADBKeyboard并且手动切换输入法才可用。

# 用于安卓控制的同类开源项目推荐
- [uiautomator2](https://github.com/openatx/uiautomator2)
- [scrcpy](https://github.com/Genymobile/scrcpy)
- [QtScrcpy](https://github.com/barry-ran/QtScrcpy)
- [minidevice](https://github.com/NakanoSanku/minidevice/tree/dev)


# 在python项目中使用

## Device


```python
from anhelper import device
device.listDevices()
```




    {'127.0.0.1:16416': ['device',
      'product:SDY-AN00',
      'model:SDY_AN00',
      'device:SDY-AN00',
      'transport_id:24'],
     '127.0.0.1:21513': ['device',
      'product:SM-S9010',
      'model:SM_S9010',
      'device:SM-S9010',
      'transport_id:23']}




```python
# 通过网络连接设备
device.connectDevice('127.0.0.1', port=16416)
```




    True




```python
device.listDevices()
```




    {'127.0.0.1:16416': ['device',
      'product:SDY-AN00',
      'model:SDY_AN00',
      'device:SDY-AN00',
      'transport_id:24'],
     '127.0.0.1:21513': ['device',
      'product:SM-S9010',
      'model:SM_S9010',
      'device:SM-S9010',
      'transport_id:23']}




```python
# 获取adb连接的第一个设备
# getDevice已对多线程进行了优化,不同线程中调用不会重复构建实例
dev = device.getDevice()
```


```python
# 检查是否处于输入法输入状态
dev.getIMEInputActive()
```




    False




```python
# 获取屏幕显示参数
dev.getWM()
```




    {'width': 1280, 'height': 720, 'density': 240}




```python
%%time
# 获取屏幕方向(顺时针旋转)
dev.getOrientation()
```

    CPU times: total: 0 ns
    Wall time: 86.9 ms
    




    0




```python
# 修改分辨率
dev.setWM(720, 1280, fit_orientation = True)
dev.getWM()
```




    {'width': 1280, 'height': 720, 'density': 240}




```python
dev.setWM(**device.CONST.TABLET_720P, fit_orientation = True)
dev.getWM()
```




    {'width': 1280, 'height': 720, 'density': 240}



## ime


```python
from anhelper import ime
# 获取默认设备的ADBKeyboard输入法对象
mime = ime.getIME()
```


```python
# 检查ADBKeyboard是否是默认输入法
mime.getSelected()
```




    False




```python
%%time
# 等待输入完成
mime.inputSafe('你好')
```

    正在安装ADBkeyboard。。。ok
    CPU times: total: 15.6 ms
    Wall time: 540 ms
    




    'Broadcasting: Intent { act=ADB_INPUT_B64 flg=0x400000 (has extras) }\r\nBroadcast completed: result=0'




```python
%%time
# 输入且不等待完成
mime.input('你好')
```

    CPU times: total: 15.6 ms
    Wall time: 3.91 ms
    




    <Popen: returncode: None args: 'adb -s 127.0.0.1:16416 shell "am broadcast -...>




```python
## 多设备
mime2 = ime.getIME(list(device.listDevices().keys())[1])
mime2.input('再见')
```




    <Popen: returncode: None args: 'adb -s 127.0.0.1:21513 shell "am broadcast -...>



## Minicap


```python
from anhelper import minicap
from anhelper.utils.visualizehelper import *
# 获取默认设备的minicap输入法对象
mcap = minicap.getMinicap()
```


```python
# 截图默认返回cv2格式BGR矩阵
# sync=True 获取当前时间之后的第一帧
imat = mcap.cap(sync = True)
imshow(imat)
```


    
![png](doc/output_19_0.png)
    



```python
%%time
# 对于静态画面minicap不会发送新的帧,所以同步截图设置了1秒超时
imat = mcap.cap(sync=True)

```

    CPU times: total: 15.6 ms
    Wall time: 37.1 ms
    


```python
%%time
# sync=False 跳过等待直接从缓存中取帧
imat = mcap.cap(sync=False)
```

    CPU times: total: 15.6 ms
    Wall time: 15.6 ms
    


```python
# 用完记得关
mcap.close()
```

## Minitouch


```python
from anhelper import minitouch
import time
# 获取默认设备的minicap输入法对象
touch = minitouch.getMinitouch()
```


```python
%%time
# 由于触控设备通常支持多个触控点,使用useContact()自动分配触控点,以避免冲突
# 所有的触控操作推荐使用比例坐标而非绝对坐标
# 比例坐标:x = 绝对坐标x/屏幕宽度, y=绝对坐标y/屏幕高度, 0 <= x,y <= 1
with touch.useContact() as c:
    c.swipe(0.5,0.2, 0.5, 0.4, duration_ms=3000)
    print(c.id)
    
with touch.useContact() as c:
    print(c.id)
    c.tap(1000, 500)
    c.tap(0.5, 0.5)

```

    正在部署minitouch。。。ok
    9
    8
    CPU times: total: 78.1 ms
    Wall time: 1.94 s
    


```python
%%time
# 同一个触控点的操作会覆盖掉上一个操作未完成的部分
with touch.useContact() as c:
    c.swipe(0.5,0.2, 0.5, 0.4, duration_ms=3000)
    time.sleep(2)
    print(c.inuse)
    c.swipe(0.5,0.2, 0.5, 0.4, duration_ms=3000)
```

    True
    CPU times: total: 78.1 ms
    Wall time: 2.01 s
    


```python
%%time
with touch.useContact() as c:
    c.swipe(0.5, 0.4, 0.5, 0.6, duration_ms=3000)
```

    CPU times: total: 46.9 ms
    Wall time: 53.7 ms
    


```python
%%time
with touch.useContact() as c:
    c.tap(0.9, 0.7)

```

    CPU times: total: 0 ns
    Wall time: 976 µs
    


```python
# 绝对坐标也可以使用但不推荐,坐标原点为旋转后的屏幕左上角,与截图坐标一致
with touch.useContact() as c:
    c.tap(700, 500)
```


```python
# 用完记得关
touch.close()
```

## WebUI(Demo)


```python
from anhelper import webui
from IPython.display import IFrame
```


```python
# 创建一个webui,绑定默认设备(连接的第一个),可以使用不同的device_id来绑定不同设备
# webui可以在网页中同步显示设备屏幕的内容
# divice_id 可以通过 device.listDevices()获取
ui = webui.WebUI(device_id=None)
ui.start()
```


```python
# 检查webui是否正在运行
ui.is_alive()
```




    True




```python
IFrame( ui.url, width='100%',height='400px')
```



![png](doc/page1.png)




    127.0.0.1 - - [29/Jul/2023 23:56:15] "GET / HTTP/1.1" 200 -
    

    正在部署minicap。。。ok
   

    127.0.0.1 - - [29/Jul/2023 23:56:16] "GET /video_feed HTTP/1.1" 200 -
    


```python
ui2 = webui.WebUI(device_id=None, port=5001)
ui2.start()
```


```python
ui2.is_alive()
```




    True




```python
IFrame( ui2.url, width='100%',height='400px')
```





![png](doc/page2.png)




    127.0.0.1 - - [29/Jul/2023 23:56:20] "GET / HTTP/1.1" 200 -
    127.0.0.1 - - [29/Jul/2023 23:56:20] "GET /video_feed HTTP/1.1" 200 -
    


```python
# 关闭webui
# 多个webui可以指向同一个设备,可以分别创建和关闭
ui2.stop()
```


```python
ui.stop()
```


```python

```

# 包含开源项目许可声明

[minicap](https://github.com/DeviceFarmer/minicap/blob/master/LICENSE)

[minitouch](https://github.com/DeviceFarmer/minitouch/blob/master/LICENSE)

[ADBKeyBoard](https://github.com/senzhk/ADBKeyBoard/blob/master/LICENSE)

[vue](https://github.com/vuejs/core/blob/main/LICENSE)

[pure.css](https://github.com/pure-css/pure/blob/master/LICENSE)

[fontawesome](https://fontawesome.com/license/free)

None

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/zlolss/AnHelper",
    "name": "anhelper",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.0.0",
    "maintainer_email": "",
    "keywords": "test",
    "author": "zlols",
    "author_email": "zlols@foxmail.com",
    "download_url": "https://files.pythonhosted.org/packages/bb/ed/7f47e69844ddca147eaac7829827cef91783f416ca812cfbf4f0e69dd6c4/anhelper-0.1.6.tar.gz",
    "platform": null,
    "description": "# \u8bf4\u660e\r\n\u7528\u4e8eandroid\u8bbe\u5907\u8fdc\u7a0b\u5b9e\u65f6\u63a7\u5236\u7684\u5de5\u5177\u6574\u5408\u5305\u3002\r\n- \u5c01\u88c5\u4e86[minicap](https://github.com/bbsvip/minicap_minitouch_prebuilt/tree/main) \u3001 [minicap_sdk32](https://github.com/UrielCh/minicap-prebuilt)\u3001 [minitouch](https://github.com/bbsvip/minicap_minitouch_prebuilt/tree/main) \u3001[ADBKeyboard](https://github.com/senzhk/ADBKeyBoard) \u7684\u9884\u7f16\u8bd1\u5305\r\n- \u652f\u6301\u591a\u7ebf\u7a0b\uff08threading\uff09\u4e2d\u8d44\u6e90\u81ea\u52a8\u5206\u914d\uff0c\u4f46\u5e94\u907f\u514d\u5728\u591a\u8fdb\u7a0b\uff08multiprocessing\uff09\u4e2d\u4f7f\u7528\r\n- \u652f\u6301\u591a\u8bbe\u5907\u8fde\u63a5\r\n- \u652f\u6301\u5b89\u5353\u8bbe\u5907\u7684\u5b9e\u65f6\u622a\u56fe(\u5ef6\u8fdf\u7ea630~40ms)\r\n- \u652f\u6301\u4fee\u6539\u5206\u8fa8\u7387\r\n- \u652f\u6301\u76d1\u542c\u5c4f\u5e55\u65cb\u8f6c\r\n- \u652f\u6301\u76d1\u542c\u8f93\u5165\u6846\u5f39\u51fa\r\n- \u5185\u7f6e\u89e6\u63a7\u70b9\u5750\u6807\u53d8\u6362\r\n- \u652f\u6301\u4e2d\u6587\u8f93\u5165\r\n- \u5305\u542b\u4e00\u4e2a\u8fdc\u7a0b\u63a7\u5236demo\r\n- \u652f\u6301\u5b89\u5353\u7cfb\u7edf\u7248\u672candroid<=12, sdk<=32\r\n\r\n# \u9002\u7528\u573a\u666f\r\n- \u6709\u4e00\u5b9a\u5b9e\u65f6\u6027\u8981\u6c42\u7684\u5b89\u5353\u6e38\u620f\u81ea\u52a8\u63a7\u5236\u9879\u76ee\r\n- \u9700\u8981\u4ece\u4e0d\u540c\u7ebf\u7a0b\u63a7\u5236\u3001\u83b7\u53d6\u5c4f\u5e55\u5185\u5bb9\u7684\u591a\u7ebf\u7a0b\u9879\u76ee\r\n\r\n# \u5b89\u88c5\r\n\r\n```shell\r\npip install anhelper\r\n```\r\n\r\n# Demo\r\n\u8fd0\u884cdemo\u9700\u8981\u786e\u4fdd\u5df2\u7ecf\u901a\u8fc7adb\u8fde\u63a5\u5b89\u5353\u8bbe\u5907\r\n\r\n```shell\r\nanhelper-demo\r\n```\r\n\r\n# \u5df2\u77e5\u95ee\u9898\r\n- \u5b9e\u4f53\u673a\u4e0a\u53ef\u80fd\u5b58\u5728\u8f93\u5165\u8bbe\u5907\u5199\u5165\u6743\u9650\u95ee\u9898\uff0c\u5bfc\u81f4minitouch\u65e0\u6cd5\u8fd0\u884c\u3002\u9700\u8981adb\u83b7\u53d6root\u6743\u9650\u3002\r\n- \u90e8\u5206\u673a\u5668\u9700\u8981\u624b\u52a8\u5728\u8bbe\u7f6e\u4e2d\u5f00\u542fADBKeyboard\u5e76\u4e14\u624b\u52a8\u5207\u6362\u8f93\u5165\u6cd5\u624d\u53ef\u7528\u3002\r\n\r\n# \u7528\u4e8e\u5b89\u5353\u63a7\u5236\u7684\u540c\u7c7b\u5f00\u6e90\u9879\u76ee\u63a8\u8350\r\n- [uiautomator2](https://github.com/openatx/uiautomator2)\r\n- [scrcpy](https://github.com/Genymobile/scrcpy)\r\n- [QtScrcpy](https://github.com/barry-ran/QtScrcpy)\r\n- [minidevice](https://github.com/NakanoSanku/minidevice/tree/dev)\r\n\r\n\r\n# \u5728python\u9879\u76ee\u4e2d\u4f7f\u7528\r\n\r\n## Device\r\n\r\n\r\n```python\r\nfrom anhelper import device\r\ndevice.listDevices()\r\n```\r\n\r\n\r\n\r\n\r\n    {'127.0.0.1:16416': ['device',\r\n      'product:SDY-AN00',\r\n      'model:SDY_AN00',\r\n      'device:SDY-AN00',\r\n      'transport_id:24'],\r\n     '127.0.0.1:21513': ['device',\r\n      'product:SM-S9010',\r\n      'model:SM_S9010',\r\n      'device:SM-S9010',\r\n      'transport_id:23']}\r\n\r\n\r\n\r\n\r\n```python\r\n# \u901a\u8fc7\u7f51\u7edc\u8fde\u63a5\u8bbe\u5907\r\ndevice.connectDevice('127.0.0.1', port=16416)\r\n```\r\n\r\n\r\n\r\n\r\n    True\r\n\r\n\r\n\r\n\r\n```python\r\ndevice.listDevices()\r\n```\r\n\r\n\r\n\r\n\r\n    {'127.0.0.1:16416': ['device',\r\n      'product:SDY-AN00',\r\n      'model:SDY_AN00',\r\n      'device:SDY-AN00',\r\n      'transport_id:24'],\r\n     '127.0.0.1:21513': ['device',\r\n      'product:SM-S9010',\r\n      'model:SM_S9010',\r\n      'device:SM-S9010',\r\n      'transport_id:23']}\r\n\r\n\r\n\r\n\r\n```python\r\n# \u83b7\u53d6adb\u8fde\u63a5\u7684\u7b2c\u4e00\u4e2a\u8bbe\u5907\r\n# getDevice\u5df2\u5bf9\u591a\u7ebf\u7a0b\u8fdb\u884c\u4e86\u4f18\u5316\uff0c\u4e0d\u540c\u7ebf\u7a0b\u4e2d\u8c03\u7528\u4e0d\u4f1a\u91cd\u590d\u6784\u5efa\u5b9e\u4f8b\r\ndev = device.getDevice()\r\n```\r\n\r\n\r\n```python\r\n# \u68c0\u67e5\u662f\u5426\u5904\u4e8e\u8f93\u5165\u6cd5\u8f93\u5165\u72b6\u6001\r\ndev.getIMEInputActive()\r\n```\r\n\r\n\r\n\r\n\r\n    False\r\n\r\n\r\n\r\n\r\n```python\r\n# \u83b7\u53d6\u5c4f\u5e55\u663e\u793a\u53c2\u6570\r\ndev.getWM()\r\n```\r\n\r\n\r\n\r\n\r\n    {'width': 1280, 'height': 720, 'density': 240}\r\n\r\n\r\n\r\n\r\n```python\r\n%%time\r\n# \u83b7\u53d6\u5c4f\u5e55\u65b9\u5411\uff08\u987a\u65f6\u9488\u65cb\u8f6c\uff09\r\ndev.getOrientation()\r\n```\r\n\r\n    CPU times: total: 0 ns\r\n    Wall time: 86.9 ms\r\n    \r\n\r\n\r\n\r\n\r\n    0\r\n\r\n\r\n\r\n\r\n```python\r\n# \u4fee\u6539\u5206\u8fa8\u7387\r\ndev.setWM(720, 1280, fit_orientation = True)\r\ndev.getWM()\r\n```\r\n\r\n\r\n\r\n\r\n    {'width': 1280, 'height': 720, 'density': 240}\r\n\r\n\r\n\r\n\r\n```python\r\ndev.setWM(**device.CONST.TABLET_720P, fit_orientation = True)\r\ndev.getWM()\r\n```\r\n\r\n\r\n\r\n\r\n    {'width': 1280, 'height': 720, 'density': 240}\r\n\r\n\r\n\r\n## ime\r\n\r\n\r\n```python\r\nfrom anhelper import ime\r\n# \u83b7\u53d6\u9ed8\u8ba4\u8bbe\u5907\u7684ADBKeyboard\u8f93\u5165\u6cd5\u5bf9\u8c61\r\nmime = ime.getIME()\r\n```\r\n\r\n\r\n```python\r\n# \u68c0\u67e5ADBKeyboard\u662f\u5426\u662f\u9ed8\u8ba4\u8f93\u5165\u6cd5\r\nmime.getSelected()\r\n```\r\n\r\n\r\n\r\n\r\n    False\r\n\r\n\r\n\r\n\r\n```python\r\n%%time\r\n# \u7b49\u5f85\u8f93\u5165\u5b8c\u6210\r\nmime.inputSafe('\u4f60\u597d')\r\n```\r\n\r\n    \u6b63\u5728\u5b89\u88c5ADBkeyboard\u3002\u3002\u3002ok\r\n    CPU times: total: 15.6 ms\r\n    Wall time: 540 ms\r\n    \r\n\r\n\r\n\r\n\r\n    'Broadcasting: Intent { act=ADB_INPUT_B64 flg=0x400000 (has extras) }\\r\\nBroadcast completed: result=0'\r\n\r\n\r\n\r\n\r\n```python\r\n%%time\r\n# \u8f93\u5165\u4e14\u4e0d\u7b49\u5f85\u5b8c\u6210\r\nmime.input('\u4f60\u597d')\r\n```\r\n\r\n    CPU times: total: 15.6 ms\r\n    Wall time: 3.91 ms\r\n    \r\n\r\n\r\n\r\n\r\n    <Popen: returncode: None args: 'adb -s 127.0.0.1:16416 shell \"am broadcast -...>\r\n\r\n\r\n\r\n\r\n```python\r\n## \u591a\u8bbe\u5907\r\nmime2 = ime.getIME(list(device.listDevices().keys())[1])\r\nmime2.input('\u518d\u89c1')\r\n```\r\n\r\n\r\n\r\n\r\n    <Popen: returncode: None args: 'adb -s 127.0.0.1:21513 shell \"am broadcast -...>\r\n\r\n\r\n\r\n## Minicap\r\n\r\n\r\n```python\r\nfrom anhelper import minicap\r\nfrom anhelper.utils.visualizehelper import *\r\n# \u83b7\u53d6\u9ed8\u8ba4\u8bbe\u5907\u7684minicap\u8f93\u5165\u6cd5\u5bf9\u8c61\r\nmcap = minicap.getMinicap()\r\n```\r\n\r\n\r\n```python\r\n# \u622a\u56fe\u9ed8\u8ba4\u8fd4\u56decv2\u683c\u5f0fBGR\u77e9\u9635\r\n# sync=True \u83b7\u53d6\u5f53\u524d\u65f6\u95f4\u4e4b\u540e\u7684\u7b2c\u4e00\u5e27\r\nimat = mcap.cap(sync = True)\r\nimshow(imat)\r\n```\r\n\r\n\r\n    \r\n![png](doc/output_19_0.png)\r\n    \r\n\r\n\r\n\r\n```python\r\n%%time\r\n# \u5bf9\u4e8e\u9759\u6001\u753b\u9762minicap\u4e0d\u4f1a\u53d1\u9001\u65b0\u7684\u5e27\uff0c\u6240\u4ee5\u540c\u6b65\u622a\u56fe\u8bbe\u7f6e\u4e861\u79d2\u8d85\u65f6\r\nimat = mcap.cap(sync=True)\r\n\r\n```\r\n\r\n    CPU times: total: 15.6 ms\r\n    Wall time: 37.1 ms\r\n    \r\n\r\n\r\n```python\r\n%%time\r\n# sync=False \u8df3\u8fc7\u7b49\u5f85\u76f4\u63a5\u4ece\u7f13\u5b58\u4e2d\u53d6\u5e27\r\nimat = mcap.cap(sync=False)\r\n```\r\n\r\n    CPU times: total: 15.6 ms\r\n    Wall time: 15.6 ms\r\n    \r\n\r\n\r\n```python\r\n# \u7528\u5b8c\u8bb0\u5f97\u5173\r\nmcap.close()\r\n```\r\n\r\n## Minitouch\r\n\r\n\r\n```python\r\nfrom anhelper import minitouch\r\nimport time\r\n# \u83b7\u53d6\u9ed8\u8ba4\u8bbe\u5907\u7684minicap\u8f93\u5165\u6cd5\u5bf9\u8c61\r\ntouch = minitouch.getMinitouch()\r\n```\r\n\r\n\r\n```python\r\n%%time\r\n# \u7531\u4e8e\u89e6\u63a7\u8bbe\u5907\u901a\u5e38\u652f\u6301\u591a\u4e2a\u89e6\u63a7\u70b9\uff0c\u4f7f\u7528useContact()\u81ea\u52a8\u5206\u914d\u89e6\u63a7\u70b9\uff0c\u4ee5\u907f\u514d\u51b2\u7a81\r\n# \u6240\u6709\u7684\u89e6\u63a7\u64cd\u4f5c\u63a8\u8350\u4f7f\u7528\u6bd4\u4f8b\u5750\u6807\u800c\u975e\u7edd\u5bf9\u5750\u6807\r\n# \u6bd4\u4f8b\u5750\u6807\uff1ax = \u7edd\u5bf9\u5750\u6807x/\u5c4f\u5e55\u5bbd\u5ea6, y=\u7edd\u5bf9\u5750\u6807y/\u5c4f\u5e55\u9ad8\u5ea6, 0 <= x,y <= 1\r\nwith touch.useContact() as c:\r\n    c.swipe(0.5,0.2, 0.5, 0.4, duration_ms=3000)\r\n    print(c.id)\r\n    \r\nwith touch.useContact() as c:\r\n    print(c.id)\r\n    c.tap(1000, 500)\r\n    c.tap(0.5, 0.5)\r\n\r\n```\r\n\r\n    \u6b63\u5728\u90e8\u7f72minitouch\u3002\u3002\u3002ok\r\n    9\r\n    8\r\n    CPU times: total: 78.1 ms\r\n    Wall time: 1.94 s\r\n    \r\n\r\n\r\n```python\r\n%%time\r\n# \u540c\u4e00\u4e2a\u89e6\u63a7\u70b9\u7684\u64cd\u4f5c\u4f1a\u8986\u76d6\u6389\u4e0a\u4e00\u4e2a\u64cd\u4f5c\u672a\u5b8c\u6210\u7684\u90e8\u5206\r\nwith touch.useContact() as c:\r\n    c.swipe(0.5,0.2, 0.5, 0.4, duration_ms=3000)\r\n    time.sleep(2)\r\n    print(c.inuse)\r\n    c.swipe(0.5,0.2, 0.5, 0.4, duration_ms=3000)\r\n```\r\n\r\n    True\r\n    CPU times: total: 78.1 ms\r\n    Wall time: 2.01 s\r\n    \r\n\r\n\r\n```python\r\n%%time\r\nwith touch.useContact() as c:\r\n    c.swipe(0.5, 0.4, 0.5, 0.6, duration_ms=3000)\r\n```\r\n\r\n    CPU times: total: 46.9 ms\r\n    Wall time: 53.7 ms\r\n    \r\n\r\n\r\n```python\r\n%%time\r\nwith touch.useContact() as c:\r\n    c.tap(0.9, 0.7)\r\n\r\n```\r\n\r\n    CPU times: total: 0 ns\r\n    Wall time: 976 \u00b5s\r\n    \r\n\r\n\r\n```python\r\n# \u7edd\u5bf9\u5750\u6807\u4e5f\u53ef\u4ee5\u4f7f\u7528\u4f46\u4e0d\u63a8\u8350\uff0c\u5750\u6807\u539f\u70b9\u4e3a\u65cb\u8f6c\u540e\u7684\u5c4f\u5e55\u5de6\u4e0a\u89d2\uff0c\u4e0e\u622a\u56fe\u5750\u6807\u4e00\u81f4\r\nwith touch.useContact() as c:\r\n    c.tap(700, 500)\r\n```\r\n\r\n\r\n```python\r\n# \u7528\u5b8c\u8bb0\u5f97\u5173\r\ntouch.close()\r\n```\r\n\r\n## WebUI\uff08Demo\uff09\r\n\r\n\r\n```python\r\nfrom anhelper import webui\r\nfrom IPython.display import IFrame\r\n```\r\n\r\n\r\n```python\r\n# \u521b\u5efa\u4e00\u4e2awebui\uff0c\u7ed1\u5b9a\u9ed8\u8ba4\u8bbe\u5907\uff08\u8fde\u63a5\u7684\u7b2c\u4e00\u4e2a\uff09\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e0d\u540c\u7684device_id\u6765\u7ed1\u5b9a\u4e0d\u540c\u8bbe\u5907\r\n# webui\u53ef\u4ee5\u5728\u7f51\u9875\u4e2d\u540c\u6b65\u663e\u793a\u8bbe\u5907\u5c4f\u5e55\u7684\u5185\u5bb9\r\n# divice_id \u53ef\u4ee5\u901a\u8fc7 device.listDevices()\u83b7\u53d6\r\nui = webui.WebUI(device_id=None)\r\nui.start()\r\n```\r\n\r\n\r\n```python\r\n# \u68c0\u67e5webui\u662f\u5426\u6b63\u5728\u8fd0\u884c\r\nui.is_alive()\r\n```\r\n\r\n\r\n\r\n\r\n    True\r\n\r\n\r\n\r\n\r\n```python\r\nIFrame( ui.url, width='100%',height='400px')\r\n```\r\n\r\n\r\n\r\n![png](doc/page1.png)\r\n\r\n\r\n\r\n\r\n    127.0.0.1 - - [29/Jul/2023 23:56:15] \"GET / HTTP/1.1\" 200 -\r\n    \r\n\r\n    \u6b63\u5728\u90e8\u7f72minicap\u3002\u3002\u3002ok\r\n   \r\n\r\n    127.0.0.1 - - [29/Jul/2023 23:56:16] \"GET /video_feed HTTP/1.1\" 200 -\r\n    \r\n\r\n\r\n```python\r\nui2 = webui.WebUI(device_id=None, port=5001)\r\nui2.start()\r\n```\r\n\r\n\r\n```python\r\nui2.is_alive()\r\n```\r\n\r\n\r\n\r\n\r\n    True\r\n\r\n\r\n\r\n\r\n```python\r\nIFrame( ui2.url, width='100%',height='400px')\r\n```\r\n\r\n\r\n\r\n\r\n\r\n![png](doc/page2.png)\r\n\r\n\r\n\r\n\r\n    127.0.0.1 - - [29/Jul/2023 23:56:20] \"GET / HTTP/1.1\" 200 -\r\n    127.0.0.1 - - [29/Jul/2023 23:56:20] \"GET /video_feed HTTP/1.1\" 200 -\r\n    \r\n\r\n\r\n```python\r\n# \u5173\u95edwebui\r\n# \u591a\u4e2awebui\u53ef\u4ee5\u6307\u5411\u540c\u4e00\u4e2a\u8bbe\u5907\uff0c\u53ef\u4ee5\u5206\u522b\u521b\u5efa\u548c\u5173\u95ed\r\nui2.stop()\r\n```\r\n\r\n\r\n```python\r\nui.stop()\r\n```\r\n\r\n\r\n```python\r\n\r\n```\r\n\r\n# \u5305\u542b\u5f00\u6e90\u9879\u76ee\u8bb8\u53ef\u58f0\u660e\r\n\r\n[minicap](https://github.com/DeviceFarmer/minicap/blob/master/LICENSE)\r\n\r\n[minitouch](https://github.com/DeviceFarmer/minitouch/blob/master/LICENSE)\r\n\r\n[ADBKeyBoard](https://github.com/senzhk/ADBKeyBoard/blob/master/LICENSE)\r\n\r\n[vue](https://github.com/vuejs/core/blob/main/LICENSE)\r\n\r\n[pure.css](https://github.com/pure-css/pure/blob/master/LICENSE)\r\n\r\n[fontawesome](https://fontawesome.com/license/free)\r\n\r\nNone\r\n",
    "bugtrack_url": null,
    "license": "MIT license",
    "summary": "screencap, touch, remote control for android devices via adb",
    "version": "0.1.6",
    "project_urls": {
        "Homepage": "https://github.com/zlolss/AnHelper"
    },
    "split_keywords": [
        "test"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e23c2b5afe224b20be1768a995b8d9617ace31c6d0dc8dd282546dc769042477",
                "md5": "8bba89f47404c708f334005fc1c0a572",
                "sha256": "f1ec0381c8c2cc40bd9b44fc5c9dd640832cf75b5219d4e549919e9f981e68b4"
            },
            "downloads": -1,
            "filename": "anhelper-0.1.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8bba89f47404c708f334005fc1c0a572",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.0.0",
            "size": 7013922,
            "upload_time": "2024-01-07T12:15:29",
            "upload_time_iso_8601": "2024-01-07T12:15:29.325571Z",
            "url": "https://files.pythonhosted.org/packages/e2/3c/2b5afe224b20be1768a995b8d9617ace31c6d0dc8dd282546dc769042477/anhelper-0.1.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bbed7f47e69844ddca147eaac7829827cef91783f416ca812cfbf4f0e69dd6c4",
                "md5": "d187d68ee21b4f113e423fddccb28160",
                "sha256": "c72b4c3815e69215af678b7b318e9d78dcb451e6b17162028698e6d6c201df54"
            },
            "downloads": -1,
            "filename": "anhelper-0.1.6.tar.gz",
            "has_sig": false,
            "md5_digest": "d187d68ee21b4f113e423fddccb28160",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.0.0",
            "size": 6254480,
            "upload_time": "2024-01-07T12:15:35",
            "upload_time_iso_8601": "2024-01-07T12:15:35.046509Z",
            "url": "https://files.pythonhosted.org/packages/bb/ed/7f47e69844ddca147eaac7829827cef91783f416ca812cfbf4f0e69dd6c4/anhelper-0.1.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-07 12:15:35",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "zlolss",
    "github_project": "AnHelper",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "anhelper"
}
        
Elapsed time: 0.82695s