Appium appium+python 解决安装权限弹窗

A308寝帅 · 2018年09月08日 · 最后由 xiakexing 回复于 2018年09月20日 · 1769 次阅读

今天说说当今主流的自动化UI测试框架之一的appium使用总结,其中卡的我比较久的是被测App的安装时手机弹出的权限弹窗问题,主要说下解决方案。

之前也接触过网易的airtest project,uiautomator2等自动化测试框架, appium相对要麻烦一些,需要很多手机设备信息,包括被测App的信息。
appium主要的问题就在于它的设计就是建立在手机已经安装好了被测App的,它初始化连接设备需要打开指定App,而手动去安装被测App时很low的方式,一般来说我们会想到用 脚本去点击“同意弹窗”,但appium没初始化完成时是无法使用click方法的。

看过网上一些解决方案,说说我的实践效果:
1,采用adb点击弹窗“同意”坐标方式。
效果不佳,而且手机众多,很多手机的询问弹窗位置不一样,不建议使用。
2,通过adb 先把被测apk文件push到手机指定文件夹,再用db shell pm install 安装。
网上说能解决部分手机(不出现询问弹窗),但我使用的小米,华为等依然有弹窗。可能是手机原因不用吧。 多与做设备集群的自动化测试的来说,这种依然不行。
3,首次安装人工点击,测试完成后不卸载,后续App版本用自动化脚本测试时采取覆盖安装。
覆盖安装不会出现询问弹窗(我测的小米是这样),这种方式就只low一次,后续还好吧。,
4,采用其他框架如uiautomator2的脚本,在appium是初始化安装App时,点击掉询问弹窗。
可行,但入手门槛高。
5,下面介绍我使用的这种方案,如下:
因为appium需要先打开一个App才能完成初始化,所以我们可以在配置参数中不配置我们被测的App,可以配置一些很小的App信息,且必须是每部手机上都会安装的。刚好,使用appium在设备与服务端通信,会在设备上安装一款叫appium setting的很小的App。
因此,我们可以参数里配置它,完成初始化后,再用adb或者appium提供的安装函数去安装实际被测App,再使用多线程去点击掉询问弹窗。代码如下:

#配置appium srtting为被测App
desired_caps = {}
desired_caps['platformName']='Android'
desired_caps['deviceName']='huawei-stf_al00-8BN0217930000453'
desired_caps['paltformVersion']='8.0.0'
desired_caps['appPackage']='io.appium.settings'
desired_caps['appActivity']='io.appium.settings.Settings'
desired_caps['autoGrantPermissions']= True
drive = webdriver.Remote('http://localhost:4723/wd/hub,desired_caps')
#再安装真实被测App,利用线程点击掉询问弹窗
thread1 = usb_install_thread() #这是点击弹窗的线程
thread1.start()
drive.install_app(hGoName)

好,到此结束。喜欢的点个赞吗,谢谢大家。

共收到 33 条回复 时间 点赞

这思路挺赞的,上次Jonathan来中国参加MTSC2018大会的时候其实也跟恒温、恒捷和我讨论过这个问题。他们也在想办法改进这块,我给的建议是把启动uiautomator2的过程提前到安装apk之前。 你这个方法也是挺赞的,也算是独辟蹊径。不过楼主把代码格式调整下吧。。。

usb_install_thread()点击弹窗的方法实现内容是什么呢?
另外有些设备的ROM安装io.appium.settingsio.appium.settings.Settings两个守护进程都强制必须用户手动确认才能安装。😅

安装U2之前,可以启动U1来解决弹窗问题,安装完成后再把U1关掉就完事

分叉1个线程去做了Ui自动化点那个。

Sutune 回复

class usb_install_thread(threading.Thread): # 安装确认
def init(self):
threading.Thread.init(self)

def run(self): # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
usb_install()

def usb_install():
while True:
if flag == False:
break
try:
em = drive.find_element_by_xpath("//android.widget.Button[contains(@text,'继续安装')]")
if em:
em.click()
except:
pass
try:
em =drive.find_element_by_xpath("//android.widget.Button[contains(@text,'允许')]")
if em:
em.click()
except:
pass
try:
em = drive.find_element_by_xpath("//android.widget.Button[contains(@text,'确认')]")
if em:
em.click()
except:
pass

这是个python的线程,用来判断出现“允许”“确认”等弹窗的,因为每个手机的可能不通,但大概就这几种,加判断就可以了

Sutune 回复

这两个是手机与服务端通信用的,这个就属于appium自身的需求了,可以采用上树方案4 去用uiautomator2的脚本的脚本循环判断点击,但是有点麻烦,得编写人员会这两个框架,还得搭环境

好的 谢谢 刚开始用这个还不大会 将就看下吧 代码很简单 大家应该能看懂的

李海默 回复

跟方案4差不多 不过有点麻烦哦

陈子昂 回复

当然是用线程去点击,问题在于用线程去点击得先完成初始化,才能用click吧? 而appium配置参数里得先指定App,打开后才算完成初始化,那么打开App,说明已经安装上了, 实际上初始化安装App时,线程根本没法用appium的click操作,之前大多采用的是另外用uiautomator的脚本在appium初始化前循环检测点击,这样得启俩服务,编写uiautomator的脚本,有点麻烦的

哇,一下子解决了困扰我多时的问题,还有一个问题就是如何启动安装包?通过usb安装软件是有权限的,很多手机一般不得行

还有我要测多部手机,手机信息可以从数据库中读到,那可以配置Appnium自动安装软件给权限吗?同一个软件安装包在不同手机上名称会变吗

红客联盟 回复

如何启动安装包?不论你的安装包在手机还是电脑都可以用adb命令去安装,usb安装权限问题,我这篇文章就是解决这个的, appium不能配置自动给软件安装权限,权限是系统的, 同一个安装包在不同手机上包名是一样的

A308寝帅 回复

那这个有点麻烦的就是有的厂商的手机,对USB启动安装限制很严,通过usb不能自动安装,比如vivo

红客联盟 回复

我文章中讲了如何解决这个安装权限问题的,uiautomator的话直接写个线程,循环检查就ok,线程代码也在评论区给了,appium有点不同,解决方案自己看文章吧,很详细了

A308寝帅 关于 USB 安装安卓软件权限问题 中提及了此贴 09月10日 11:43
A308寝帅 Appium 安装、启动 app 权限弹框问题 中提及了此贴 09月10日 11:45
A308寝帅 回复

您的文章认真拜读了,您说的权限是安装软件启动后需要获取的权限,我的意思是很多厂商直接限制了安装包的启动,也就是通过usb根本无法启动安装软件,自然也就没有后续的权限弹框选择

红客联盟 回复

我说的是安装软件时的权限(安装时手机弹窗“是否允许安装,不是从应用市场下载的。。。等等警告,需要人工确认”),不是安装后首次启动的权限,usb怎么会无法安装呢?安卓手机不像iOS吧,是允许用户自己安装软件的,只不过是要出现 警告/确认弹窗的

红客联盟 回复

对 您也可以使用appium的 安装函数去安装试试,我这边都可以哎,只是弹窗问题解决就行了

mark一下,感谢分享

提示找不到这个软件包

能够不用appnium框架,只进行ui点击操作手机端权限吗

红客联盟 回复

用UI2来做自动化脚本也可以啊 ,其实个人感觉UI2更简单,UI2连接设备只需要device号,连接后用的多线程点击也可以的,UI2的框架如何使用可以去官方学习下

红客联盟 回复

你用adb安装怎么会找不到呢?adb安装好像有3种还是4种方式呢,你可以直接从电脑里安装到手机啊
os.system("adb install -r " + hGoName) gGoName是apk文件在电脑的地址,这只是一种方式哈,当然,很多手机会有弹窗的

A308寝帅 回复

我是说appnium安装找不到你哪个包

用UI2开启多线程前几次还可以click到按钮,后边就click不到了哇,线程学你的做了判断和异常处理的

if flag == False:
break
这个flag标志位是依据什么设置的呢,大佬

红客联盟 回复

我这个线程不是只为了点一部手机,是为了点掉多不手机的弹窗,而多部手机的弹窗文字都不一样,所以做了判断,判断有就点,没有就下一个判断,异常处理是有时候没点到不至于脚本报错(有的手机会有弹窗时间,10秒内不点就消失,有时候会错过)。

红客联盟 回复

if flag == False:
break 这是个开关,在脚本开头 你要先写句flag = Ture , 这时线程会循环判断 有没有方法里写的那几个弹窗, 当你觉得脚本某阶段不需要线程点击了(安装完成),你就写句flag = False 线程循环检测到flag = False时 ,就停止了

A308寝帅 回复

这个原理我知道,我只是想了解一下你那边是如何判断脚本不需要点击了的,这个很关键

红客联盟 回复

这个你可以一直监控到你进入App,根据情况来使用吧,安装这块的线程你就可以当进入App后就关闭掉

解决了一个顽疾啊,有时间自己试试。
还有一个问题,想问下,用python的os安装包的时候,adb每执行一次,感觉下次执行还是需要初始化,之前用airtest的时候,多次调用单个的adb命令会出问题
比如说我清除包的数据(模拟了次卸包重装),做了一件事,之后再掉接口去安装一个渠道包,这个时候它就超时了,看后台一堆5037的进程,
想问问有什么办法能像在命令台一样,只要连接没断开,下次可以直接执行adb命令呢

郎佳星 回复

呃呃 这个问题我还没遇到过呢 我这边多次调用adb命令没问题的 你检查下你的版本这些 用最新的试试吧 我没遇到过这个问题哦

整个service去弄这些事情也是不错的

看起来不错,赞一个~

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册