Last active
September 30, 2025 08:23
-
-
Save codeskyblue/67b462f2e9952ce3db7d5dcaac7dd809 to your computer and use it in GitHub Desktop.
uiautomator2使用自定义弹窗监控的例子
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # author: codeskyblue 2025 | |
| # https://github.com/openatx/uiautomator2 | |
| # Example: how to manually handle popup-windows | |
| import random | |
| import time | |
| from typing import Optional, Sequence, Tuple | |
| import adbutils | |
| from loguru import logger | |
| from uiautomator2 import Device as U2Device | |
| from uiautomator2.xpath import PageSource, XMLElement | |
| class PopupRule: | |
| def __init__(self, target: str, neighbors: Optional[Sequence[str]] = None): | |
| self.target = target | |
| self.neighbors = neighbors or () | |
| def get_match(self, page_source: PageSource) -> Optional[XMLElement]: | |
| for xpath in self.neighbors: | |
| elements = page_source.find_elements(xpath) | |
| if not elements: | |
| return None | |
| els = page_source.find_elements(self.target) | |
| return els[0] if els else None | |
| POPUP_RULES = ( | |
| PopupRule('//*[@content-desc="继续"]'), | |
| PopupRule('//android.widget.Button[@text="继续"]'), | |
| PopupRule('//*[@text="以后再说"]', neighbors=['//*[@text="Google 存储空间备份"]']), | |
| ) | |
| class MyDevice: | |
| def __init__(self, serial: Optional[str] = None): | |
| self.u2 = U2Device(serial or adbutils.device()) | |
| def click(self, x: int, y: int): | |
| self.u2.click(x, y) | |
| def _handle_popup(self, page_source: PageSource) -> bool: | |
| popups = list(POPUP_RULES) | |
| random.shuffle(popups) | |
| for rule in popups: | |
| el = rule.get_match(page_source) | |
| if el: | |
| logger.info(f"检测到弹窗: {rule.target}, 点击关闭") | |
| x, y = el.center() | |
| self.click(x, y) | |
| return True | |
| return False | |
| def get_stable_page_source(self) -> Tuple[PageSource, bool]: # has_popup | |
| deadline = time.time() + 10 | |
| has_popup = False | |
| while time.time() < deadline: | |
| page_source = self.u2.xpath.get_page_source() | |
| if self._handle_popup(page_source): | |
| has_popup = True | |
| continue | |
| return page_source, has_popup | |
| raise TimeoutError("未能在规定时间内稳定页面") | |
| def click_by_xpath(self, xpath: str, timeout: float=30, nf_ok: bool = False): | |
| # nf: not found | |
| logger.debug(f"Click: {xpath}") | |
| deadline = time.time() + timeout | |
| while time.time() < deadline: | |
| page_source, has_popup = self.get_stable_page_source() | |
| if has_popup: | |
| deadline = time.time() + timeout | |
| els = page_source.find_elements(xpath) | |
| if els: | |
| self.click(*els[0].center()) | |
| return | |
| else: | |
| if nf_ok: | |
| print("Not found, but OK:", xpath) | |
| raise TimeoutError(f"未能在规定时间内点击到元素: {xpath}") | |
| if __name__ == "__main__": | |
| device = MyDevice() | |
| device.click_by_xpath('//*[@text="证件"]') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment