• 【Andriod】使用adb命令安装和卸载apk的通用python脚本


    1.前言

    如不会使用adb请看之前的文章
    【Andriod】adb调试安卓手机时连接真机或模拟器的3种方法,你知道么?

    2.连接设备

    import os  # python标准库中的os模块
    
    """
    使用python编写脚本对app完成自动启动的操作
    """
    
    
    class AdbConnect:
        #如果配置了环境变量这里可以为空,我没有配置所以得从根目如调用adb
        ANDROID_SDB_ABS_PATH = "F:\dev_tools\\android-sdk_r24.4.1-windows\\android-sdk-windows\platform-tools\\"
    
        # 构造函数
        def __init__(self, device_name):
            # 初始化时,传入的device_name表示模拟器的名称(USB连接传设备编号,模拟器传ip端口)
            self.device_name = device_name
    
        # 连接设备
        def adb_connect(self):
            # (1)popen和system方法都可以执行指令,popen可以接受返回对象,此处要查看连接设备的列表,把查询到的连接设备结果保存在变量device_list中
            device = os.popen(self.ANDROID_SDB_ABS_PATH + "adb devices")
            device_list = device.read()
            print("连接设备列表1:\n{}".format(device_list))
    
            # (2)判断设备名称是否在连接设备列表中,如果不在就调用连接设备的方法,再查询连接状态是否成功,如果在就直接查询连接设备和状态
            # 判断连接设备的名称是否在连接设备列表中
            if self.device_name not in device_list:
                self.connection_equipment()  # 调用连接设备的方法
                # print(self.query_device_list())
                return self.query_device_list()  # 查询连接设备和状态
            else:
                # print(self.query_device_list())
                return self.query_device_list()  # 查询连接设备和状态
    
        # 查询连接设备的列表(可根据连接设备名称查询连接设备的状态)
        def query_device_list(self):
            device = os.popen(self.ANDROID_SDB_ABS_PATH + "adb devices")
            # popen与system可以执行指令,popen可以接受返回对象
    
            device_list = device.read()
            # 读取adb devices返回的结果
    
            print("连接设备列表2:\n{}".format(device_list))
            # 打印连接设备列表
    
            con_attached_list = device_list[device_list.rfind(self.device_name):-2]
            # 从连接设备列表截取连接设备的名称到连接状态这部分的字符串,连接设备列表的字符串最后两行是空所以取-2
            # print(con_attached_list)# FJH7N19131000457	device
    
            dve_len = len(self.device_name)
            # 计算连接设备的长度dve_len,根据此长度来确定截取连接状态的位置
            # print(dve_len) # 16
    
            dve_ps = con_attached_list.rfind(self.device_name)
            # 取出连接设备在连接设备列表的起始位置dve_ps
            # print(dve_ps) # 0
    
            con_attached = con_attached_list[dve_ps + dve_len + 1:dve_ps + dve_len + 7]
            # 截取连接设备的连接状态,从起始位置dve_ps加上连接设备长度dve_len+1(设备名称到状态之间有空格所有+1)
            # 从状态开始的位置往后截取6个字符:dve_ps + dve_len + 7,后面只需判断这部分截取的结果是否是device
            #print(con_attached)# device
    
            if self.device_name in con_attached_list and con_attached == 'device':
            
                # 判断连接设备的名称是否在连接设备列表,且状态是否为device
                return "adb已连接上设备{}".format(self.device_name)
            elif self.device_name in con_attached_list and con_attached != 'device':
                return "连接设备的状态异常\n{}".format(con_attached_list)
            elif self.device_name not in con_attached_list:
                return "未连接该设备,请检查"
            else:
                return "未知错误"
    
        def connection_equipment(self):
            os.system("adb connect {}".format(self.device_name))
            # 使用adb connect 连接设备
    
    
    if __name__ == '__main__':
        a = AdbConnect("FJH7N19131000457")
        s = a.adb_connect()
        print(s)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    执行结果
    在这里插入图片描述

    3.从本机通过adb安装apk

    import os
    from adb_connect import AdbConnect
    
    
    class AppInstall:
    
        def __init__(self, device_name, apk_path, method=''):
            self.apk_path = apk_path  # apk的路径
            self.install_method = method  # 安装的app方法,常规安装(默认)、R(覆盖安装)、D(降级安装)
            self.device = device_name  # 设备的名称(USB连接传设备编号,模拟器传ip端口)
    
        def app_install(self):  # 安装的方法
            adb_cont = AdbConnect(self.device) # 初始化adb连接的类,传入设备名称
            device_status = adb_cont.adb_connect()  # 调用adb连接类的方法连接设备
    
            if "已连接上设备" in device_status:  # 如果已连接设备则执行下面的安装app步骤
                print(device_status)  # 打印连接设备的列表
                try:
                    if self.install_method == '':  # 判断是否传入的安装方法为空
                        self.app_direct_install()  # 调用常规安装app的方法
                    elif self.install_method == 'R':  # 传入了R参数,表示覆盖安装
                        self.app_replace_install()  # 调用覆盖安装的方法
                    elif self.app_downgrade_install() == 'D':  # 传入了D参数,表示降级安装
                        self.app_downgrade_install()  # 调用降级安装的方法
                    else:
                        pass
                except Exception as e:  # 如果有错误则打印错误
                    print(e)
            else:
                print(device_status)  # 如果不是已连接设备,则打印连接设备列表
    
        def app_direct_install(self):  # 常规安装app的方法
            install = os.popen(
                AdbConnect.ANDROID_SDB_ABS_PATH + "adb install {}".format(self.apk_path))  # 执行adb install命令常规安装
            install_re = install.read()  # 把安装的结果赋值给变量install_re
            if 'Success' in install_re[-9:-1]:  # 判断安装结果的部分包含Success
                return print("app已成功安装")  # 打印app已安装成功
            else:
                return print("app未成功安装,安装结果:{}\n覆盖或降级安装需要在初始化时添加安装附加参数:R(覆盖安装)、D(降级安装)".format(install_re[-41:-2]))
    
        def app_replace_install(self):  # 覆盖安装的方法
            install = os.popen(
                AdbConnect.ANDROID_SDB_ABS_PATH + "adb install -r {}".format(self.apk_path))  # 执行adb install -r命令覆盖安装
            install_re = install.read()
            if 'Success' in install_re[-9:-1]:
                return print("app已成功安装")
            else:
                return print("app未成功安装,安装结果:{}\n覆盖或降级安装需要在初始化时添加安装附加参数:R(覆盖安装)、D(降级安装)".format(install_re[-41:-2]))
    
        def app_downgrade_install(self):  # 降级安装的方法
            install = os.popen(
                AdbConnect.ANDROID_SDB_ABS_PATH + "adb install -r -d {}".format(self.apk_path))  # 执行adb install -r -d命令降级安装
            install_re = install.read()
            if 'Success' in install_re[-9:-1]:
                return print("app已成功安装")
            else:
                return print("app未成功安装,安装结果:{}\n覆盖或降级安装需要在初始化时添加安装附加参数:R(覆盖安装)、D(降级安装)".format(install_re[-41:-2]))
    
    
    if __name__ == '__main__':
        # a = AppInstall(r"D:\ac\APP\tools\yibijizhang.apk", "127.0.0.1:62001", method="R")
        # a.app_install()
    
        #b = AppInstall("127.0.0.1:62001", r"D:\download\meituan10.10.403.apk")
        #b.app_install()
    
        c = AppInstall("FJH7N19131000457", r"F:\my_tools\DigiFinex_V2023.10.12_debugT.apk","R")
        c.app_install()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    执行结果
    在这里插入图片描述

    4.从本机通过adb卸载apk

    import os
    from adb_connect import AdbConnect
    
    
    
    class AppUninstall:
        def __init__(self, device_name):
            self.device = device_name  # 设备的名称(USB连接传设备编号,模拟器传ip端口)
            con = AdbConnect(self.device)  # 实例化连接设备的类
            con.adb_connect()  # 调用连接设备的方法
    
        def app_uninstall(self):
            app_pack_list = self.app_packages_three()  # 调用查询第三方包名的方法,得到包含所有第三方安装包名的列表
            if app_pack_list:  # 判断第三方安装包名的列表不为空
                print("安装的app包名列表:\n{}".format(app_pack_list))  # 打印第三方安装包名列表
                uninstall_app_pack = input("请输入要删除app的包名:")  # 输入要删除的包名
                if uninstall_app_pack in app_pack_list:  # 判断输入要删除的包名在查询出来的结果中
                    un_re = os.popen(AdbConnect.ANDROID_SDB_ABS_PATH + "adb uninstall {}".format(
                        uninstall_app_pack))  # 使用adb uninstall <包名>命令卸载app
                    uninstall_re = un_re.read()  # 读取卸载的结果
                    uninstall_result = uninstall_re[:7]  # 截取卸载结果的前7位字母
                    if uninstall_result == 'Success':  # 判断卸载结果的7位字母为Success
                        print("app卸载成功")  # 打印app卸载成功
                    else:
                        print("未知错误")  # 打印未知错误
                else:
                    print("您输入的包名不存在,请检查!")  # 如果输入的包名不存在包名列表中则提示
            else:
                print("未查询到第三方安装的app")  # 如果第三方安装包名列表为空则提示
    
        def app_packages_three(self):
            packages = os.popen(AdbConnect.ANDROID_SDB_ABS_PATH + "adb shell pm list packages -3")  # adb命令查询第三方安装的包名
            app_packages = packages.read()  # 读取第三方安装的app包名
            print(app_packages)
    
            app_pack_str = app_packages.replace('\n', '')  # 读取结果把换行符\n替换为空,删除换行符
            app_pack_list = app_pack_str.split("package:")  # 使用split方法切片,得到包名的一个列表
            print(app_pack_list)
    
            app_pack_list.pop(0)  # 使用列表的pop方法删除包名列表中的第一个数据
            return app_pack_list  # 返回包名列表
    
    
    if __name__ == '__main__':
        a = AppUninstall("FJH7N19131000457")
        a.app_uninstall()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    执行结果
    在这里插入图片描述

  • 相关阅读:
    [附源码]java毕业设计明光中学考试系统
    arcmap / arcgis 安装教程
    wzx-jmw:NFL合理,但可能被颠覆。2023-2024
    java银行存取款程序设计
    方法调用过程
    【Axure教程】雷达扫描动态效果(航空信息可视化案例)
    【云原生】手把手教你搭建ferry开源工单系统
    edge浏览器 路径获得
    y138.第八章 Servless和Knative从入门到精通 -- Knative基础(二)
    Qt与MQTT交互通信
  • 原文地址:https://blog.csdn.net/qq877728715/article/details/134055455