mobile-mcp-ai 2.3.6__py3-none-any.whl → 2.3.7__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.
@@ -652,7 +652,14 @@ class BasicMobileToolsLite:
652
652
  # ==================== 输入操作 ====================
653
653
 
654
654
  def input_text_by_id(self, resource_id: str, text: str) -> Dict:
655
- """通过 resource-id 输入文本"""
655
+ """通过 resource-id 输入文本
656
+
657
+ 优化策略:
658
+ 1. 先用 resourceId 定位
659
+ 2. 如果只有 1 个元素 → 直接输入
660
+ 3. 如果有多个相同 ID(>5个说明 ID 不可靠)→ 改用 EditText 类型定位
661
+ 4. 多个 EditText 时选择最靠上的(搜索框通常在顶部)
662
+ """
656
663
  try:
657
664
  if self._is_ios():
658
665
  ios_client = self._get_ios_client()
@@ -667,13 +674,70 @@ class BasicMobileToolsLite:
667
674
  return {"success": True, "message": f"✅ 输入成功: '{text}'"}
668
675
  return {"success": False, "message": f"❌ 输入框不存在: {resource_id}"}
669
676
  else:
670
- elem = self.client.u2(resourceId=resource_id)
671
- if elem.exists(timeout=0.5):
672
- elem.set_text(text)
673
- time.sleep(0.3)
674
- self._record_operation('input', element=resource_id, ref=resource_id, text=text)
675
- return {"success": True, "message": f"✅ 输入成功: '{text}'"}
677
+ elements = self.client.u2(resourceId=resource_id)
678
+
679
+ # 检查是否存在
680
+ if elements.exists(timeout=0.5):
681
+ count = elements.count
682
+
683
+ # 只有 1 个元素,直接输入
684
+ if count == 1:
685
+ elements.set_text(text)
686
+ time.sleep(0.3)
687
+ self._record_operation('input', element=resource_id, ref=resource_id, text=text)
688
+ return {"success": True, "message": f"✅ 输入成功: '{text}'"}
689
+
690
+ # 多个相同 ID(<=5个),尝试智能选择
691
+ if count <= 5:
692
+ for i in range(count):
693
+ try:
694
+ elem = elements[i]
695
+ info = elem.info
696
+ # 优先选择可编辑的
697
+ if info.get('editable') or info.get('focusable'):
698
+ elem.set_text(text)
699
+ time.sleep(0.3)
700
+ self._record_operation('input', element=resource_id, ref=resource_id, text=text)
701
+ return {"success": True, "message": f"✅ 输入成功: '{text}'"}
702
+ except:
703
+ continue
704
+ # 没找到可编辑的,用第一个
705
+ elements[0].set_text(text)
706
+ time.sleep(0.3)
707
+ self._record_operation('input', element=resource_id, ref=resource_id, text=text)
708
+ return {"success": True, "message": f"✅ 输入成功: '{text}'"}
709
+
710
+ # ID 不可靠(不存在或太多),改用 EditText 类型定位
711
+ edit_texts = self.client.u2(className='android.widget.EditText')
712
+ if edit_texts.exists(timeout=0.5):
713
+ et_count = edit_texts.count
714
+ if et_count == 1:
715
+ edit_texts.set_text(text)
716
+ time.sleep(0.3)
717
+ self._record_operation('input', element='EditText', ref='EditText', text=text)
718
+ return {"success": True, "message": f"✅ 输入成功: '{text}' (通过 EditText 定位)"}
719
+
720
+ # 多个 EditText,选择最靠上的
721
+ best_elem = None
722
+ min_top = 9999
723
+ for i in range(et_count):
724
+ try:
725
+ elem = edit_texts[i]
726
+ top = elem.info.get('bounds', {}).get('top', 9999)
727
+ if top < min_top:
728
+ min_top = top
729
+ best_elem = elem
730
+ except:
731
+ continue
732
+
733
+ if best_elem:
734
+ best_elem.set_text(text)
735
+ time.sleep(0.3)
736
+ self._record_operation('input', element='EditText', ref='EditText', text=text)
737
+ return {"success": True, "message": f"✅ 输入成功: '{text}' (通过 EditText 定位,选择最顶部的)"}
738
+
676
739
  return {"success": False, "message": f"❌ 输入框不存在: {resource_id}"}
740
+
677
741
  except Exception as e:
678
742
  return {"success": False, "message": f"❌ 输入失败: {e}"}
679
743
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mobile-mcp-ai
3
- Version: 2.3.6
3
+ Version: 2.3.7
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,7 +1,7 @@
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=uqd-YG9vTxQmJEVmio_z_yj8LOeZnhvRP7YxvSueuZs,59803
4
+ mobile_mcp/core/basic_tools_lite.py,sha256=SxUArYAc1wcm7DmaqcuNvaqFpxmS54YeJ_B5SHUvICo,63168
5
5
  mobile_mcp/core/device_manager.py,sha256=PX3-B5bJFnKNt6C8fT7FSY8JwD-ngZ3toF88bcOV9qA,8766
6
6
  mobile_mcp/core/dynamic_config.py,sha256=Ja1n1pfb0HspGByqk2_A472mYVniKmGtNEWyjUjmgK8,9811
7
7
  mobile_mcp/core/ios_client_wda.py,sha256=KudSbWTy-0l8OMQjXpsDYAiL59w7HVrw-i7ApfExJLA,18755
@@ -17,9 +17,9 @@ mobile_mcp/utils/__init__.py,sha256=8EH0i7UGtx1y_j_GEgdN-cZdWn2sRtZSEOLlNF9HRnY,
17
17
  mobile_mcp/utils/logger.py,sha256=Sqq2Nr0Y4p03erqcrbYKVPCGiFaNGHMcE_JwCkeOfU4,3626
18
18
  mobile_mcp/utils/xml_formatter.py,sha256=uwTRb3vLbqhT8O-udzWT7s7LsV-DyDUz2DkofD3hXOE,4556
19
19
  mobile_mcp/utils/xml_parser.py,sha256=QhL8CWbdmNDzmBLjtx6mEnjHgMFZzJeHpCL15qfXSpI,3926
20
- mobile_mcp_ai-2.3.6.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
21
- mobile_mcp_ai-2.3.6.dist-info/METADATA,sha256=sJOSvqLIeuVVfxEE0mR_AyuT37uzBnnCHwM1EV3k_1g,9423
22
- mobile_mcp_ai-2.3.6.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
23
- mobile_mcp_ai-2.3.6.dist-info/entry_points.txt,sha256=KB_FglozgPHBprSM1vFbIzGyheFuHFmGanscRdMJ_8A,68
24
- mobile_mcp_ai-2.3.6.dist-info/top_level.txt,sha256=lLm6YpbTv855Lbh8BIA0rPxhybIrvYUzMEk9OErHT94,11
25
- mobile_mcp_ai-2.3.6.dist-info/RECORD,,
20
+ mobile_mcp_ai-2.3.7.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
21
+ mobile_mcp_ai-2.3.7.dist-info/METADATA,sha256=YhwM3C6TMmdvvkfKXJ3jM4iDiwSYZk_1LlrY3uuT9xI,9423
22
+ mobile_mcp_ai-2.3.7.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
23
+ mobile_mcp_ai-2.3.7.dist-info/entry_points.txt,sha256=KB_FglozgPHBprSM1vFbIzGyheFuHFmGanscRdMJ_8A,68
24
+ mobile_mcp_ai-2.3.7.dist-info/top_level.txt,sha256=lLm6YpbTv855Lbh8BIA0rPxhybIrvYUzMEk9OErHT94,11
25
+ mobile_mcp_ai-2.3.7.dist-info/RECORD,,