基于adb操作安卓手机封装的python库

python 复制代码
import re
import shlex
import subprocess


class ADBClient:
    def __init__(self, ip, port):
        """
        初始化ADBClient实例。
        :param ip: 远程设备的IP地址。
        :param port: 远程设备的端口号。
        """
        self.ip = ip
        self.port = port

    def is_app_running(self, package_name):
        """
        检查指定的应用是否正在设备上运行。
        :param package_name: 应用的包名。
        :return: 如果应用正在运行,返回True;否则返回False。
        """
        try:
            # 通过ADB命令获取当前运行中的应用列表,并检索目标应用包名
            result = subprocess.run(["adb", "-s", f"{self.ip}:{self.port}", "shell", "ps"], capture_output=True,
                                    text=True)
            output = result.stdout

            # 使用正则表达式搜索应用包名
            if re.search(package_name, output):
                return True
            else:
                return False
        except subprocess.CalledProcessError as e:
            # 打印错误信息并返回False,表示未能成功执行ADB命令
            print(f"发生错误:{e}")
            return False

    def open_app(self, package_name, activity_name):
        """
        在设备上启动指定的应用。
        :param package_name: 应用的包名。
        :param activity_name: 应用要启动的Activity名称。
        :return: 如果应用成功启动,返回True;否则返回False。
        """
        try:
            # 首先检查应用是否已经在运行
            if self.is_app_running(package_name):
                print("@@@应用已经在运行")
                return True

            # 如果应用未运行,则通过ADB命令启动应用
            subprocess.run(["adb", "-s", f"{self.ip}:{self.port}", "shell", "am", "start", "-n",
                            f"{package_name}/{activity_name}"])
        except subprocess.CalledProcessError as e:
            # 如果ADB命令执行出错,打印错误信息
            print(f"发生错误:{e}")
            return False

    def execute_adb_command(self, adb_command):
        """
        执行ADB命令,并返回命令的输出和错误信息。

        参数:
        - adb_command: 要执行的ADB命令字符串。

        返回值:
        - 一个元组,包括命令的输出(stdout)和错误信息(stderr)。如果命令执行失败,返回None和错误信息。
        """
        try:
            # 使用subprocess运行ADB命令,将命令字符串分割为列表,添加设备IP和端口信息
            result = subprocess.run(["adb", "-s", f"{self.ip}:{self.port}"] + adb_command.split(), capture_output=True,
                                    text=True)
            # 返回执行结果的输出和错误信息
            return result.stdout, result.stderr
        except subprocess.CalledProcessError as e:
            # 如果命令执行出错,返回错误信息
            return None, f"发生错误:{e}"

    def get_current_window_info(self):
        """
        获取当前窗口的信息,包括包名和应用名称。

        该方法通过运行ADB命令,提取当前焦点窗口的包名和应用名称。

        返回:
            tuple: 成功时返回一个包含包名和应用名称的元组 (pkg, path);如果无法提取到信息,则返回 (None, None)。
        """
        # 构造获取当前窗口信息的ADB命令
        cmd = 'shell dumpsys window | grep mCurrentFocus'
        # 运行ADB命令并获取输出
        result = subprocess.run(["adb", "-s", f"{self.ip}:{self.port}"] + cmd.split(), capture_output=True, text=True)
        output = result.stdout.strip()

        # 使用正则表达式提取包名和应用名称
        pattern = r"mCurrentFocus=Window\{.+?\s+(\S+)/(.+?)\}"
        match = re.search(pattern, output)

        if match:
            # 如果匹配成功,提取并返回包名和应用名称
            pkg = match.group(1)
            path = match.group(2)
            return pkg, path
        else:
            # 如果匹配失败,返回None
            return None, None

    # 坐标点击事件
    def tap_by_coordinates(self, x, y):
        try:
            # 构建 adb 命令
            cmd = ["adb", "-s", f"{self.ip}:{self.port}", "shell", "input", "tap", str(x), str(y)]

            # 执行点击事件
            subprocess.run(cmd, check=True)
            print(f"已点击坐标 ({x}, {y})")

        except subprocess.CalledProcessError as e:
            print(f"Error: {e}")

    # 跳转到path指定页面
    def toPath(self, action, param=None):
        """
           根据指定的操作动作和参数,向应用发送命令,实现页面跳转或其他操作。

           参数:
           action: 字符串,指定要执行的操作,例如"settings"表示设置页面。
           param: 可选参数,字符串类型,当需要传递额外的参数给操作时使用,比如用户ID或视频ID等。

           返回值: True表示操作成功,False表示操作失败。
           """
        commands = {
            # 某页面
            "settings": "am start -n ..."
            # 其他页面往这放
        }

        # 检查命令是否在映射中
        if action in commands:
            # 执行命令
            full_cmd = ["adb", "-s", f"{self.ip}:{self.port}", "shell"] + shlex.split(commands[action])
            subprocess.run(full_cmd, check=True)
            return True
        else:
            # 如果命令不在映射中,返回False
            return False

食用方法

python 复制代码
# 创建ADBClient实例,并尝试打开指定的应用
adb_client = ADBClient('192.168.1.5', '5003')
adb_client.open_app("com.zhiliaoapp.musically", "com.ss.android.ugc.aweme.splash.SplashActivity")
res = adb_client.execute_adb_command("root")
print("执行adb命令返回的结果:" + str(res))

# 获取当前活动的应用程序包名称和页面ID
pkg, path = adb_client.get_current_window_info()
print("当前活动的应用程序包名称:", pkg)
print("当前活动的页面ID:", path)

# 模拟点击"com.zhiliaoapp.musically:id/c5w"元素
adb_client.tap_by_coordinates(667, 633)

# 跳转页面
adb_client.toPath('settings')
相关推荐
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen4 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone4 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui