2929
3030router = 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
3345def 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
333345def 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
357378def capture_screenshot (device_serial : str | None = None ):
@@ -444,6 +465,19 @@ def get_real_ios_hierarchy(device_udid: str):
444465
445466
446467def 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
472495async 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