python脚本处理Android安装启动卸载app(二)

195 阅读3分钟

「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。

APPIUM环境搭建

首选python变成语言+appium依赖库+Appium-python-Client客户端

  • Java JDK必不可少
  • Android-SDK
  • Nodejs环境(因为appium客户端是node开发的)
npm install -g appium
    • 在上面appium报错的时候,根据提示安装对应的版本:.net framework 4.5
  • APPIUM服务端
(appium) C:\Users\qguan>appium
[Appium] Welcome to Appium v1.18.0
[Appium] Appium REST http interface listener started on 0.0.0.0:4723
  • python安装appium客户端
pip install Appium-python-Client
  • 下载夜神模拟器,Android版本比较高,可能一些公司会抛弃低版本的Android客户端
# 夜神模拟器,在bin目录下将nox_adb重命名,或者将SDK的adb.exe覆盖到夜神bin目录下
夜神端口默认:62001
逍遥端口默认:21503

注意事项

时常在使用模拟器或真机做自动化的时候,会出现异常报错:找不到设备,经确认adb devices是有检测到的;也能adb connect连接正确,就是会突然找不到。

执行脚本时,注意:先启动appium服务器,否则会连接不到服务器找不到设备;然后需要connect连接模拟器;执行完之后,建议进行关闭操作。

Python代码示例

参考bat示例,先清楚要做什么再做什么,但是在Python中,可能需要稍微调整一下执行顺序,找到或拼接apk的绝对路径先存起来,然后再依次遍历,对于appium工具会有所不同,这是bat所不具备的,需要设置(模拟器或真机)设备和app的参数属性,然后再创建远程连接对象,启动app和卸载,然后再启动后还可以进行app功能点击事件。

  • desired_caps属性
caps = {}
caps["platformName"] = "Android"
caps["platformVersion"] = "9" # 这个很重要,测试设备的Android版本号
caps["deviceName"] = "127.0.0.1:4723" # 模拟器有各自的默认端口,而真机的默认端口是从4723递增的
# selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: 'app' option is required for reinstall
caps["app"] = None # apk包路径,在设备没有时,会自动安装
caps["appPackage"] = "com.chutzpah.yasibro" # 应用包名,可以用来检查设备已安装
caps["appActivity"] = "com.chutzpah.yasibro.main.view.MainActivity"
caps["automationName"] = "UIAutomator2"
caps["resetKeyboard"] = True
caps["unicodeKeyboard"] = True
caps["noReset"] = True # 表示默认app原有的数据,如果是每次安装则无效False
  • 找到apk包并存储绝对路径
# 拼接apk包路径
BASEDIR = os.path.dirname(os.path.dirname(__file__))
APKPATH = os.path.join(BASEDIR, "10.40.0")

# 遍历获取apk绝对路径
APKFILES = []
for root, _, files in os.walk(APKPATH):
    for file in files:
        APKFILES.append(os.path.join(root, file))
  • 启动appium后台服务并创建adb连接设备
# 启动appium服务
subprocess.call("start /b appium", shell=True)
# 连接设备
os.popen("adb connect {}".format(caps["deviceName"]))
  • 执行app对应操作之后 ,应关闭appium服务并断开adb连接
def stop_appium(port=4723):
    """释放指定的端口"""
    cmd_find = 'netstat -aon | findstr %s' % port
    result = os.popen(cmd_find).read().split()[-1]
    if result:
        cmd_kill = 'taskkill -f -pid %s' % result
        os.popen(cmd_kill)
        
# 关闭服务
stop_appium()

# 设备断开连接
os.popen("adb disconnect {}".format(caps["deviceName"]))
  • app的操作流程就是遍历apk包,然后创建连接对象,最后卸载
# 遍历apk路径,依次启动-卸载-再启动
for APKFILE in APKFILES:     
    caps["app"] = APKFILE
    driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps)
    
    # 这个中间部分,可以实现app部分功能操作,以便真实达到生产apk包的走查效果
    
    INSTALLED = driver.is_app_installed(caps["appPackage"])
    if not INSTALLED: # 这段代码块基本不会执行
        driver.install_app(APKFILE)
        print("需要安装")
    else:
        driver.remove_app(caps["appPackage"])
        print("卸载APP")
    sleep(2)
    driver.quit()
  • 进入SDK\tools\bin目录下双击uiautomatorviewer就可以对app的界面进行元素查找 在这里插入图片描述

总结

整个代码部分和环境部署环节,最难的估计就是环境搭建了,因为它不同的设备(虚拟、真机)从连接和设置上都有很大区别,有些不一定都适用,所以才很难调试。但是苦心人天不负,最终还是被题主调试出来了,然后对于这些操作都需要去思考的,题主原本搭建的框架,再从头看代码都有些不知所以,当初是怎么写的、怎么实现的,为啥过了一段时间不维护它就不行呢?