Skip to content

Commit f99a5c8

Browse files
mdshakib007mdshakib007
andauthored
Proper UI dump upload handling for mobile (#672)
* Refactor UI dump upload handling to start uploads in the background on server startup * Enhance UI dump capture by prioritizing Appium driver output and now we are using hash for track changes on dom --------- Co-authored-by: mdshakib007 <shakib@mail.com>
1 parent fcdc77e commit f99a5c8

3 files changed

Lines changed: 57 additions & 31 deletions

File tree

node_cli.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
from Framework.install_handler.android.java import update_java_path
3939
from settings import ZEUZ_NODE_PRIVATE_RSA_KEYS_DIR
4040
from Framework.install_handler.long_poll_handler import InstallHandler
41-
from server.mobile import upload_android_ui_dump, upload_ios_ui_dump
41+
from server.mobile import start_ui_dump_uploads
4242
from Framework.install_handler.android.android_sdk import update_android_sdk_path
4343

4444
def adjust_python_path():
@@ -1347,8 +1347,7 @@ async def main():
13471347
update_android_sdk_path()
13481348
update_outdated_modules()
13491349
asyncio.create_task(start_server())
1350-
asyncio.create_task(upload_android_ui_dump())
1351-
asyncio.create_task(upload_ios_ui_dump())
1350+
start_ui_dump_uploads()
13521351
asyncio.create_task(delete_old_automationlog_folders())
13531352
await destroy_session()
13541353

server/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from server.connect import router as connect_router
99
from server.evaluator import router as evaluator_router
1010
from server.node_operator import router as operator_router
11-
from server.mobile import router as mobile_router, upload_android_ui_dump
11+
from server.mobile import router as mobile_router, start_ui_dump_uploads
1212
from server.mac import router as mac_router
1313
from server.linux import router as linux_router
1414
from server.installers import router as installers_router
@@ -45,6 +45,10 @@ def main() -> FastAPI:
4545
v1router.include_router(linux_router)
4646
v1router.include_router(installers_router)
4747
app = FastAPI()
48+
49+
@app.on_event("startup")
50+
async def _start_background_uploads():
51+
start_ui_dump_uploads()
4852
app.include_router(v1router)
4953

5054
origins = [

server/mobile.py

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@
2929

3030
router = APIRouter(prefix="/mobile", tags=["mobile"])
3131

32+
_UPLOAD_TASKS_STARTED = False
33+
34+
35+
def start_ui_dump_uploads() -> None:
36+
"""Start background UI dump uploads once per process."""
37+
global _UPLOAD_TASKS_STARTED
38+
if _UPLOAD_TASKS_STARTED:
39+
return
40+
_UPLOAD_TASKS_STARTED = True
41+
asyncio.create_task(upload_android_ui_dump())
42+
asyncio.create_task(upload_ios_ui_dump())
43+
3244

3345
def is_wda_running(port: int) -> bool:
3446
"""Check if WebDriverAgent is running on given port."""
@@ -332,26 +344,35 @@ def run_adb_command(command):
332344

333345
def capture_ui_dump(device_serial: str | None = None):
334346
"""Capture the current UI hierarchy from the device"""
347+
# Try to get from active Appium driver first (like web does)
348+
try:
349+
from Framework.Built_In_Automation.Mobile.CrossPlatform.Appium.BuiltInFunctions import appium_driver
350+
351+
if appium_driver is not None:
352+
page_src = appium_driver.page_source
353+
with open(UI_XML_PATH, "w") as xml_file:
354+
xml_file.write(page_src)
355+
return
356+
except Exception as e:
357+
pass
358+
359+
# Fallback to ADB
335360
device_flag = f"-s {device_serial}" if device_serial else ""
361+
362+
if os.path.exists(UI_XML_PATH):
363+
os.remove(UI_XML_PATH)
364+
336365
out = run_adb_command(
337366
f"{ADB_PATH} {device_flag} shell uiautomator dump /sdcard/ui.xml".strip()
338367
)
339368
if out.startswith("Error:"):
340-
from Framework.Built_In_Automation.Mobile.CrossPlatform.Appium.BuiltInFunctions import (
341-
appium_driver,
342-
)
343-
344-
if appium_driver is None:
345-
return
346-
page_src = appium_driver.page_source
347-
with open(UI_XML_PATH, "w") as xml_file:
348-
xml_file.write(page_src)
349-
else:
350-
out = run_adb_command(
351-
f"{ADB_PATH} {device_flag} pull /sdcard/ui.xml {UI_XML_PATH}"
352-
)
353-
if out.startswith("Error:"):
354-
return
369+
return
370+
371+
out = run_adb_command(
372+
f"{ADB_PATH} {device_flag} pull /sdcard/ui.xml {UI_XML_PATH}"
373+
)
374+
if os.path.exists(UI_XML_PATH):
375+
size = os.path.getsize(UI_XML_PATH)
355376

356377

357378
def capture_screenshot(device_serial: str | None = None):
@@ -444,6 +465,19 @@ def get_real_ios_hierarchy(device_udid: str):
444465

445466

446467
def capture_ios_ui_dump(device_udid: str):
468+
# Try to get from active Appium driver first (like web does)
469+
try:
470+
from Framework.Built_In_Automation.Mobile.CrossPlatform.Appium.BuiltInFunctions import appium_driver
471+
472+
if appium_driver is not None:
473+
page_src = appium_driver.page_source
474+
with open(IOS_XML_PATH, 'w', encoding='utf-8') as xml_file:
475+
xml_file.write(page_src)
476+
return
477+
except Exception as e:
478+
pass
479+
480+
# Fallback to WDA
447481
real_hierarchy = get_real_ios_hierarchy(device_udid)
448482
if real_hierarchy:
449483
try:
@@ -456,17 +490,6 @@ def capture_ios_ui_dump(device_udid: str):
456490
with open(IOS_XML_PATH, 'w', encoding='utf-8') as xml_file:
457491
xml_file.write(xml_content)
458492
return
459-
460-
# Fallback to Appium driver
461-
try:
462-
from Framework.Built_In_Automation.Mobile.CrossPlatform.Appium.BuiltInFunctions import appium_driver
463-
if appium_driver is not None:
464-
page_src = appium_driver.page_source
465-
with open(IOS_XML_PATH, 'w', encoding='utf-8') as xml_file:
466-
xml_file.write(page_src)
467-
return
468-
except:
469-
pass
470493

471494

472495
async def upload_android_ui_dump():
@@ -778,4 +801,4 @@ def is_ios_app_installed(sim_udid: str, bundle_id: str):
778801

779802
return {"installed": False}
780803
except Exception as e:
781-
return {"installed": False, "error": str(e)}
804+
return {"installed": False, "error": str(e)}

0 commit comments

Comments
 (0)