@@ -166,12 +166,43 @@ def run_adb_command_bytes(cmd: str, timeout: int = 30) -> bytes:
166166 raise RuntimeError (f"ADB command timed out after { timeout } s: { cmd } " )
167167
168168
169+ def get_appium_driver_for_serial (device_serial : str | None = None ):
170+ """
171+ Retrieve the specific Appium driver instance for the given Android device serial.
172+ Defaults to the global appium_driver if no serial is provided.
173+ """
174+ from Framework .Built_In_Automation .Shared_Resources import BuiltInFunctionSharedResources as Shared_Resources
175+
176+ if not device_serial :
177+ return Shared_Resources .Get_Shared_Variables ("appium_driver" , log = False )
178+
179+ appium_details = Shared_Resources .Get_Shared_Variables ("appium_details" , log = False )
180+ if isinstance (appium_details , dict ):
181+ for name , details in appium_details .items ():
182+ stored_serial = details .get ("serial" )
183+ if stored_serial and (stored_serial == device_serial or stored_serial in device_serial or device_serial in stored_serial ):
184+ return details .get ("driver" )
185+
186+ return None
187+
188+
169189def fetch_xml_and_screenshot (device_serial : str | None = None ) -> tuple [str , bytes ]:
170190 """
171191 Single-function fetch. Primary path uses ONE adb exec-out command to capture
172192 UI XML + PNG (base64) in a single stream. Falls back (still inside this function)
173193 if markers or outputs are invalid.
174194 """
195+ # Try Appium first
196+ try :
197+ appium_driver = get_appium_driver_for_serial (device_serial )
198+ if appium_driver is not None :
199+ xml = appium_driver .page_source
200+ png = appium_driver .get_screenshot_as_png ()
201+ if xml and png :
202+ return xml , png
203+ except Exception :
204+ pass
205+
175206 device_flag = f"-s { device_serial } " if device_serial else ""
176207
177208 SPLIT = "__ZEUZ_SPLIT__"
@@ -206,6 +237,8 @@ def fetch_xml_and_screenshot(device_serial: str | None = None) -> tuple[str, byt
206237 if "<hierarchy" in xml and png .startswith (b"\x89 PNG" ):
207238 return xml , png
208239
240+ return "" , b""
241+
209242
210243@router .get ("/inspect" , response_model = InspectorResponse )
211244async def inspect (device_serial : str | None = None ):
@@ -346,15 +379,21 @@ def capture_ui_dump(device_serial: str | None = None):
346379 """Capture the current UI hierarchy from the device"""
347380 # Try to get from active Appium driver first (like web does)
348381 try :
349- from Framework . Built_In_Automation . Mobile . CrossPlatform . Appium . BuiltInFunctions import appium_driver
382+ appium_driver = get_appium_driver_for_serial ( device_serial )
350383
351384 if appium_driver is not None :
352385 page_src = appium_driver .page_source
353386 with open (UI_XML_PATH , "w" ) as xml_file :
354387 xml_file .write (page_src )
355388 return
356389 except Exception as e :
357- pass
390+ # If Appium driver is active but failed, do NOT fallback to ADB as it will kill the session
391+ try :
392+ appium_driver = get_appium_driver_for_serial (device_serial )
393+ if appium_driver is not None :
394+ return
395+ except Exception :
396+ pass
358397
359398 # Fallback to ADB
360399 device_flag = f"-s { device_serial } " if device_serial else ""
@@ -368,11 +407,9 @@ def capture_ui_dump(device_serial: str | None = None):
368407 if out .startswith ("Error:" ):
369408 return
370409
371- out = run_adb_command (
410+ run_adb_command (
372411 f"{ ADB_PATH } { device_flag } pull /sdcard/ui.xml { UI_XML_PATH } "
373412 )
374- if os .path .exists (UI_XML_PATH ):
375- size = os .path .getsize (UI_XML_PATH )
376413
377414
378415def capture_screenshot (device_serial : str | None = None ):
@@ -496,7 +533,12 @@ async def upload_android_ui_dump():
496533 prev_xml_hash = ""
497534 while True :
498535 try :
499- await asyncio .to_thread (capture_ui_dump )
536+ device_to_capture = None
537+ devices = get_devices ()
538+ if devices :
539+ device_to_capture = devices [0 ].serial
540+
541+ await asyncio .to_thread (capture_ui_dump , device_to_capture )
500542 try :
501543 with open (UI_XML_PATH , "r" ) as xml_file :
502544 xml_content = xml_file .read ()
0 commit comments