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

文章目录

  • 1.前言
  • 2.连接设备
  • 3.从本机通过adb安装apk
  • 4.从本机通过adb卸载apk

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)

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

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()

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

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()

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/104736.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

更加轻松处理相同文件名!覆盖复制操作全新升级,避免重复命名!

亲爱的用户&#xff0c;您是否在进行覆盖复制操作时&#xff0c;常常因为相同的文件名而无法正常完成任务&#xff1f;现在&#xff0c;我们为您推出了全新的覆盖复制升级版&#xff0c;让您更加轻松处理相同文件名&#xff0c;避免重复命名的尴尬局面&#xff01; 首先第一步…

【23真题】四电四邮、专业课最简单的!

先科普下四电四邮有哪些&#xff1a;北邮、南邮、西邮、重邮、西电、成电、桂电、杭电 其中北邮、重邮、西电、成电&#xff0c;难度必须在第一梯队&#xff0c;毕竟大浪淘金&#xff0c;没点难度&#xff0c;没法筛人。南邮考通信原理&#xff0c;这里不做横向比较。桂电考信…

正确部署Baichuan2(Ubuntu20.4) 步骤及可能出现的问题

部署其实是不太复杂的,但实际上也耗费了接近2-3天的时间去不断的设置 1 硬件配置信息 采用esxi 虚拟化的方式将T4 卡穿透给esxi 种的ubuntu20.4虚拟机 CPU给到8 core 内存至少32GB以上 T4卡是16GB 2 预先准备OS环境 这里使用的是ubuntu20.4版本,esxi中需要设置uefI启动方…

99%的时间里使用的14个git命令

学习14个Git命令&#xff0c;因为你将会在99%的时间里使用它们 必须了解的命令整理 1&#xff0c;git init 初始化一个新的Git仓库。 这将在当前目录中创建一个名为".git"的子目录&#xff0c;Git会将所有仓库的元数据存储在其中。 2&#xff0c;git clone 克隆…

用低代码平台代替Excel搭建进销存管理系统

目录 一、用低代码平台搭建系统 1.需求调研 2.基于痛点梳理业务流程 3.低代码实现 &#xff08;1&#xff09;基础资料模块 &#xff08;2&#xff09;采购管理模块 &#xff08;3&#xff09;销售管理模块 &#xff08;4&#xff09;库存管理模块 &#xff08;5&…

u-boot 通过 SD 卡启动 Linux(三)

u-boot 移植 linux 运行 linuxSD卡(rootfs) 运行 u-bootSD卡(kerneldtbrootfs) 前面单独介绍了 u-boot 的移植&#xff0c;linux 移植和 rootfs 根 文件系统的制作。本节主要通过将前面的串起来介绍 u-bootSD卡(kerneldtbrootfs)启动 linux。 根文件系统制作 cd rootfscp -r…

QT QProcess的使用

定义 The QProcess class is used to start external programs and to communicate with them. QProcess类是用来启动一个外部程序并与之通信。 本文福利&#xff0c;莬费领取Qt开发学习资料包、技术视频&#xff0c;内容包括&#xff08;Qt实战项目视频教程代码&#xff0c;…

EG网关串口连接台达PLC

EG网关串口连接台达PLC 前言&#xff1a;台达PLC是一款国产优秀的可编程控制器&#xff0c;广泛应于工业控制领域&#xff0c;是一款性能高&#xff0c;运行稳定的控制器。此次我们要把台达DVP-ES系列PLC通过modbus驱动连接到EMCP物联网云平台&#xff08;简称EMCP&#xff09;…

论文-分布式-分布式计算|容错-分布式控制下的自稳定系统

参考文献Self-stabilizing systems in spite of distributed control可以把松散耦合的 循环序列过程 间的同步任务&#xff0c;看成是要保持一个这样的不变性&#xff1a;“系统要处于一种合法状态”因此每个进程在运行每一个可能会改变不变性的步骤之前都要先检查一下是可以执…

轻松批量剪辑:将MP4视频转换为FLV格式

在视频制作和编辑领域&#xff0c;批量剪辑和格式转换是非常常见的操作。将MP4视频转换为FLV格式&#xff0c;可以帮助我们更好地管理和发布视频内容。本文将介绍云炫AI智剪如何轻松批量剪辑&#xff0c;将MP4视频转换为FLV格式&#xff0c;帮助您提高工作效率&#xff0c;减少…

高防CDN:保卫您的网站免受攻击之利与弊

在当今数字化时代&#xff0c;网络安全对于网站经营者至关重要。高防CDN&#xff08;Content Delivery Network&#xff09;技术旨在提供强大的安全性&#xff0c;以保护网站免受恶意攻击。本文将探讨高防CDN为普通网站带来的优势与不足之处&#xff0c;并分析国内外高防CDN的发…

在C代码中找到栈顶的位置并访问栈空间

任务目标 在主循环中写一个任务&#xff0c;检查栈是否溢出。 思路 先找到任务的栈顶位置。在初始化时在栈顶位置写一个标志&#xff0c;运行过程中及时检查该标志是否被改写。如果标志位改变了&#xff0c;则判断为栈溢出。 问题 在RTOS中&#xff0c;任务的栈空间是自己分…

Jmeter(十四):跨线程组传递jmeter变量及cookie的处理详解

setUp线程组 setUp thread group 一种特殊类型的线程组&#xff0c;用于在执行常规线程组之前执行一些必要的操作。 在 setup线程组下提到的线程行为与普通线程组完全相同。不同的是执行顺序--- 它会在普通线程组执行之前被触发&#xff1b; 应用场景举例&#xff1a; A、测…

项目中拖拽元素,可以使用html的draggable属性,当然也可以用第三方插件interact

项目中拖拽元素&#xff0c;可以使用html的draggable属性&#xff0c;当然也可以用第三方插件interact 一、安装二、引用三、使用 一、安装 npm install interactjs二、引用 import interact from interactjs三、使用 <div class"drag_box"> &…

如何公网远程连接本地群晖NAS中的WebDAV

文章目录 1. 在群晖套件中心安装WebDav Server套件1.1 安装完成后&#xff0c;启动webdav服务&#xff0c;并勾选HTTP复选框 2. 局域网测试WebDav服务2.1 下载RaiDrive客户端2.2 打开RaiDrive&#xff0c;设置界面语言可以选择中文2.3 点击添加按钮&#xff0c;新建虚拟驱动区2…

品牌媒介工作流程是什么,媒体投放目标怎么做?

品牌媒介其实说简单也很简单&#xff0c;说难也很难&#xff0c;简单在于其实事情流程简洁&#xff0c;难呢&#xff0c;在于很多东西如果不亲身体验是无法领悟到精髓的。今天为大家分享下品牌媒介工作流程是什么&#xff0c;媒体投放目标怎么做&#xff1f; 我们怎么才能在媒体…

2023年腾讯云双11活动云服务器价格表

2023年腾讯云双11活动已经拉开了序幕&#xff0c;腾讯云推出了一系列的优惠活动&#xff0c;下面给大家分享腾讯云双11活动云服务器价格表&#xff0c;对于有需要购买云服务器的用户来说&#xff0c;无疑是一份非常有价值的参考。 一、腾讯云双十一活动入口 活动入口&#xff…

2021-arXiv-The Power of Scale for Parameter-Efficient Prompt Tuning

2021-arXiv-The Power of Scale for Parameter-Efficient Prompt Tuning Paper: https://arxiv.org/abs/2104.08691 Code: https://github.com/google-research/ text-to-text-transfer-transformer/ blob/main/released_checkpoints.md# lm-adapted-t511lm100k 在这项工作中&…

14、Python -- 列表推导式(for表达式)与控制循环

目录 for表达式&#xff08;列表推导式&#xff09;列表推导式的说明使用break跳出循环使用continue忽略本次循环使用return结束函数 列表推导式 使用break跳出循环 使用continue忽略本次循环 for表达式&#xff08;列表推导式&#xff09; for表达式用于利用其他区间、元组、…

Telegram 引入了国产小程序容器技术

Telegram 宣布为其开发者提供了一项“能够在 App 中运行迷你应用”的新功能&#xff08; 迷你应用即 Mini App&#xff0c;下文中以“小程序”代替&#xff09;。 在一篇博客文章中&#xff0c;Telegram 的开发者写到“小程序提供了可替代互联网网站的灵活界面&#xff08;cre…