mobile-mcp-ai 2.5.8__py3-none-any.whl → 2.5.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -53,7 +53,34 @@ class BasicMobileToolsLite:
53
53
  }
54
54
  self.operation_history.append(record)
55
55
 
56
-
56
+ def _get_full_hierarchy(self) -> str:
57
+ """获取完整的 UI 层级 XML(包含 NAF 元素)
58
+
59
+ 优先使用 ADB 直接 dump,比 uiautomator2.dump_hierarchy 更完整
60
+ """
61
+ import sys
62
+
63
+ if self._is_ios():
64
+ # iOS 使用 page_source
65
+ ios_client = self._get_ios_client()
66
+ if ios_client and hasattr(ios_client, 'wda'):
67
+ return ios_client.wda.source()
68
+ return ""
69
+
70
+ # Android: 优先使用 ADB 直接 dump
71
+ try:
72
+ # 方法1: ADB dump(获取最完整的 UI 树,包括 NAF 元素)
73
+ self.client.u2.shell('uiautomator dump /sdcard/ui_dump.xml')
74
+ result = self.client.u2.shell('cat /sdcard/ui_dump.xml')
75
+ if result and isinstance(result, str) and result.strip().startswith('<?xml'):
76
+ xml_string = result.strip()
77
+ self.client.u2.shell('rm /sdcard/ui_dump.xml')
78
+ return xml_string
79
+ except Exception as e:
80
+ print(f" ⚠️ ADB dump 失败: {e}", file=sys.stderr)
81
+
82
+ # 方法2: 回退到 uiautomator2
83
+ return self.client.u2.dump_hierarchy(compressed=False)
57
84
 
58
85
  # ==================== 截图 ====================
59
86
 
@@ -354,7 +381,7 @@ class BasicMobileToolsLite:
354
381
  if show_popup_hints and not self._is_ios():
355
382
  try:
356
383
  import xml.etree.ElementTree as ET
357
- xml_string = self.client.u2.dump_hierarchy(compressed=False)
384
+ xml_string = self._get_full_hierarchy()
358
385
  root = ET.fromstring(xml_string)
359
386
 
360
387
  # 检测弹窗区域
@@ -531,7 +558,7 @@ class BasicMobileToolsLite:
531
558
  else:
532
559
  try:
533
560
  import xml.etree.ElementTree as ET
534
- xml_string = self.client.u2.dump_hierarchy(compressed=False)
561
+ xml_string = self._get_full_hierarchy()
535
562
  root = ET.fromstring(xml_string)
536
563
 
537
564
  for elem in root.iter():
@@ -1087,9 +1114,9 @@ class BasicMobileToolsLite:
1087
1114
  return {"success": False, "message": f"❌ 点击失败: {e}"}
1088
1115
 
1089
1116
  def _find_element_in_tree(self, text: str) -> Optional[Dict]:
1090
- """在 XML 树中查找包含指定文本的元素"""
1117
+ """在 XML 树中查找包含指定文本的元素(使用完整 UI 层级)"""
1091
1118
  try:
1092
- xml = self.client.u2.dump_hierarchy(compressed=False)
1119
+ xml = self._get_full_hierarchy()
1093
1120
  import xml.etree.ElementTree as ET
1094
1121
  root = ET.fromstring(xml)
1095
1122
 
@@ -1831,7 +1858,7 @@ class BasicMobileToolsLite:
1831
1858
  return ios_client.list_elements()
1832
1859
  return [{"error": "iOS 暂不支持元素列表,建议使用截图"}]
1833
1860
  else:
1834
- xml_string = self.client.u2.dump_hierarchy(compressed=False)
1861
+ xml_string = self._get_full_hierarchy()
1835
1862
  elements = self.client.xml_parser.parse(xml_string)
1836
1863
 
1837
1864
  result = []
@@ -1867,8 +1894,8 @@ class BasicMobileToolsLite:
1867
1894
  screen_width = self.client.u2.info.get('displayWidth', 720)
1868
1895
  screen_height = self.client.u2.info.get('displayHeight', 1280)
1869
1896
 
1870
- # 获取元素列表
1871
- xml_string = self.client.u2.dump_hierarchy(compressed=False)
1897
+ # 获取元素列表(使用完整 UI 层级)
1898
+ xml_string = self._get_full_hierarchy()
1872
1899
  import xml.etree.ElementTree as ET
1873
1900
  root = ET.fromstring(xml_string)
1874
1901
 
@@ -2021,8 +2048,8 @@ class BasicMobileToolsLite:
2021
2048
  screen_width = self.client.u2.info.get('displayWidth', 720)
2022
2049
  screen_height = self.client.u2.info.get('displayHeight', 1280)
2023
2050
 
2024
- # 获取原始 XML
2025
- xml_string = self.client.u2.dump_hierarchy(compressed=False)
2051
+ # 获取原始 XML(使用完整 UI 层级)
2052
+ xml_string = self._get_full_hierarchy()
2026
2053
 
2027
2054
  # 关闭按钮的文本特征
2028
2055
  close_texts = ['×', 'X', 'x', '关闭', '取消', 'close', 'Close', 'CLOSE', '跳过', '知道了']
@@ -2893,8 +2920,8 @@ class BasicMobileToolsLite:
2893
2920
  try:
2894
2921
  import xml.etree.ElementTree as ET
2895
2922
 
2896
- # ========== 第1步:控件树查找关闭按钮 ==========
2897
- xml_string = self.client.u2.dump_hierarchy(compressed=False)
2923
+ # ========== 第1步:控件树查找关闭按钮(使用完整 UI 层级)==========
2924
+ xml_string = self._get_full_hierarchy()
2898
2925
  root = ET.fromstring(xml_string)
2899
2926
 
2900
2927
  # 关闭按钮的常见特征
@@ -189,8 +189,29 @@ class MobileClient:
189
189
  return xml_string
190
190
 
191
191
  # Android平台
192
- # 获取XML
193
- xml_string = self.u2.dump_hierarchy(compressed=False)
192
+ # 获取XML - 优先使用 ADB 直接 dump(更完整,包含 NAF 元素)
193
+ xml_string = None
194
+ try:
195
+ # 方法1: 使用 ADB 直接 dump(获取最完整的 UI 树,包括 NAF 元素)
196
+ import subprocess
197
+ import tempfile
198
+ import os
199
+
200
+ # 在设备上执行 dump
201
+ self.u2.shell('uiautomator dump /sdcard/ui_dump.xml')
202
+
203
+ # 读取文件内容
204
+ result = self.u2.shell('cat /sdcard/ui_dump.xml')
205
+ if result and isinstance(result, str) and result.strip().startswith('<?xml'):
206
+ xml_string = result.strip()
207
+ # 清理临时文件
208
+ self.u2.shell('rm /sdcard/ui_dump.xml')
209
+ except Exception as e:
210
+ print(f" ⚠️ ADB dump 失败,使用 uiautomator2: {e}", file=sys.stderr)
211
+
212
+ # 方法2: 回退到 uiautomator2 的 dump_hierarchy
213
+ if not xml_string:
214
+ xml_string = self.u2.dump_hierarchy(compressed=False)
194
215
 
195
216
  # 确保xml_string是字符串类型
196
217
  if not isinstance(xml_string, str):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mobile-mcp-ai
3
- Version: 2.5.8
3
+ Version: 2.5.9
4
4
  Summary: 移动端自动化 MCP Server - 支持 Android/iOS,AI 功能可选(基础工具不需要 AI)
5
5
  Home-page: https://github.com/test111ddff-hash/mobile-mcp-ai
6
6
  Author: douzi
@@ -1,12 +1,12 @@
1
1
  mobile_mcp/__init__.py,sha256=sQJZTL_sxQFzmcS7jOtS2AHCfUySz40vhX96N6u1qy4,816
2
2
  mobile_mcp/config.py,sha256=yaFLAV4bc2wX0GQPtZDo7OYF9E88tXV-av41fQsJwK4,4480
3
3
  mobile_mcp/core/__init__.py,sha256=ndMy-cLAIsQDG5op7gM_AIplycqZSZPWEkec1pEhvEY,170
4
- mobile_mcp/core/basic_tools_lite.py,sha256=hmsNjoNH-EsSU7GAclSsYiYKgds0RlmdrVlGmun3gPw,153561
4
+ mobile_mcp/core/basic_tools_lite.py,sha256=C9_mptagHKGgGfPUxzmoM0t080JNERYDDNb0OrbV8sQ,154736
5
5
  mobile_mcp/core/device_manager.py,sha256=xG5DoeNFs45pl-FTEhEWblqVwxtFK-FmVEGlNL6EqRI,8798
6
6
  mobile_mcp/core/dynamic_config.py,sha256=Ja1n1pfb0HspGByqk2_A472mYVniKmGtNEWyjUjmgK8,9811
7
7
  mobile_mcp/core/ios_client_wda.py,sha256=Nq9WxevhTWpVpolM-Ymp-b0nUQV3tXLFszmJHbDC4wA,18770
8
8
  mobile_mcp/core/ios_device_manager_wda.py,sha256=A44glqI-24un7qST-E3w6BQD8mV92YVUbxy4rLlTScY,11264
9
- mobile_mcp/core/mobile_client.py,sha256=ELl2ypgJunsKVkWwhkXN8zco4mj3OnGGqtSEofpSmWc,62714
9
+ mobile_mcp/core/mobile_client.py,sha256=AaBntQSW2loAw7xL3j_IABNzrJO_Uukf9-F1z1xl6xE,63672
10
10
  mobile_mcp/core/template_matcher.py,sha256=tv8RU6zdeDobqphaP4Y8sicb1esg3gcQlZae1tNyitM,14559
11
11
  mobile_mcp/core/templates/close_buttons/auto_x_0112_151217.png,sha256=s7tBVaYLBApNSEXjwi5kX8GXwUqgbNyNVEhXYjN9nd4,27373
12
12
  mobile_mcp/core/templates/close_buttons/auto_x_0112_152037.png,sha256=s7tBVaYLBApNSEXjwi5kX8GXwUqgbNyNVEhXYjN9nd4,27373
@@ -24,9 +24,9 @@ mobile_mcp/utils/__init__.py,sha256=8EH0i7UGtx1y_j_GEgdN-cZdWn2sRtZSEOLlNF9HRnY,
24
24
  mobile_mcp/utils/logger.py,sha256=Sqq2Nr0Y4p03erqcrbYKVPCGiFaNGHMcE_JwCkeOfU4,3626
25
25
  mobile_mcp/utils/xml_formatter.py,sha256=uwTRb3vLbqhT8O-udzWT7s7LsV-DyDUz2DkofD3hXOE,4556
26
26
  mobile_mcp/utils/xml_parser.py,sha256=QhL8CWbdmNDzmBLjtx6mEnjHgMFZzJeHpCL15qfXSpI,3926
27
- mobile_mcp_ai-2.5.8.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
28
- mobile_mcp_ai-2.5.8.dist-info/METADATA,sha256=vwWnw9dqb_pqiZz635gcRRW4TvyI_WKavutrapxCBHQ,10495
29
- mobile_mcp_ai-2.5.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
- mobile_mcp_ai-2.5.8.dist-info/entry_points.txt,sha256=KB_FglozgPHBprSM1vFbIzGyheFuHFmGanscRdMJ_8A,68
31
- mobile_mcp_ai-2.5.8.dist-info/top_level.txt,sha256=lLm6YpbTv855Lbh8BIA0rPxhybIrvYUzMEk9OErHT94,11
32
- mobile_mcp_ai-2.5.8.dist-info/RECORD,,
27
+ mobile_mcp_ai-2.5.9.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
28
+ mobile_mcp_ai-2.5.9.dist-info/METADATA,sha256=j1KcGXfXaAeU3KJiSOAlo150FG9Mvg3cRlmDjJK3nZY,10495
29
+ mobile_mcp_ai-2.5.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ mobile_mcp_ai-2.5.9.dist-info/entry_points.txt,sha256=KB_FglozgPHBprSM1vFbIzGyheFuHFmGanscRdMJ_8A,68
31
+ mobile_mcp_ai-2.5.9.dist-info/top_level.txt,sha256=lLm6YpbTv855Lbh8BIA0rPxhybIrvYUzMEk9OErHT94,11
32
+ mobile_mcp_ai-2.5.9.dist-info/RECORD,,