折腾:
【未解决】iOS自动化安装app:给当前WiFi去掉代理以及自动安装app后再恢复之前代理
期间,调试期间遇到一个情况:
【未解决】iOS自动化操作设置出错:启动设置后找不到无线局域网
调试遇到问题:

[200611 13:38:53][DevicesMethods.py 856] Not found element {'type': 'XCUIElementTypeStaticText', 'name': '无线局域网', 'enabled': 'true', 'parent_class_chains': ["/XCUIElementTypeCell[`name = '无线局域网' AND rect.x = 0 AND rect.width = 414`]"]}背景是:之前已打开了设置,此时不是 设置的首页 而是 无线局域网 的列表页:

所以,要去想办法避免此问题。
为了完全避免,感觉最好是:
启动 设置之前,完全关闭掉设置
否则设置 还可能处于其他页面,也会遇到不支持的情况
此处启动
com.apple.Preferences
之前,先去完全stop停止,要去找找代码如何写,是否有这方面的接口
# terminate app
c.session().app_terminate("com.apple.Health")去试试
先去看了看代码
/Users/xxx/.pyenv/versions/3.8.0/Python.framework/Versions/3.8/lib/python3.8/site-packages/wda/__init__.py
def app_launch(self,
。。。
def app_activate(self, bundle_id):
return self._session_http.post("/wda/apps/launch", {
"bundleId": bundle_id,
})
def app_terminate(self, bundle_id):
return self._session_http.post("/wda/apps/terminate", {
"bundleId": bundle_id,
})
def app_state(self, bundle_id):
。。。写代码
iOS_AppId_Settings = "com.apple.Preferences" # stop before start to avoid current page is not homepage of 设置 self.wdaClient.session().app_terminate(iOS_AppId_Settings)
调试看看
结果并没有用:
启动后,还是处于:无线局域网 列表页
所以,此处app_terminate并没有关闭掉app
再去试试
self.wdaClient().app_terminate(iOS_AppId_Settings)
结果:
File "/Users/xxx/dev/xxx/crawler/appAutoCrawler/AppCrawler/venv/lib/python3.8/site-packages/wda/__init__.py", line 1703, in __getattr__ return getattr(element, oper) AttributeError: 'Element' object has no attribute 'app_terminate'
报错,不支持。
参考
# get app state
c.session().app_state("com.apple.Health") 先去看看,此处的 设置 是否的确是 正在运行,且处于 后台
突然发现之前写法是:
src/common/MainUtils.py
# self.wdaClient.session().app_terminate(self.appPackage) self.wdaClient.app_terminate(self.appPackage)
所以此处去改为:
self.wdaClient.app_terminate(iOS_AppId_Settings)
结果:
问题依旧。
还是去获取 设置 的当前状态,比较确定
curState = self.iOSGetAppState(iOS_AppId_Settings)
logging.info("curState=%s", curState)
def iOSGetAppState(self, appBundleId):
"""get iOS app state"""
curAppState = self.wdaClient.app_state(appBundleId)
logging.debug("curAppState=%s", curAppState)
# -> 发生异常: TypeError, not all arguments converted during string formatting
# curAppStateValue = curAppState["value"]
# -> 发生异常: TypeError, tuple indices must be integers or slices, not str
# curAppStateValue = curAppState["value"]
"""
{
"value" : 4,
"sessionId" : "5BBD460B-F420-461D-A5E3-244A74CDF5CE"
}
"""
curAppStateValue = curAppState[0]
logging.debug("curAppStateValue=%s", curAppStateValue)
curStateEnum = ApplicationState(curAppStateValue)
logging.debug("curStateEnum=%s", curStateEnum)
return curStateEnum调试
# <GenericDict, len() = 3>
# curAppStateValue = curAppState[0]
curAppStatus = curAppState.status
curAppSessionId = curAppState.sessionId
logging.debug("curAppStatus=%s, curAppSessionId=%s", curAppStatus, curAppSessionId)
curAppStateValue = curAppState.value
logging.debug("curAppStateValue=%s", curAppStateValue)
curStateEnum = ApplicationState(curAppStateValue)
logging.debug("curStateEnum=%s", curStateEnum)
<ApplicationState.RunningBackgroundSuspended: 2>
表示是在运行,但是是在后台 被暂停了
curState=ApplicationState.RunningBackgroundSuspended
那去手动杀掉,看看返回结果如何
此处,遇到之前问题:
当杀掉 设置 的app,重新调试时,结果wda的client就报错,连不上了。
-》推断是,确定是:杀掉最近运行的app,比如 AppStore,设置等,重新调试时,wda的挂了。
其中log中会显示:
t = 1822.22s Requesting snapshot of accessibility hierarchy for app with pid 52 2020-06-11 14:08:31.570725+0800 WebDriverAgentRunner-Runner[9228:3611864] Getting the most recent active application (out of 1 total items) 2020-06-11 14:10:48.151681+0800 WebDriverAgentRunner-Runner[9228:3611864] Getting the most recent active application (out of 1 total items)
即:
Getting the most recent active application (out of 1 total items)
只能重启wda的test manager才可以

<ApplicationState.NotRunning: 1>
就是:没有运行,是对的。
再去启动试试
结果:启动后,还是无线局域网列表页
-》说明是:
不是之前 设置 没有被关闭掉,而是之前退出最后的页面是 无线局域网的列表页
-》反推:要确保之前 设置 被关闭时,退出时,要处于 主页,而不能是其他页面
否则后续,即使已完全关闭了 设置,重新打开时,都会保留在 之前页面
此处之前页面是 无线局域网列表页,所以就是处在 无线局域网列表页,而不是我们希望的:设置的主页。
此处故意再去试试:
杀掉 设置时,处于:通用 页面,重新去启动,看看是否处于:通用 页面
手动点击时,是不会的,是会进入主页的。
换代码启动试试,也是没问题,会进入主页的。
那看来是:
对于 无线局域网页面,很特殊,杀掉之前,如果处于 无线局域网列表页,重启后就会进入 这个 无线局域网列表页
也看来 手动和 代码启动,效果是一样的
那手动多去测试测试其他情况
无线局域网列表页 和 WiFi详情页 杀掉后,重启设置,都不会进入之前页面,都还是 设置主页
所以,之前很是奇怪,为何会进入后,直接进入 无线局域网列表页
先去测另外的:
代码中 设置 后台运行,关闭掉,看看状态十分变化
[200611 14:21:57][DevicesMethods.py 2589] before terminal: curState=ApplicationState.RunningBackgroundSuspended [200611 14:21:59][DevicesMethods.py 2596] after terminal: curState=ApplicationState.NotRunning
是可以干掉的
启动后,结果:又是进入 无线局域网列表页。。。
奇怪了。
去参考:
# launch without terminate app (WDAEmptyResponseError might raise)
c.session().app_activate("com.apple.Health") # same as app_launch试试app_activate或,找找是否有app_launch
从注释看:app_launch会先terminate app,再launch
之前代码也看到是有的:app_launch的
所以去试试
另外注意到
/Users/xxx/.pyenv/versions/3.8.0/Python.framework/Versions/3.8/lib/python3.8/site-packages/wda/__init__.py
def deactivate(self, duration):
"""Put app into background and than put it back
Args:
- duration (float): deactivate time, seconds
"""
return self._session_http.post('/wda/deactivateApp', dict(duration=duration))有 非激活 app,像是按home,让app进入后台运行
后续有空需要用到,再去试试
不过这次的:
[200611 14:26:47][DevicesMethods.py 2589] before terminal: curState=ApplicationState.RunningForeground [200611 14:26:48][DevicesMethods.py 2596] after terminal: curState=ApplicationState.NotRunning
干掉后,再去代码的launch启动,至少是进入设置主页了。
多测试其他情况试试
期间,去解决:
【已解决】Python代码logging打印报错:TypeError not all arguments converted during string formatting
此处,先去terminate,再去launch,貌似很稳定:确保启动后可以进入设置主页,而不是 之前的 无线局域网的列表页
再多测试看看
另外,再去:
【已解决】整理和优化facebook-wda的app管理相关通用功能和函数
【总结】
至此,启动 设置 之前,先去 terminate终止 设置(如果有,不管是 前台运行,还是 后台运行 的 设置 的话),再去launch启动,即可确保启动后的 设置,是设置主页,而不会是之前,偶尔会出现的 无线局域网列表页 了。
相关代码:
def iOSGetAppState(self, appBundleId):
"""get iOS app state
Args:
appBundleId (str): iOS app bundle id
Returns:
bool, enum/dict:
true, app status enum
false, error info dict
Raises:
"""
curAppState = self.wdaClient.app_state(appBundleId)
logging.debug("curAppState=%s", curAppState)
"""
{
"value" : 4,
"sessionId" : "5BBD460B-F420-461D-A5E3-244A74CDF5CE"
}
"""
# # <GenericDict, len() = 3>
# # curAppStateValue = curAppState[0]
# # curAppStatus = curAppState.status
# # curAppSessionId = curAppState.sessionId
# # logging.debug("curAppStatus=%s, curAppSessionId=%s", curAppStatus, curAppSessionId)
# curAppStateValue = curAppState.value
# logging.debug("curAppStateValue=%s", curAppStateValue)
# curStateEnum = ApplicationState(curAppStateValue)
# logging.debug("curStateEnum=%s", curStateEnum)
# return curStateEnum
isGetOk, respInfo = self.processWdaResponse(curAppState)
if isGetOk:
respValue = respInfo
curStateEnum = ApplicationState(respValue)
logging.debug("curStateEnum=%s", curStateEnum)
respInfo = curStateEnum
return isGetOk, respInfo
def iOSTerminateApp(self, appBundleId):
"""Terminate iOS app
Args:
appBundleId (str): iOS app bundle id
Returns:
bool, bool/str:
true, bool
True: terminal Ok
False: terminal fail
eg: current not running 设置, if terminal, return False
false, str: error message
Raises:
"""
# isTerminalOk = False
# respInfo = None
# self.wdaClient.session().app_terminate(appBundleId)
# self.wdaClient().app_terminate(appBundleId)
terminateResp = self.wdaClient.app_terminate(appBundleId)
logging.debug("terminateResp=%s", terminateResp)
# respStatus = resp.status
# respValue = resp.value
# respSessionId = resp.sessionId
# logging.info("respStatus=%s, respValue=%s, respSessionId", respStatus, respValue, respSessionId)
# if respStatus == 0:
# isTerminalOk = True
# respInfo = None
# else:
# errInfo = {
# "status": respStatus,
# "value": respValue,
# }
# respInfo = errInfo
isTerminalOk, respInfo = self.processWdaResponse(terminateResp)
return isTerminalOk, respInfo
def iOSLaunchApp(self, appBundleId):
"""Launch iOS app
Args:
appBundleId (str): iOS app bundle id
Returns:
bool, None/str:
true, None
false, str: error message
Raises:
"""
launchResp = self.wdaClient.app_launch(appBundleId)
logging.debug("launchResp=%s", launchResp)
isLaunchOk, respInfo = self.processWdaResponse(launchResp)
return isLaunchOk, respInfo
def processWdaResponse(self, wdaResponse):
"""Process common wda (http post) response
Args:
Returns:
bool, ?/dict:
true, response value
false, error info dict
Raises:
"""
isRespOk = False
respInfo = None
logging.debug("wdaResponse=%s", wdaResponse)
respStatus = wdaResponse.status
respValue = wdaResponse.value
respSessionId = wdaResponse.sessionId
logging.debug("respStatus=%s, respValue=%s, respSessionId", respStatus, respValue, respSessionId)
if respStatus == 0:
isRespOk = True
respInfo = respValue
else:
isRespOk = False
errInfo = {
"status": respStatus,
"value": respValue,
"sessionId": respSessionId,
}
respInfo = errInfo
return isRespOk, respInfo
def settingsDisableWiFiProxy(self):
"""in settings, find current WiFi, find and disable its proxy if existed
Args:
Returns:
bool, dict/str:
true, proxy info dict: found and disable proxy OK, return proxy info
if no proxy, proxy info dict is empty
false, str: occure some error, return error message
Raises:
"""
isProcessdOk = False
respInfo = None
iOS_AppId_Settings = "com.apple.Preferences"
isGetOk, curState = self.iOSGetAppState(iOS_AppId_Settings)
logging.info("before terminal: curState=%s", curState)
# stop before start to avoid current page is not homepage of 设置
isTerminalOk, respInfo = self.iOSTerminateApp(iOS_AppId_Settings)
logging.info("isTerminalOk=%s, respInfo=%s", isTerminalOk, respInfo)
isGetOk, curState = self.iOSGetAppState(iOS_AppId_Settings)
logging.info("after terminal: curState=%s", curState)
# settingsSession = self.wdaClient.session(iOS_AppId_Settings)
# logging.debug("settingsSession=%s" % settingsSession)
# launchResult = self.wdaClient.app_launch(iOS_AppId_Settings)
# logging.debug("launchResult=%s", launchResult)
isLaunchOk, respInfo = self.iOSLaunchApp(iOS_AppId_Settings)
logging.info("isLaunchOk=%s, respInfo=%s", isLaunchOk, respInfo)
# logging.info("launchResult: value=%s, status=%s, sessionId=%s", launchResult.value, launchResult.status, launchResult.sessionId)
# launchResult: value=None, status=0, sessionId=79A39B72-F5F9-4A01-8E58-DD380452350A
# logging.info("launchResult=%s", str(launchResult))
# launchResult=GenericDict(value=None, sessionId='79A39B72-F5F9-4A01-8E58-DD380452350A', status=0)
即可。
【后记 20200611】
折腾:
【未接】iOS自动化处理WiFi代理:配置代理页中从关闭切换到手动恢复之前代理配置信息
期间,已经实现了 强制关闭 设置,再重新启动,结果:

[200611 18:21:54][DevicesMethods.py 2177] isTerminalOk=True, respInfo=True
[200611 18:21:56][DevicesMethods.py 856] Not found element {'type': 'XCUIElementTypeStaticText', 'name': '无线局域网', 'enabled': 'true', 'parent_class_chains': ["/XCUIElementTypeCell[`name = '无线局域网' AND rect.x = 0 AND rect.width = 414`]"]}
[200611 18:21:56][DevicesMethods.py 856] Not found element {'type': 'XCUIElementTypeStaticText', 'name': '无线局域网', 'enabled': 'true', 'parent_class_chains': ["/XCUIElementTypeCell[`name = '无线局域网' AND rect.x = 0 AND rect.width = 414`]"]}
[200611 18:21:56][DevicesMethods.py 856] Not found element {'type': 'XCUIElementTypeStaticText', 'name': '无线局域网', 'enabled': 'true', 'parent_class_chains': ["/XCUIElementTypeCell[`name = '无线局域网' AND rect.x = 0 AND rect.width = 414`]"]}
[200611 18:21:56][DevicesMethods.py 856] Not found element {'type': 'XCUIElementTypeStaticText', 'name': '无线局域网', 'enabled': 'true', 'parent_class_chains': ["/XCUIElementTypeCell[`name = '无线局域网' AND rect.x = 0 AND rect.width = 414`]"]}
[200611 18:21:57][DevicesMethods.py 856] Not found element {'type': 'XCUIElementTypeStaticText', 'name': '无线局域网', 'enabled': 'true', 'parent_class_chains': ["/XCUIElementTypeCell[`name = '无线局域网' AND rect.x = 0 AND rect.width = 414`]"]}
[200611 18:21:57][common_utils.py 654] Still fail after 5 retry for <bound method DevicesMethods.iOSFromSettingsIntoWifiList of <src.AppCrawler.AppCrawler object at 0x1027fbeb0>>情况是:
很明显,前面是terminate 成功了,但是,现在重新launch设置,但是设置却还是一进来就是: 无线局域网列表页
所以:此处有问题
设置 很可能就会 直接进入 无线局域网列表页
实在不行,可以去:
加上额外判断,如果进来的是 无线局域网页,也能支持
但是就是有点觉得诡异:
为何有时候就会出现这种:
启动设置后 直接进入 无线局域网 列表页
但是也懒得研究原因了。因为也找不到原因。
对了,要不去:
更改了WiFI的配置后,直接terminate干掉设置
看看是否会出现这个问题
# Note: after save, terminal Settings, try to avoid re-launch directly into WiFi list page
iOS_AppId_Settings = "com.apple.Preferences"
isTerminalOk, respInfo = self.iOSTerminateApp(iOS_AppId_Settings)
logging.info("isTerminalOk=%s, respInfo=%s", isTerminalOk, respInfo)去试试。
算了,不用试了。
先去支持:
【已解决】iOS自动化设置WiFi:如何启动设置并判断进入WiFi列表页
如此,即可实现:
启动 设置
如果(异常的)已经处于 WiFI列表页,则返回
如果 正常的 处于设置首页,再去找到并点击 无线局域网 进入 WiFi列表页,即可。
转载请注明:在路上 » 【已解决】iOS自动化操作设置出错:启动设置后找不到无线局域网