Skip to content

Commit 81915f6

Browse files
committed
add support /features, /current_activity
1 parent 234a8b4 commit 81915f6

File tree

4 files changed

+72
-19
lines changed

4 files changed

+72
-19
lines changed

uiautodev/app.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import platform
1010
import signal
1111
from pathlib import Path
12-
from typing import List
12+
from typing import Dict, List
1313

1414
import adbutils
1515
import uvicorn
@@ -25,6 +25,7 @@
2525
from uiautodev.model import Node
2626
from uiautodev.provider import AndroidProvider, HarmonyProvider, IOSProvider, MockProvider
2727
from uiautodev.remote.scrcpy import ScrcpyServer
28+
from uiautodev.router.android import router as android_device_router
2829
from uiautodev.router.device import make_router
2930
from uiautodev.router.xml import router as xml_router
3031
from uiautodev.utils.envutils import Environment
@@ -68,7 +69,23 @@ def enable_logger_to_console():
6869
app.include_router(harmony_router, prefix="/api/harmony", tags=["harmony"])
6970

7071
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
7289

7390
class InfoResponse(BaseModel):
7491
version: str

uiautodev/driver/android.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ def __init__(self, serial: str):
3131
@cached_property
3232
def ud(self) -> u2.Device:
3333
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 ""
3443

3544
def screenshot(self, id: int) -> Image.Image:
3645
if id > 0:

uiautodev/router/android.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
import io
88
import logging
9-
from typing import Any, Dict, List
9+
from typing import Any, Dict, List, Optional
1010

11-
from fastapi import APIRouter, Response
11+
from fastapi import APIRouter, Query, Request, Response
1212
from fastapi.responses import StreamingResponse
1313
from pydantic import BaseModel
1414

@@ -19,9 +19,6 @@
1919

2020
logger = logging.getLogger(__name__)
2121

22-
class AndroidShellPayload(BaseModel):
23-
command: str
24-
2522

2623
def make_router(provider: BaseProvider) -> APIRouter:
2724
router = APIRouter()
@@ -37,18 +34,6 @@ def _list() -> List[DeviceInfo]:
3734
logger.exception("list_devices failed")
3835
return Response(content=str(e), media_type="text/plain", status_code=500)
3936

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-
5237
@router.get(
5338
"/{serial}/screenshot/{id}",
5439
responses={200: {"content": {"image/jpeg": {}}}},

0 commit comments

Comments
 (0)