# 定义抽象类 import json import logging from abc import ABC, abstractmethod import uiautomator2 as u2 class AbsUi(ABC): def __init__(self, serial: str): """ :param serial: 设备序列号。 例如 127.0.0.1:6555 可以通过 `adb devices` 获取 """ # u2.logger.setLevel(logging.DEBUG) # 屏幕高度 self.height = 0 # 屏幕宽度 self.width = 0 self.d = u2.connect(serial) self._points = {} self.point_path = 'point.json' self.enable_click_monitor() self._func = [] def enable_click_monitor(self): """ 启用点击监控,在屏幕上显示点击位置 """ # self.d.settings['operation_delay'] = (0.5, 0.5) # 增加操作延迟以便观察 self.d.debug = True self.d.toast.show('点击监控已启用') # 显示提示 # 确保有悬浮窗权限 self.d.set_fastinput_ime(True) # 启用ime self.d.show_float_window(True) # 显示悬浮窗 # 可选:打开开发者选项中的"指针位置" self.d.shell('settings put system pointer_location 1') def to_top_swipe(self): """ 滑动到屏幕最顶部,通过多次滑动确保到达顶部 """ width, height = self.get_screen_size() # 循环滑动直到无法继续滑动 for _ in range(3): self.d.swipe(width // 2, height * 0.8, width // 2, height) # 向上滑动 # 短暂等待确保滑动完成 self.d.sleep(0.1) def click_point(self, x: int, y: int): """ 点击指定坐标 :param x: x坐标 :param y: y坐标 """ self.d.click(x, y) def click_xpath(self, xpath: str): """ 点击指定xpath """ el = self.d.xpath(xpath).get() if el: el.click() else: logging.warning(f"未找到元素: {xpath}") def to_next_swipe(self): """ 向上滑动一屏 """ width, height = self.get_screen_size() # 从屏幕下方向上滑动到顶部 self.d.swipe(width // 2, height * 0.8, width // 2, height * 0.2, duration=0.1) # 向上滑动 def get_screen_size(self): """ 获取屏幕尺寸,宽度和高度 """ self.width, self.height = self.d.window_size() logging.info(f"屏幕尺寸: {self.width}x{self.height}") return self.width, self.height def drag_slider_ext(self, start_x: int, start_y: int, end_x: int, end_y: int, steps: int = 50): """ 精确拖动滑块 :param start_x: 起始x坐标 :param start_y: 起始y坐标 :param end_x: 结束x坐标 :param end_y: 结束y坐标 :param steps: 步数,值越大滑动越平滑 """ self.d.swipe_ext(start_x, start_y, end_x, end_y, steps) def add_point(self, point=None): """ 添加坐标点 point = { "name": "", "x": 0, "y": 0, "desc": "", "xpath": "" } """ logging.info("保存坐标点: %s", point) self._points[point['name']] = point def add_func(self, func): """ 添加坐标点采集函数 """ self._func.append(func) def save_point(self): """ 保存坐标 """ self.to_top_swipe() self.d.sleep(2) for func in self._func: func() __tmp__ = {} for k, v in self._points.items(): __tmp__[k] = v with open(self.point_path, "w", encoding="utf-8") as f: json.dump(__tmp__, f, ensure_ascii=False, indent=4) def get_point(self, info: dict): """ 获取坐标点 info 数据结构 { "name": "btn_mairu_kaiduo", "desc": "买入/开多", "xpath": '//*[@content-desc="买入/开多"]' """ el = self.d.xpath(info['xpath']).get() x, y = el.center() self.add_point({ "name": info['name'], "x": x, "y": y, "desc": info['desc'], "xpath": info['xpath'], }) return x, y