likes
comments
collection
share

Appium操控安卓模拟器快速上手 (python) 含双机运行或双应用可行方法

作者站长头像
站长
· 阅读数 30

Appium操控安卓模拟器快速上手 (python)

非系统性学习,只是为了快速开始用,我自己用途主要是写脚本操控模拟器(当然安卓真机也可以)干一些事情,所以对于跑测试用例的可能用处不大(虽然本来应该的用途是跑测试用例)。 写了一段时间这个了,想记录一下。也会加入一些写了一段时间脚本的小小经验,包括什么双应用切换啊之类的。

环境搭建

我当初是看的这个教程,写的非常好了,跟着一步步做就能把环境搭好了。 总结起来需要的就是:

  • Appium客户端(desktop或者控制台版本应该都行,不过为了要分析html结构还是得下个desktop的,控制台版本我自己用的不多,貌似没desktop那么占资源)
  • Java SDK (需要配JAVA_HOME环境变量)
  • Android Studio,并且在里面的SDK Manager安装Android SDK
  • 如果用模拟器那么需要安装模拟器,我比较喜欢雷电,因为adb很好连
  • 调试adb(如果是雷电的话,启动模拟器之后adb devices一下应该就可以看到设备了)(建议可以把adb也配进环境变量,以后控制台直接adb xxxcommand会方便一些)

环境上基本就这么多,然后就是面向具体app的问题了。adb之前我也接触过一点,我遇到过的问题列在下面:

  • 模拟器和电脑adb版本不一致:把模拟器的adb替换成之前Android Studio里下载好的就行(在platfrom tools之类名字的文件夹里),链接里的教程也有提到。不过雷电的话我没遇到过这个问题。
  • 无法检测到真机:要打开USB调试权限,反正能开的相关权限都开开
  • 无法检测到模拟器:链接里的教程也提到了一点,adb devices检测不到的话需要adb connect 127.0.0.1:portNumber,具体的端口号可以上网查查,包括多开的端口号也都是有规律的,写脚本没有问题。

Appium Desktop调试

我这里用酷我音乐演示,app版本不同可能html结构会有一些差异。 这部分链接里的教程也写清楚了的,准备一个apk,然后去模拟器的安装根目录,里面有aapt.exe,然后执行.\aapt.exe dump badging xxx.apk,找到package name和lunchable activity name,复制下来。 像这样在appium里填上session各参数。 Appium操控安卓模拟器快速上手 (python) 含双机运行或双应用可行方法

{
  "platformName": "Android",
  "platformVersion": "5.1.1",	// 填模拟器或者真机的安卓版本,设置里能看见
  "deviceName": "emulator", // 安卓的话这个参数没有用,随便填都可以
  "appPackage": "cn.kuwo.player",	// 上面找到的package name
  "appActivity": "cn.kuwo.player.activities.EntryActivity"	// 上面找到的lunchable activity name
}

appium里这样填就可以了,注意appium里最后一条后面不可以打逗号(py里随意) 然后appium里就能像浏览器里F12检查源代码一样看见html代码,也可以做一些操作,也有操作录制什么的。

小例子

这里用我之前写过的脚本的一小部分来看看吧,我们控制模拟器在里面检索一个关键词,就这么简单一件小事情。 在appium里可以很容易看到搜索框的信息,一步步跟过去(可以用操作录制)能轻易获取各元素的id或者xpath等信息,于是我们可以开始写代码了。

from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium.webdriver.common.touch_action import TouchAction
import time

# appium服务监听地址
server='http://localhost:4723/wd/hub'
# app启动参数,跟上面我们启动appium的是一样的
desired_caps={
  "platformName": "Android",
  "platformVersion": "5.1.1",
  "deviceName": "emulator",
  "appPackage": "cn.kuwo.player",
  "appActivity": "cn.kuwo.player.activities.EntryActivity"
}

引入相关库和启动参数,接下来继续写(这里就不写函数了)。

# 定义driver和wait
driver = webdriver.Remote(server,desired_caps) # 连上模拟器或者真机
wait = WebDriverWait(driver,15)	# 设置超时时间

# 这里应该是有一个弹窗广告,按ok
el1 = wait.until(EC.presence_of_element_located((By.ID,"cn.kuwo.player:id/tv_ok")))
el1.click()
time.sleep(2)

# 微博登录,现在可能不是这样了
ele_radio = wait.until(EC.presence_of_element_located((By.ID, "cn.kuwo.player:id/cb_protocol")))
if ele_radio.is_selected() == False:
	ele_radio.click()
ele_wb = wait.until(EC.presence_of_element_located((By.XPATH,"//android.widget.TextView[@content-desc=\"微博登录\"]")))
ele_wb.click()
ele_wb_panel = wait.until(EC.presence_of_element_located((By.XPATH,"/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.webkit.WebView")))
ele_wb_panel.click()
ele_username = wait.until(EC.presence_of_element_located((By.XPATH, "//android.webkit.WebView[@content-desc=\"登录 - 新浪微博\"]/android.view.View[2]/android.view.View[1]/android.widget.EditText[1]")))
ele_username.click()
time.sleep(0.3)
ele_username.send_keys(username)
ele_pw = wait.until(EC.presence_of_element_located((By.XPATH, "//android.webkit.WebView[@content-desc=\"登录 - 新浪微博\"]/android.view.View[2]/android.view.View[1]/android.widget.EditText[2]")))
ele_pw.click()
time.sleep(0.3)
ele_pw.send_keys(password)
ele_login = wait.until(EC.presence_of_element_located((By.XPATH, "//android.view.View[@content-desc=\"登录\"]")))
ele_login.click()
ele_login_sure = wait.until(EC.presence_of_element_located((By.XPATH, "//android.view.View[@content-desc=\"确认\"]")))
ele_login_sure.click()

# 搜索,主要是这部分
ele_search = wait.until(EC.presence_of_element_located((By.ID, "cn.kuwo.player:id/main_home_search")))
ele_search.click()
time.sleep(0.1)
# 防止没点上
try:
    ele_search.click()
except:
    pass
ele_search_box = wait.until(EC.presence_of_element_located((By.ID, "cn.kuwo.player:id/search_bar_et")))
ele_search_box.click()
ele_search_box.send_keys("关键词")
time.sleep(10)

# 退出driver,当然这段代码片段里不quit也没什么问题
driver.quit()

XPATH和ID都是appium我们start session之后自己操作一遍检查到的。 启动参数也可以有更多,具体的可以看appium官网,我自己会经常用到的有两个:

"noReset": "True",
"newCommandTimeout": "2000",

noReset默认是False,如果设为True的话,就会保留应用里的数据,这样就可以保留我们手动登录的登录状态,很多时候都很好用。 newCommandTimeout单位是秒,默认是一分钟还是两分钟,意思是没有任何操作多久之后就自动帮你关掉连接,如果需要在app上做比较长时间的等待操作建议把这个数改到很大,不然在等的过程中server就自己关了,并不是我们想要的效果。 所以如果加上noReset,上面的代码可以把登录部分都删掉直接搜索,当然具体版本具体分析。

双机

当然在本文的语境里是双模拟器,但是道理都是相通的嘛。(我也真没俩手机...) 还是引申上面的例子,看看怎么比较简单的启动两个模拟器。 最简单直观的方法就是开两个模拟器,开两个appium,然后启动两个脚本,这么做是可以实现的,但需要做出一些修改。

appium

首先,启动appium的时候我们一般是

Appium操控安卓模拟器快速上手 (python) 含双机运行或双应用可行方法 直接start。但是为了开双机,我们就不能这样了,去点Advanced看看。

拉到下面可以看见有一个port,默认是+1. Appium操控安卓模拟器快速上手 (python) 含双机运行或双应用可行方法

那么我们可以一个用4723+4724port,一个用4725+4726port来启动(simple或者advanced启动都可以,一样,配置是这样就可以)。

代码

代码也需要做一些调整,分为4723启动的和4725启动的两个代码,并且也要严格区分模拟器。先手动把两个需要的模拟器打开,打开控制台adb devices把两个模拟器的名字记下来(不行的话adb connect一下,多开模拟器端口规律网上一搜就是),我这里雷电模拟器的两个分别是emulator-5558和emulator-5560。 然后代码里我们唯一要做的调整只有这一段:

# appium服务监听地址
server='http://localhost:4723/wd/hub' # 另一份代码是4725
# app启动参数
desired_caps={
  "platformName": "Android",
  "platformVersion": "5.1.1",
  "deviceName": "dnplayer1",	// 安卓这个参数无所谓,不用管
  "appPackage": "cn.kuwo.player",
  "appActivity": "cn.kuwo.player.activities.EntryActivity",
  "udid": "emulator-5560",	// 另一份代码是emulator-5558
  "systemPort": 4724	// 另一份代码是4726
}

然后就可以愉快的双开了,多开道理也都是一样的,重要的就是udid和两个端口号。

双应用

当然,多应用也是一样。这里简单的写两个可行的方法(不一定多标准但可行)。

driver.start_activity()

官网描述 其他像上面一样,需要打开一个新应用的时候drvier.start_activity(package_name, activity_name)就可以,要跳回原来的应用就再调用一次填上原来应用的参数。

双driver

因为我想在模拟器里用加速器之类的这种会对ip地址有影响的软件,所以用上面的方法的时候我就会发现加速器一打开,再试图调用当前driver干什么的话就会报错,查了很久也没有结果,最后抱着试一试的心态发现直接用两个driver就可以了,需要哪个driver打开哪个driver,另一个就挂在那就行,不要driver了就quit,很舒服。(当然其实只是规避了加速后driver就“失效”的问题,那个软件的driver还是不能用的,但是另一个应用的driver就没有任何问题)

转载自:https://juejin.cn/post/6929397311021776903
评论
请登录