@@ -443,18 +443,21 @@ async def launch(self) -> None:
443443 # 先杀掉可能残留的 APP 和 U2 进程
444444 # Flutter app 如果已在运行且有活跃动画,XPath 策略会因 waitForIdle 卡死
445445 loop = asyncio .get_event_loop ()
446+ adb_pre = ["adb" ]
447+ if self ._config .device_name :
448+ adb_pre .extend (["-s" , self ._config .device_name ])
446449 if self ._config .app_package :
447450 await loop .run_in_executor (
448451 None , lambda : subprocess .run (
449- [ "adb" , "shell" , "am" , "force-stop" , self ._config .app_package ],
452+ adb_pre + [ "shell" , "am" , "force-stop" , self ._config .app_package ],
450453 capture_output = True , timeout = 5 ,
451454 )
452455 )
453456 for u2_pkg in ("io.appium.uiautomator2.server" ,
454457 "io.appium.uiautomator2.server.test" ):
455458 await loop .run_in_executor (
456459 None , lambda pkg = u2_pkg : subprocess .run (
457- [ "adb" , "shell" , "am" , "force-stop" , pkg ],
460+ adb_pre + [ "shell" , "am" , "force-stop" , pkg ],
458461 capture_output = True , timeout = 5 ,
459462 )
460463 )
@@ -483,6 +486,12 @@ async def launch(self) -> None:
483486 self ._device .screen_width = int (parts [0 ])
484487 self ._device .screen_height = int (parts [1 ])
485488 self ._device .is_connected = True
489+ # 保存设备序列号到extra,供adb命令(截图/点击/输入等)使用-s参数
490+ device_udid = caps .get ("deviceUDID" , "" ) or caps .get ("udid" , "" )
491+ if device_udid :
492+ self ._device .extra ["serial" ] = device_udid
493+ elif self ._config .device_name :
494+ self ._device .extra ["serial" ] = self ._config .device_name
486495
487496 logger .info ("Appium Session 创建成功 | ID={} | 设备={}" ,
488497 self ._session_id [:8 ], self ._device .name )
@@ -518,9 +527,10 @@ async def launch(self) -> None:
518527 component = f"{ self ._config .app_package } /{ self ._config .app_activity } "
519528 try :
520529 loop2 = asyncio .get_event_loop ()
530+ _adb_fg = self ._adb_args ()
521531 await loop2 .run_in_executor (
522532 None , lambda : subprocess .run (
523- [ "adb" , "shell" , "am" , "start" , "-n" , component ],
533+ _adb_fg + [ "shell" , "am" , "start" , "-n" , component ],
524534 capture_output = True , timeout = 10 ,
525535 )
526536 )
@@ -644,9 +654,10 @@ async def _rebuild_session_and_launch(
644654 解决 Flutter app 重启后 UiAutomator2 Server 死锁的问题。
645655 """
646656 # 1. adb force-stop 杀掉 app
657+ _adb = self ._adb_args ()
647658 await loop .run_in_executor (
648659 None , lambda : subprocess .run (
649- [ "adb" , "shell" , "am" , "force-stop" , pkg ],
660+ _adb + [ "shell" , "am" , "force-stop" , pkg ],
650661 capture_output = True , timeout = 10 ,
651662 )
652663 )
@@ -669,12 +680,12 @@ async def _rebuild_session_and_launch(
669680 # 新Session会复用死锁的Server,所以必须手动杀掉
670681 def _kill_uia2 ():
671682 subprocess .run (
672- [ "adb" , "shell" , "am" , "force-stop" ,
683+ _adb + [ "shell" , "am" , "force-stop" ,
673684 "io.appium.uiautomator2.server" ],
674685 capture_output = True , timeout = 5 ,
675686 )
676687 subprocess .run (
677- [ "adb" , "shell" , "am" , "force-stop" ,
688+ _adb + [ "shell" , "am" , "force-stop" ,
678689 "io.appium.uiautomator2.server.test" ],
679690 capture_output = True , timeout = 5 ,
680691 )
@@ -723,9 +734,10 @@ def _kill_uia2():
723734 logger .warning ("设置waitForIdleTimeout失败: {}" , e )
724735
725736 # 6. 确保 APP 在前台
737+ _adb2 = self ._adb_args ()
726738 await loop .run_in_executor (
727739 None , lambda : subprocess .run (
728- [ "adb" , "shell" , "am" , "start" , "-n" , component ],
740+ _adb2 + [ "shell" , "am" , "start" , "-n" , component ],
729741 capture_output = True , timeout = 10 ,
730742 )
731743 )
@@ -934,9 +946,10 @@ async def hide_keyboard(self) -> None:
934946 return
935947 loop = asyncio .get_event_loop ()
936948 try :
949+ _adb_kb = self ._adb_args ()
937950 await loop .run_in_executor (
938951 None , lambda : subprocess .run (
939- [ "adb" , "shell" , "input" , "keyevent" , "111" ],
952+ _adb_kb + [ "shell" , "input" , "keyevent" , "111" ],
940953 capture_output = True , timeout = 5 ,
941954 )
942955 )
@@ -1094,9 +1107,9 @@ def _capture():
10941107 # ── Logcat 日志收集 ──────────────────────────────────
10951108
10961109 def _adb_args (self ) -> list [str ]:
1097- """构建带设备序列号的 adb 命令前缀。"""
1110+ """构建带设备序列号的 adb 命令前缀。多设备环境必须带 -s。 """
10981111 cmd = ["adb" ]
1099- serial = self ._config .device_name
1112+ serial = self ._device . extra . get ( "serial" , "" ) or self . _config .device_name
11001113 if serial :
11011114 cmd .extend (["-s" , serial ])
11021115 return cmd
@@ -1556,7 +1569,7 @@ def _is_u2_process_alive(self) -> bool:
15561569 """同步检测设备上 UiAutomator2 Server 进程是否存活。"""
15571570 try :
15581571 r = subprocess .run (
1559- [ "adb" , "shell" , "ps" , "-A" ],
1572+ self . _adb_args () + [ "shell" , "ps" , "-A" ],
15601573 capture_output = True , text = True , timeout = 5 ,
15611574 )
15621575 return "uiautomator" in r .stdout
@@ -1582,11 +1595,12 @@ async def _recover_u2_session(self) -> None:
15821595 self ._session_id = None
15831596
15841597 # 2. 清理残留的 U2 进程
1598+ _adb_r = self ._adb_args ()
15851599 def _kill_uia2 ():
15861600 for pkg in ("io.appium.uiautomator2.server" ,
15871601 "io.appium.uiautomator2.server.test" ):
15881602 subprocess .run (
1589- [ "adb" , "shell" , "am" , "force-stop" , pkg ],
1603+ _adb_r + [ "shell" , "am" , "force-stop" , pkg ],
15901604 capture_output = True , timeout = 5 ,
15911605 )
15921606 await loop .run_in_executor (None , _kill_uia2 )
0 commit comments