Package: anhelper
说明用于android设备远程实时控制的工具整合包。封装了minicap、minicap_sdk32、minitouch、ADBKeyboard的预编译包支持多线程（threading）中资源自动分配，但应避免在多进程（multiprocessing）中使用支持多设备连接支持安卓设备的实时截图(延迟约30~40ms)支持修改分辨率支持监听屏幕旋转支持监听输入框弹出内置触控点坐标变换支持中文输入包含一个远程控制demo支持安卓系统版本android<=12, sdk<=32适用场景有一定实时性要求的安卓游戏自动控制项目需要从不同线程控制、获取屏幕内容的多线程项目安装pipinstallanhelperDemo运行demo需要确保已经通过adb连接安卓设备anhelper-demo已知问题实体机上可能存在输入设备写入权限问题，导致minitouch无法运行。需要adb获取root权限。部分机器需要手动在设置中开启ADBKeyboard并且手动切换输入法才可用。用于安卓控制的同类开源项目推荐uiautomator2scrcpyQtScrcpyminidevice在python项目中使用Devicefromanhelperimportdevicedevice.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']}# 通过网络连接设备device.connectDevice('127.0.0.1',port=16416)Truedevice.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']}# 获取adb连接的第一个设备# getDevice已对多线程进行了优化，不同线程中调用不会重复构建实例dev=device.getDevice()# 检查是否处于输入法输入状态dev.getIMEInputActive()False# 获取屏幕显示参数dev.getWM(){'width': 1280, 'height': 720, 'density': 240}%%time# 获取屏幕方向（顺时针旋转）dev.getOrientation()CPU times: total: 0 ns
Wall time: 86.9 ms





0# 修改分辨率dev.setWM(720,1280,fit_orientation=True)dev.getWM(){'width': 1280, 'height': 720, 'density': 240}dev.setWM(**device.CONST.TABLET_720P,fit_orientation=True)dev.getWM(){'width': 1280, 'height': 720, 'density': 240}imefromanhelperimportime# 获取默认设备的ADBKeyboard输入法对象mime=ime.getIME()# 检查ADBKeyboard是否是默认输入法mime.getSelected()False%%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'%%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 -...>## 多设备mime2=ime.getIME(list(device.listDevices().keys())[1])mime2.input('再见')<Popen: returncode: None args: 'adb -s 127.0.0.1:21513 shell "am broadcast -...>Minicapfromanhelperimportminicapfromanhelper.utils.visualizehelperimport*# 获取默认设备的minicap输入法对象mcap=minicap.getMinicap()# 截图默认返回cv2格式BGR矩阵# sync=True 获取当前时间之后的第一帧imat=mcap.cap(sync=True)imshow(imat)%%time# 对于静态画面minicap不会发送新的帧，所以同步截图设置了1秒超时imat=mcap.cap(sync=True)CPU times: total: 15.6 ms
Wall time: 37.1 ms%%time# sync=False 跳过等待直接从缓存中取帧imat=mcap.cap(sync=False)CPU times: total: 15.6 ms
Wall time: 15.6 ms# 用完记得关mcap.close()Minitouchfromanhelperimportminitouchimporttime# 获取默认设备的minicap输入法对象touch=minitouch.getMinitouch()%%time# 由于触控设备通常支持多个触控点，使用useContact()自动分配触控点，以避免冲突# 所有的触控操作推荐使用比例坐标而非绝对坐标# 比例坐标：x = 绝对坐标x/屏幕宽度, y=绝对坐标y/屏幕高度, 0 <= x,y <= 1withtouch.useContact()asc:c.swipe(0.5,0.2,0.5,0.4,duration_ms=3000)print(c.id)withtouch.useContact()asc: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%%time# 同一个触控点的操作会覆盖掉上一个操作未完成的部分withtouch.useContact()asc: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%%timewithtouch.useContact()asc:c.swipe(0.5,0.4,0.5,0.6,duration_ms=3000)CPU times: total: 46.9 ms
Wall time: 53.7 ms%%timewithtouch.useContact()asc:c.tap(0.9,0.7)CPU times: total: 0 ns
Wall time: 976 µs# 绝对坐标也可以使用但不推荐，坐标原点为旋转后的屏幕左上角，与截图坐标一致withtouch.useContact()asc:c.tap(700,500)# 用完记得关touch.close()WebUI（Demo）fromanhelperimportwebuifromIPython.displayimportIFrame# 创建一个webui，绑定默认设备（连接的第一个），可以使用不同的device_id来绑定不同设备# webui可以在网页中同步显示设备屏幕的内容# divice_id 可以通过 device.listDevices()获取ui=webui.WebUI(device_id=None)ui.start()# 检查webui是否正在运行ui.is_alive()TrueIFrame(ui.url,width='100%',height='400px')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 -ui2=webui.WebUI(device_id=None,port=5001)ui2.start()ui2.is_alive()TrueIFrame(ui2.url,width='100%',height='400px')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 -# 关闭webui# 多个webui可以指向同一个设备，可以分别创建和关闭ui2.stop()ui.stop()包含开源项目许可声明minicapminitouchADBKeyBoardvuepure.cssfontawesomeNone