Python调用雷电模拟器示例

import os
import subprocess
import re


class LdInit:
    def __init__(self, path: str):
        """
        初始化雷电模拟器ldconsole.exe操作
        :param path: str,雷电模拟器安装目录
        """
        os.putenv('Path', path)

    @staticmethod
    def Run_Command(command: str):
        """
        取DOS执行结果
        :param command: str,命令
        :return: str,返回值
        """
        # process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        # stdout, _ = process.communicate()
        # return stdout.decode('gbk')
        result = subprocess.run(command, capture_output=True, shell=True, encoding='gbk')
        return result.stdout

    def Info_Ld(self):
        """
        # 获取雷电模拟器的信息/刷新模拟器
        :return:
        """
        return self.Run_Command('ldconsole.exe list2')

    def Start_Ld(self, num: int):
        """
        启动指定雷电模拟器
        :param num: int,模拟器ID
        :return:
        """
        command = f'ldconsole.exe launch --index {num}'
        self.Run_Command(command)

    def Stop_Ld(self, num: int):
        """
        关闭指定雷电模拟器
        :param num: int,模拟器ID
        :return:
        """
        command = f'ldconsole.exe quit --index {num}'
        self.Run_Command(command)

    def Restart_Ld(self, num: int):
        """
        重启指定雷电模拟器
        :param num: int,模拟器ID
        :return:
        """
        command = f'ldconsole.exe reboot --index {num}'
        self.Run_Command(command)

    def Sort_Ld_Windows(self):
        """
        排列模拟器窗口
        :return:
        """
        self.Run_Command('ldconsole.exe sortWnd')


class LdOperate:
    def __init__(self, path: str):
        """
        初始化雷电模拟器ld.exe操作
        :param path: str,雷电模拟器安装路径
        """
        os.putenv('Path', path)

    @staticmethod
    def Run_Command(command: str):
        """
        取DOS执行结果
        :param command: str,命令
        :return: str,返回值
        """
        # process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        # stdout, _ = process.communicate()
        # return stdout.decode('gbk')
        result = subprocess.run(command, capture_output=True, shell=True, encoding='gbk')
        return result.stdout

    def Key_Click(self, num: int, key: str):
        """
        雷电模拟器按键点击
        :param num: int,模拟器ID
        :param key: str,键值
        :return:
        """
        command = f'ld.exe -s {num} input keyevent {key}'
        return self.Run_Command(command)

    def Get_Phone_Model(self, num: int):
        """
        取模雷电拟器机型信息
        :param num: int,模拟器ID
        :return:
        """
        command = f'ld.exe -s {num} getprop ro.product.model'
        return self.Run_Command(command)

    def View_Memory_Usage(self, num: int, PackageName: str):
        """
        查看指定应用内存占用
        :param num: int,模拟器ID
        :param PackageName: str,应用包名
        :return:
        """
        command = f'ld.exe -s {num} dumpsys meminfo {PackageName}'
        return self.Run_Command(command)

    def Enumerate_Package_Names(self, num: int,
                                filter: int):
        """
        枚举包名 filter留空或者为0,枚举所有包名;1,显示每个包的文件位置;2,只显示禁用的应用的包名;3,只显示可用的应用的包名;4,只显示系统应用的包名;5,只显示第三方应用的包名;6,查看应用的安装者。
        :param num: int,模拟器ID
        :param filter: int,枚举范围
        :return:
        """
        filter_dict = {
            0: "",
            1: " -f",
            2: " -d",
            3: " -e",
            4: " -s",
            5: " -3",
            6: " -i"
        }
        if filter in filter_dict:
            parameter = filter_dict[filter]
        else:
            parameter = ""
        command = f'ld.exe -s {num} pm list packages {parameter}'
        return self.Run_Command(command)

    def Get_Android_Version(self, num: int):
        """
        取雷电模拟器安卓版本
        :param num: int,模拟器ID
        :return:
        """
        command = f'ld.exe -s {num} getprop ro.build.version.release'
        return self.Run_Command(command)

    def View_File_Contents(self, num: int, path: str):
        """
        查看文件内容,如果安卓版本小于7,需要处理文件路径,好像用不到,现在都是7以上(懒得写文件路径处理)
        :param num: int,模拟器ID
        :param path: str,欲查看文件绝对路径
        :return:
        """
        command = f'ld.exe -s {num} cat "{path}"'
        return self.Run_Command(command)

    def Find_Files(self, num: int, path: str, filename: str):
        """
        查找文件
        :param num: int,模拟器ID
        :param path: str,查找路径
        :param filename: str,文件名
        :return:
        """
        command = f'ld.exe -s {num} "find {path} -name "{filename}""'
        return self.Run_Command(command)

    def Find_App_Package_Name(self, num: int, keyword: str):
        """
        通过关键词来模糊搜索模拟器中安装的应用,返回匹配的数量和包名数组。比如不同平台的游戏客户端,包名都会有所不同,但都有着相似的包名,这个命令就很有用了。
        :param num: int,模拟器ID
        :param keyword: str,关键词
        :return:
        """
        AllPackageName = self.Enumerate_Package_Names(num, 0)
        lines = AllPackageName.splitlines()
        allPackageName = [line for line in lines if line != ""]
        search_pattern = re.compile(re.escape(keyword), re.IGNORECASE)
        matching_packages = [package for package in allPackageName if search_pattern.search(package)]
        if matching_packages:
            for package in matching_packages:
                return package
        else:
            return None

    def Create_Directory(self, num: int, directoryname: str):
        """
        创建目录
        :param num: int,模拟器ID
        :param directoryname: str,目录绝对路径
        :return:
        """
        command = f'ld.exe -s {num} mkdir "{directoryname}"'
        return self.Run_Command(command)

    def Create_A_File(self, num: int, filename: str):
        """
        创建文件
        :param num: int,模拟器ID
        :param filename: str,文件绝对路径
        :return:
        """
        command = f'ld.exe -s {num} touch "{filename}"'
        return self.Run_Command(command)

    def Read_Task_Stack(self, num: int, filtertype: int):
        """
        读任务栈
        :param num: int,模拟器ID
        :param filtertype: int,0 = 全部activity信息,也就是“adb  dumpsys activity”所返回的内容。1 = 运行中的任务栈(Running activities)。2 = 顶栈任务栈(mFocusedActivity)。3 = 最顶端top-activity。
        :return:
        """
        filtertype_dict = {
            0: f"dumpsys activity",
            1: f"dumpsys activity | grep 'mResumedActivity'",
            2: f"dumpsys activity | grep 'mFocusedActivity'",
            3: f"dumpsys activity | grep 'top-activity'",
        }
        if filtertype in filtertype_dict:
            parameter = filtertype_dict[filtertype]
        else:
            parameter = "dumpsys activity"
        command = f'ld.exe -s {num} "{parameter}"'
        return self.Run_Command(command)

    def Send_Text(self, num: int, TextContent: str):
        """
        向窗口输入指定文本内容,不支持中文
        :param num: int,模拟器ID
        :param TextContent: str,文本内容
        :return:
        """
        command = f'ld.exe -s {num} input text "{TextContent}"'
        return self.Run_Command(command)

    def Copy_File(self, num: int, CopiedFiles: str, CopyToFile: str):
        """
        复制文件
        :param num: int,模拟器ID
        :param CopiedFiles: str,被复制文件名
        :param CopyToFile: str,复制到文件名
        :return:
        """
        command = f'ld.exe -s {num} cp {CopiedFiles} {CopyToFile}'
        return self.Run_Command(command)

    def Close_App(self, num: int, PackageName: str):
        """
        关闭应用
        :param num: int,模拟器ID
        :param PackageName: str,应用包名
        :return:
        """
        command = f'ld.exe -s {num} am force-stop {PackageName}'
        return self.Run_Command(command)

    def Disable_App(self, num: int, PackageName: str, State: bool):
        """
        禁用应用,只有系统应用才可以用,第三方应用不行
        :param num: int,模拟器ID
        :param PackageName: str,应用包名
        :param State: bool,假为不禁用,真为禁用
        :return:
        """
        if State:
            parameter = "enable"
        else:
            parameter = "disable"
        command = f'ld.exe -s {num} pm {parameter} {PackageName}'
        return self.Run_Command(command)

    def Screenshot(self, num: int, FilePath: str):
        """
        截屏
        :param num: int,模拟器ID
        :param FilePath: str,文件路径
        :return:
        """
        command = f'ld.exe -s {num} "shell screencap -p {FilePath}"'
        return self.Run_Command(command)

    def Browse_Web_Pages(self, num: int, url: str):
        """
        浏览网页
        :param num: int,模拟器ID
        :param url: str,网址
        :return:
        """
        command = f'ld.exe -s {num} am start -a android.intent.action.VIEW -d {url}'
        return self.Run_Command(command)


class DnconsoleOperate:
    def __init__(self, path):  # 路径加载到环境变量
        """
        初始化雷电模拟器dnconsole.exe操作
        :param path: str,雷电模拟器安装路径
        """
        os.putenv('Path', path)

    @staticmethod
    def Run_Command(command):
        """
        取DOS执行结果
        :param command: str,命令
        :return: str,返回值
        """
        # process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        # stdout, _ = process.communicate()
        # return stdout.decode('gbk')
        result = subprocess.run(command, capture_output=True, shell=True, encoding='gbk')
        return result.stdout

    def Get_Prop(self, num, method):
        """
        不知道干什么的 看不懂 嘤嘤嘤
        :param num: int,模拟器ID
        :param method:
        :return:
        """
        command = f'dnconsole.exe getprop --index {num} --key "{method}"'
        return self.Run_Command(command)

    def StartingApplication(self, num, package):
        """
        启动指定包名app
        :param num: int,模拟器ID
        :param package: str,应用包名
        :return:
        """
        command = f'dnconsole.exe runapp --index {num} --packagename {package}'
        return self.Run_Command(command)


if __name__ == "__main__":
    # ldinit = LdInit(r'D:\leidian\LDPlayer9')
    # ldinit.Start_Ld(0)
    ldop = LdOperate(r'D:\leidian\LDPlayer9')
    # ldop.Create_Directory(0, r"/storage/emulated/0/test")
    # ldop.Find_Files(0, r"/storage/emulated/0", "a.txt")
    # print(ldop.Get_Android_Version(0))
    # print(ldop.Read_Task_Stack(0, 0))
    # ldop.Send_Text(0, "183726")
    res = ldop.Copy_File(0, "/data/misc/user/0/cacerts-added/364618e0.0", "system/etc/security/cacerts/364618e0.0")
    print(res)