基于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')
相关推荐
雨白1 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹3 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空5 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭5 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日6 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安6 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑6 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟10 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡12 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0012 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体