uiautodev 0.7.1__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uiautodev/__init__.py +1 -1
- uiautodev/app.py +19 -2
- uiautodev/driver/android.py +9 -0
- uiautodev/router/android.py +42 -0
- uiautodev/router/device.py +2 -17
- {uiautodev-0.7.1.dist-info → uiautodev-0.8.0.dist-info}/METADATA +8 -7
- {uiautodev-0.7.1.dist-info → uiautodev-0.8.0.dist-info}/RECORD +10 -9
- {uiautodev-0.7.1.dist-info → uiautodev-0.8.0.dist-info}/LICENSE +0 -0
- {uiautodev-0.7.1.dist-info → uiautodev-0.8.0.dist-info}/WHEEL +0 -0
- {uiautodev-0.7.1.dist-info → uiautodev-0.8.0.dist-info}/entry_points.txt +0 -0
uiautodev/__init__.py
CHANGED
uiautodev/app.py
CHANGED
|
@@ -9,7 +9,7 @@ import os
|
|
|
9
9
|
import platform
|
|
10
10
|
import signal
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import List
|
|
12
|
+
from typing import Dict, List
|
|
13
13
|
|
|
14
14
|
import adbutils
|
|
15
15
|
import uvicorn
|
|
@@ -25,6 +25,7 @@ from uiautodev.common import convert_bytes_to_image, get_webpage_url, ocr_image
|
|
|
25
25
|
from uiautodev.model import Node
|
|
26
26
|
from uiautodev.provider import AndroidProvider, HarmonyProvider, IOSProvider, MockProvider
|
|
27
27
|
from uiautodev.remote.scrcpy import ScrcpyServer
|
|
28
|
+
from uiautodev.router.android import router as android_device_router
|
|
28
29
|
from uiautodev.router.device import make_router
|
|
29
30
|
from uiautodev.router.xml import router as xml_router
|
|
30
31
|
from uiautodev.utils.envutils import Environment
|
|
@@ -68,7 +69,23 @@ else:
|
|
|
68
69
|
app.include_router(harmony_router, prefix="/api/harmony", tags=["harmony"])
|
|
69
70
|
|
|
70
71
|
app.include_router(xml_router, prefix="/api/xml", tags=["xml"])
|
|
71
|
-
|
|
72
|
+
app.include_router(android_device_router, prefix="/api/android", tags=["android"])
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@app.get('/api/{platform}/features')
|
|
76
|
+
def get_features(platform: str) -> Dict[str, bool]:
|
|
77
|
+
"""Get features supported by the specified platform"""
|
|
78
|
+
features = {}
|
|
79
|
+
# 获取所有带有指定平台tag的路由
|
|
80
|
+
for route in app.routes:
|
|
81
|
+
if hasattr(route, 'tags') and platform in route.tags:
|
|
82
|
+
if route.path.startswith(f"/api/{platform}/{{serial}}/"):
|
|
83
|
+
# 提取特性名称
|
|
84
|
+
parts = route.path.split('/')
|
|
85
|
+
feature_name = parts[-1]
|
|
86
|
+
if not feature_name.startswith('{'):
|
|
87
|
+
features[feature_name] = True
|
|
88
|
+
return features
|
|
72
89
|
|
|
73
90
|
class InfoResponse(BaseModel):
|
|
74
91
|
version: str
|
uiautodev/driver/android.py
CHANGED
|
@@ -31,6 +31,15 @@ class AndroidDriver(BaseDriver):
|
|
|
31
31
|
@cached_property
|
|
32
32
|
def ud(self) -> u2.Device:
|
|
33
33
|
return u2.connect_usb(self.serial)
|
|
34
|
+
|
|
35
|
+
def get_current_activity(self) -> str:
|
|
36
|
+
ret = self.adb_device.shell2(["dumpsys", "activity", "activities"], rstrip=True, timeout=5)
|
|
37
|
+
# 使用正则查找包含前台 activity 的行
|
|
38
|
+
match = re.search(r"mResumedActivity:.*? ([\w\.]+\/[\w\.]+)", ret.output)
|
|
39
|
+
if match:
|
|
40
|
+
return match.group(1) # 返回包名/类名,例如 com.example/.MainActivity
|
|
41
|
+
else:
|
|
42
|
+
return ""
|
|
34
43
|
|
|
35
44
|
def screenshot(self, id: int) -> Image.Image:
|
|
36
45
|
if id > 0:
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# prefix for /api/android/{serial}/shell
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Dict, Optional
|
|
5
|
+
|
|
6
|
+
from fastapi import APIRouter, Request, Response
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from uiautodev.driver.android import AndroidDriver
|
|
10
|
+
from uiautodev.model import ShellResponse
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
router = APIRouter()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AndroidShellPayload(BaseModel):
|
|
18
|
+
command: str
|
|
19
|
+
|
|
20
|
+
@router.post("/{serial}/shell")
|
|
21
|
+
def shell(serial: str, payload: AndroidShellPayload) -> ShellResponse:
|
|
22
|
+
"""Run a shell command on an Android device"""
|
|
23
|
+
try:
|
|
24
|
+
driver = AndroidDriver(serial)
|
|
25
|
+
return driver.shell(payload.command)
|
|
26
|
+
except NotImplementedError as e:
|
|
27
|
+
return Response(content="shell not implemented", media_type="text/plain", status_code=501)
|
|
28
|
+
except Exception as e:
|
|
29
|
+
logger.exception("shell failed")
|
|
30
|
+
return ShellResponse(output="", error=str(e))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@router.get("/{serial}/current_activity")
|
|
34
|
+
async def get_current_activity(serial: str) -> Response:
|
|
35
|
+
"""Get the current activity of the Android device"""
|
|
36
|
+
try:
|
|
37
|
+
driver = AndroidDriver(serial)
|
|
38
|
+
activity = driver.get_current_activity()
|
|
39
|
+
return Response(content=activity, media_type="text/plain")
|
|
40
|
+
except Exception as e:
|
|
41
|
+
logger.exception("get_current_activity failed")
|
|
42
|
+
return Response(content="", media_type="text/plain")
|
uiautodev/router/device.py
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
import io
|
|
8
8
|
import logging
|
|
9
|
-
from typing import Any, Dict, List
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
10
|
|
|
11
|
-
from fastapi import APIRouter, Response
|
|
11
|
+
from fastapi import APIRouter, Query, Request, Response
|
|
12
12
|
from fastapi.responses import StreamingResponse
|
|
13
13
|
from pydantic import BaseModel
|
|
14
14
|
|
|
@@ -19,9 +19,6 @@ from uiautodev.provider import BaseProvider
|
|
|
19
19
|
|
|
20
20
|
logger = logging.getLogger(__name__)
|
|
21
21
|
|
|
22
|
-
class AndroidShellPayload(BaseModel):
|
|
23
|
-
command: str
|
|
24
|
-
|
|
25
22
|
|
|
26
23
|
def make_router(provider: BaseProvider) -> APIRouter:
|
|
27
24
|
router = APIRouter()
|
|
@@ -37,18 +34,6 @@ def make_router(provider: BaseProvider) -> APIRouter:
|
|
|
37
34
|
logger.exception("list_devices failed")
|
|
38
35
|
return Response(content=str(e), media_type="text/plain", status_code=500)
|
|
39
36
|
|
|
40
|
-
@router.post("/{serial}/shell")
|
|
41
|
-
def android_shell(serial: str, payload: AndroidShellPayload) -> ShellResponse:
|
|
42
|
-
"""Run a shell command on an Android device"""
|
|
43
|
-
try:
|
|
44
|
-
driver = provider.get_device_driver(serial)
|
|
45
|
-
return driver.shell(payload.command)
|
|
46
|
-
except NotImplementedError as e:
|
|
47
|
-
return Response(content="shell not implemented", media_type="text/plain", status_code=501)
|
|
48
|
-
except Exception as e:
|
|
49
|
-
logger.exception("shell failed")
|
|
50
|
-
return ShellResponse(output="", error=str(e))
|
|
51
|
-
|
|
52
37
|
@router.get(
|
|
53
38
|
"/{serial}/screenshot/{id}",
|
|
54
39
|
responses={200: {"content": {"image/jpeg": {}}}},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: uiautodev
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Mobile UI Automation, include UI hierarchy inspector, script recorder
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: codeskyblue
|
|
@@ -14,19 +14,20 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Requires-Dist: Pillow
|
|
17
18
|
Requires-Dist: adbutils (>=2.8.10,<3)
|
|
18
19
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
19
20
|
Requires-Dist: construct
|
|
20
|
-
Requires-Dist: fastapi (
|
|
21
|
+
Requires-Dist: fastapi (==0.115.12)
|
|
21
22
|
Requires-Dist: httpx
|
|
22
23
|
Requires-Dist: lxml
|
|
23
|
-
Requires-Dist: pillow
|
|
24
|
-
Requires-Dist: poetry (>=1.8.2,<2.0.0)
|
|
25
24
|
Requires-Dist: pydantic (>=2.6,<3.0)
|
|
26
25
|
Requires-Dist: pygments (>=2)
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist:
|
|
26
|
+
Requires-Dist: python-multipart (>=0.0.18)
|
|
27
|
+
Requires-Dist: rich
|
|
28
|
+
Requires-Dist: uiautomator2 (>=3.2.0,<4)
|
|
29
|
+
Requires-Dist: uvicorn (>=0.33.0)
|
|
30
|
+
Requires-Dist: wdapy (>0.2.2,<1)
|
|
30
31
|
Requires-Dist: websockets (>=10.4)
|
|
31
32
|
Project-URL: Homepage, https://uiauto.dev
|
|
32
33
|
Description-Content-Type: text/markdown
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
uiautodev/__init__.py,sha256=
|
|
1
|
+
uiautodev/__init__.py,sha256=SAp6OsnyWMoLbq7D6yK6OfsgN5sa4y9ftxiyyiEr2M8,164
|
|
2
2
|
uiautodev/__main__.py,sha256=0WZHyHW-M7FG5RexANNoIB5pkCX8xwQbTnmaOA9Y1kg,176
|
|
3
|
-
uiautodev/app.py,sha256=
|
|
3
|
+
uiautodev/app.py,sha256=7ucK725_44Ns61RF_oGWqtVDumtU4exT6KlYE66AUNE,5397
|
|
4
4
|
uiautodev/appium_proxy.py,sha256=yMzPnIDo50hYSaq0g5bXUpgRrFa_849wNa2o7ZpxGNY,1773
|
|
5
5
|
uiautodev/binaries/scrcpy_server.jar,sha256=ojxWWfNsJg8QXAItJ7yz6v_6JgcOe6qe2mbQE3ehrbo,71200
|
|
6
6
|
uiautodev/case.py,sha256=Jk2_5X2F-XIPnGuYTCqOVQiwwchwOhF7uKK5oKv5shg,3919
|
|
@@ -8,7 +8,7 @@ uiautodev/cli.py,sha256=nqxVTaNkItIN5REGEgVPFr0JWxPmeIPz_tZvFQNU7Jc,5442
|
|
|
8
8
|
uiautodev/command_proxy.py,sha256=C9z-dITMED4k5na45NMdEWAXlLh3Ll921mKuefFyk78,5226
|
|
9
9
|
uiautodev/command_types.py,sha256=pWdnCS4FRnEIiR1ynd4cjXX8zeFndjPztacBlukt61E,1761
|
|
10
10
|
uiautodev/common.py,sha256=1A0kXfxVrp_i5mc_aRjuqSDWFFZ7DwZR9qpRLu2GMMg,1488
|
|
11
|
-
uiautodev/driver/android.py,sha256=
|
|
11
|
+
uiautodev/driver/android.py,sha256=WCCplvjjcS8FQerv8OZe5MSgHXm03EfqdnZpVyuXApc,6773
|
|
12
12
|
uiautodev/driver/appium.py,sha256=U3TGpOXmu3tEa3E1ttTFoXehOfFyjavJQ3XA4CtqeBE,5308
|
|
13
13
|
uiautodev/driver/base_driver.py,sha256=neoVS9T8MN5RXvW6vvqXSc6pcBW_fqujJurjUrlt0OA,2816
|
|
14
14
|
uiautodev/driver/harmony.py,sha256=93pwlg04wazey8MQM6DEvcBkr52REYVw4bwz321fK38,8031
|
|
@@ -24,15 +24,16 @@ uiautodev/remote/android_input.py,sha256=r9y2SxnDw0GhN44emL-2Nz0UasaVaVtzh53hd-L
|
|
|
24
24
|
uiautodev/remote/keycode.py,sha256=RHSJVfcNY2pelQd7_tcE6T0j3n8CKBkiku7A2AJZUpk,8097
|
|
25
25
|
uiautodev/remote/scrcpy.py,sha256=Iagm9RrdB67KC2fkyyzpCeHYT0VMSQhoBEks1R_bXpo,7380
|
|
26
26
|
uiautodev/remote/touch_controller.py,sha256=dYl5XTLaYEyZiNJmKwHQpw9QhPSkN3iUetJSaiQJBHg,4255
|
|
27
|
-
uiautodev/router/
|
|
27
|
+
uiautodev/router/android.py,sha256=xwzaZduMRJsyml-7eZjNtQMg_c22ZpFAq6TErc_-tlA,1358
|
|
28
|
+
uiautodev/router/device.py,sha256=iNJUexRLUmgGT_n1UgWybX8PvRSDinpoUpvKX-NZi10,4298
|
|
28
29
|
uiautodev/router/xml.py,sha256=MKVLhjMBqE4qbEraQxvdrVp_OBnylEL9Wti5lnmBDk4,891
|
|
29
30
|
uiautodev/static/demo.html,sha256=qC7qUZP5Af9T3V5EuFGbovzv8mArwiGMWsX_vcs_Bt0,1240
|
|
30
31
|
uiautodev/utils/common.py,sha256=L1qBBBS6jRgkXlGy5o6Xafo49auLXKRWyX9x8U_IKjc,4821
|
|
31
32
|
uiautodev/utils/envutils.py,sha256=Clyt2Hz9PXpK_fT0yWbMmixXyGvCaJO3LAgamM7aUVc,197
|
|
32
33
|
uiautodev/utils/exceptions.py,sha256=lL_G_E41KWvfXnl32-E4Vgr3_HyTboxq_EwzdQMuvK4,637
|
|
33
34
|
uiautodev/utils/usbmux.py,sha256=LYupLDn7U4KFKhYQJrmIroS-3040gqZQVDRDB_FNDJM,17386
|
|
34
|
-
uiautodev-0.
|
|
35
|
-
uiautodev-0.
|
|
36
|
-
uiautodev-0.
|
|
37
|
-
uiautodev-0.
|
|
38
|
-
uiautodev-0.
|
|
35
|
+
uiautodev-0.8.0.dist-info/LICENSE,sha256=RyeW676gBYO7AVVP2zQgfEx5rPSt46vR47xXZe7TlX4,1068
|
|
36
|
+
uiautodev-0.8.0.dist-info/METADATA,sha256=8BZJQyX_F7kZK8-S9vTSD2M2OD-M9piuH9uZRZi23g8,2805
|
|
37
|
+
uiautodev-0.8.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
38
|
+
uiautodev-0.8.0.dist-info/entry_points.txt,sha256=zBY8GgseYAAzPFA5Cf4rCCS9ivdyWsNxMVVYIaGAHJU,88
|
|
39
|
+
uiautodev-0.8.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|