123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938 |
- # -*- coding:utf-8 -*-
- import time
- from ssat_sdk.ocr_convert import OCRConvert
- from ssat_sdk.device_manage.capturecard_manager import CCardManager
- from ssat_sdk.uiautomator2.ext import htmlreport
- # from uiautomator2.ext import htmlreport
- from ssat_sdk import uiautomator2 as u2, LoggingUtil, inspect, FeatureDetect, sat_environment, getSATTmpDIR, ImageCMP
- from ssat_sdk.UATree.UAT_tree import UATTree
- from ssat_sdk.tv_operator import TvOperator
- # import uiautomator2 as u2
- import os
- import re
- from ssat_sdk.utils import LoggingUtil
- from ssat_sdk.utils.string_util import getDigitFromString
- from ssat_sdk.sat_environment import getAdbDeviceSatatus
- pyFileName = os.path.split(__file__)[-1]
- def get_current_function_name():
- return inspect.stack()[1][3]
- '''
- 预置条件:保证执行PC和测试电视adb连接
- 各个API说明的例子中到达self.pyUIAutomator 是PyUIAutomator类的实例
- self.pyUIAutomator = PyUIAutomator()
- '''
- class PyUIAutomator():
- def __init__(self, serial=None):
- try:
- self.u = u2.connect_usb(serial)
- self.serial = serial
- except Exception,e:
- print e
- # hrp = htmlreport.HTMLReport(self.u, 'report')
- # try:
- # hrp.patch_click()
- # except Exception, e:
- # print e
- # pass
- # self.u.app_stop_all()
- def reConnect_usb(self):
- self.u = u2.connect_usb(self.serial)
- # hrp = htmlreport.HTMLReport(self.u, 'report')
- # try:
- # hrp.patch_click()
- # except Exception, e:
- # print e
- # pass
- # self.u.app_stop_all()
- def checkAdbConnected(self):
- return u2.check_adb_connect()
- def listenAdbConnected(self):
- count = 5
- while getAdbDeviceSatatus() is False and count >0:
- count -= 1
- LoggingUtil.printLog("PyUIAutomator","listenAdbConnected,Count %d adb not connected!"%count)
- # self.reConnect_usb()
- time.sleep(1)
- def getAdbType(self):
- return u2.check_adb_connect_type()
- '''
- 作用:获取UIAutomator 连接对象 后续可以使用该对象使用原生方法
- '''
- def getPyUIAutomator(self):
- self.listenAdbConnected()
- return self.u
- '''
- 作用:Android times次按键 key:常用按键的字符串
- 主要的键值字段:home、back、left、right、up、down、center、menu、search、enter、delete ( or del)、
- recent (recent apps)、volume_up、volume_down、volume_mute、camera、power
- times :按键次数 默认为1次
- duration:按键时间间隔 默认为1.0s
- '''
- def pressKeyTimes(self, key, times=1, duration=1.0):
- self.listenAdbConnected()
- self.u.pressKeyTimes(key, times, duration)
- '''
- 作用:获取UiObject对象
- 参数:
- className:控件类型(例如:android.widget.TextView)
- resourceId:控件的Id(例如:lh.oslauncher:id/tv_title)
- text:控件上的文件(例如:'主页')
- description:控件描述
- instance:实例参数
- 注意:className、resourceId、text 、description、instance是利用
- UIautomatoview.bat工具查看控件属性看到的
- 其中 className对应 UIautomatoview.bat中的 class
- resourceId对应 UIautomatoview.bat中的 resource-id
- description对应 UIautomatoview.bat中的 content-desc
- instance对应 UIautomatoview.bat中的 index
- 例子:uiObject =self.pyUIAutomator.getUiObject(resourceId="com.google.android.tvlauncher:id/banner_image", description=u"Play 电影", className = 'android.widget.ImageView')
- '''
- def getUiObject(self, className='', resourceId='', text='', description='', instance=-1):
- self.listenAdbConnected()
- # print 'className:', className
- # print 'resourceId:', resourceId
- # print 'text:', text
- # print 'description:', description
- # print 'instance:', instance
- uiObject = None
- try:
- if className == "" and resourceId == "" and text == "" and description == "" and instance == -1:
- print "没有参数带入,找不到对象"
- return uiObject
- if className != "" and resourceId != "" and text != "" and description != "" and instance != -1:
- uiObject = self.u(className=className, resourceId=resourceId, text=text, description=description,
- instance=instance)
- # 缺少一个元素的
- if className != "" and resourceId != "" and text != "" and description != "" and instance == -1:
- uiObject = self.u(className=className, resourceId=resourceId, text=text, description=description)
- if className != "" and resourceId != "" and text != "" and description == "" and instance != -1:
- uiObject = self.u(className=className, resourceId=resourceId, text=text, instance=instance)
- if className != "" and resourceId != "" and text == "" and description != "" and instance != -1:
- uiObject = self.u(className=className, resourceId=resourceId, description=description,
- instance=instance)
- if className != "" and resourceId == "" and text != "" and description != "" and instance != -1:
- uiObject = self.u(className=className, text=text, description=description,
- instance=instance)
- if className == "" and resourceId != "" and text != "" and description != "" and instance != -1:
- uiObject = self.u(resourceId=resourceId, text=text, description=description,
- instance=instance)
- # 缺少两个元素的
- if className == "" and resourceId == "" and text != "" and description != "" and instance != -1:
- uiObject = self.u(text=text, description=description,
- instance=instance)
- if className == "" and resourceId != "" and text == "" and description != "" and instance != -1:
- uiObject = self.u(resourceId=resourceId, description=description,
- instance=instance)
- if className == "" and resourceId != "" and text != "" and description == "" and instance != -1:
- uiObject = self.u(resourceId=resourceId, text=text,
- instance=instance)
- if className == "" and resourceId != "" and text != "" and description != "" and instance == -1:
- uiObject = self.u(resourceId=resourceId, text=text, description=description)
- if className != "" and resourceId == "" and text == "" and description != "" and instance != -1:
- uiObject = self.u(className=className, description=description,
- instance=instance)
- if className != "" and resourceId == "" and text != "" and description == "" and instance != -1:
- uiObject = self.u(className=className, text=text,
- instance=instance)
- if className != "" and resourceId != "" and text == "" and description != "" and instance == -1:
- uiObject = self.u(className=className, text=text, description=description)
- if className != "" and resourceId != "" and text == "" and description == "" and instance != -1:
- uiObject = self.u(className=className, resourceId=resourceId,
- instance=instance)
- if className != "" and resourceId != "" and text == "" and description == "" and instance != -1:
- uiObject = self.u(className=className, resourceId=resourceId, description=description)
- if className != "" and resourceId != "" and text != "" and description == "" and instance == -1:
- uiObject = self.u(className=className, resourceId=resourceId, text=text)
- # 缺少3个元素
- if className == "" and resourceId == "" and text == "" and description != "" and instance != -1:
- uiObject = self.u(description=description, instance=instance)
- if className == "" and resourceId == "" and text != "" and description == "" and instance != -1:
- uiObject = self.u(text=text, instance=instance)
- if className == "" and resourceId == "" and text != "" and description != "" and instance == -1:
- uiObject = self.u(text=text, description=description)
- if className == "" and resourceId != "" and text == "" and description == "" and instance != -1:
- uiObject = self.u(resourceId=resourceId, instance=instance)
- if className == "" and resourceId != "" and text == "" and description != "" and instance == -1:
- uiObject = self.u(resourceId=resourceId, description=description)
- if className == "" and resourceId != "" and text != "" and description == "" and instance == -1:
- uiObject = self.u(resourceId=resourceId, text=text)
- if className != "" and resourceId == "" and text == "" and description == "" and instance != -1:
- uiObject = self.u(className=className, instance=instance)
- if className != "" and resourceId == "" and text == "" and description != "" and instance == -1:
- uiObject = self.u(className=className, description=description)
- if className != "" and resourceId == "" and text != "" and description == "" and instance == -1:
- uiObject = self.u(className=className, text=text)
- if className != "" and resourceId != "" and text == "" and description == "" and instance == -1:
- uiObject = self.u(className=className, resourceId=resourceId)
- # 缺少4个元素
- if className == "" and resourceId == "" and text == "" and description == "" and instance != -1:
- uiObject = self.u(instance=instance)
- if className == "" and resourceId == "" and text == "" and description != "" and instance == -1:
- uiObject = self.u(description=description)
- if className == "" and resourceId == "" and text != "" and description == "" and instance == -1:
- uiObject = self.u(text=text)
- if className == "" and resourceId != "" and text == "" and description == "" and instance == -1:
- uiObject = self.u(resourceId=resourceId)
- if className != "" and resourceId == "" and text == "" and description == "" and instance == -1:
- uiObject = self.u(className=className)
- return uiObject
- except Exception, e:
- print e
- return uiObject
- '''
- 作用:判断当前界面中指定控件是否存在
- 参数:
- className:控件类型(例如:android.widget.TextView)
- resourceId:控件的Id(例如:lh.oslauncher:id/tv_title)
- text:控件上的文件(例如:'主页')
- description:控件描述
- instance:实例参数
- 注意:className、resourceId、text 是利用WEditor工具查看控件属性看到的
- 例子:isExists = self.pyUIAutomator.isElementExist("android.widget.TextView",
- resourceId="com.apps.weather:id/today_tv_city",
- text='鞍山')
- '''
- def isElementExist(self, className='', resourceId='', text='', description='', instance=-1):
- self.listenAdbConnected()
- try:
- uiObject = self.getUiObject(className, resourceId, text, description, instance)
- print 'uiObject:', uiObject
- if uiObject:
- isExists = uiObject.exists()
- print 'isExists:', isExists
- else:
- isExists = False
- except Exception, e:
- print e
- isExists = False
- return isExists
- '''
- 作用:获取指定控件的文字属性
- 参数:
- className:控件类型(例如:android.widget.TextView)
- resourceId:控件的Id(例如:lh.oslauncher:id/tv_title)
- 注意:className、resourceId 是利用WEditor工具查看控件属性看到的
- 例子: str_play_time = self.pyUIAutomator.getTextById("android.widget.TextView",
- resourceId="com.apps.usbmediaplayer:id/playingTime")
- '''
- def getTextById(self, className, resourceId):
- self.listenAdbConnected()
- try:
- text = self.u(className=className, resourceId=resourceId).get_text()
- except Exception, e:
- print e
- text = ''
- return text
- '''
- 作用:执行adb命令
- 参数:adbCmd:要被执行的adb命令
- 注意:adbCmd不需要输入adb shell
- 例子:self.pyUIAutomator.adb_shell('am start -n com.apps.factory.ui/.designmenu.DesignMenuActivity')
- '''
- def adb_shell(self, adbCmd):
- self.listenAdbConnected()
- try:
- self.u.adb_shell(adbCmd)
- except Exception, e:
- print e
- '''
- 作用:设置android.widget.EditText 的文字内容
- 参数:text 要输入到EditText的文字内容
- 注意:保证焦点在该EditText,处于可以输入的状态
- 例子:self.pyUIAutomator.send_text(u'鞍山')
- '''
- def send_text(self, text):
- self.listenAdbConnected()
- try:
- self.u.set_fastinput_ime(True) # 切换成FastInputIME输入法
- self.u.clear_text()
- self.u.send_keys(unicode(text)) # adb广播输入
- self.u.set_fastinput_ime(False) # 切换成正常的输入法
- except Exception, e:
- print e
- '''
- 作用:向电视机发送action动作
- 参数:actin 要执行的动作
- 注意:焦点在搜索界面输入框中,在搜索界面输入完搜索内容,执行该搜索动作
- 例子:小米谷歌商店搜索应用 搜索 keep应用
- self.pyUIAutomator.send_text("kee")
- self.pyUIAutomator.send_action("search")
- '''
- def send_action(self, action):
- self.listenAdbConnected()
- try:
- self.u.set_fastinput_ime(True) # 切换成FastInputIME输入法
- self.u.send_action(action)
- self.u.set_fastinput_ime(False) # 切换成正常的输入法
- except Exception, e:
- print e
- '''
- 作用:保存界面截图到指定地址
- 参数:pngPath 要保存图片的全路径名称
- 注意:保证该图片路径所在文件夹存在
- 例子:self.pyUIAutomator.screenshot(
- r'E:\svn\SAT\SAT_Runner\btc_runner_se\runner\smoking\report\imgs\testUSB_Desk_Focused.png')
- '''
- def screenshot(self, pngPath):
- self.listenAdbConnected()
- try:
- self.u.screenshot(pngPath)
- except Exception, e:
- print e
- '''
- 作用:在Android 一个土司提示框 方便在电视机中看到跑到哪里
- 参数:
- toastText:土司的内容
- toastTime:土司存留时间
- 注意:
- 例子:self.pyUIAutomator.makeToast('测试开始', 3)
- '''
- def makeToast(self, toastText, toastTime=1):
- self.listenAdbConnected()
- try:
- self.u.make_toast(toastText, toastTime)
- except Exception, e:
- print e
- '''
- 作用:启动指定包名的应用的指定Activity
- 参数:
- pkg_name:指定的包名
- activity:指定的activity名
- 注意:
- 例子:self.pyUIAutomator.startApp('com.apps.usbmediaplayer')
- self.pyUIAutomator.startApp('com.apps.usbmediaplayer','com.apps.usbmediaplayer.activity.MainActivity')
- '''
- def startApp(self, pkg_name, activity=None):
- self.listenAdbConnected()
- try:
- if activity:
- self.u.app_start(pkg_name, activity=activity)
- else:
- self.u.app_start(pkg_name)
- except Exception, e:
- print e
- '''
- 作用:关闭某一指定包名的APP
- 参数:
- pkg_name:指定的包名
- 注意:
- 例子:self.pyUIAutomator.stopApp('com.apps.usbmediaplayer')
- '''
- def stopApp(self, pkg_name):
- self.listenAdbConnected()
- try:
- self.u.app_stop(pkg_name)
- except Exception, e:
- print e
- '''
- 作用:关闭Android系统中所有的运行程序
- 参数:
- 注意:
- 例子:self.pyUIAutomator.stopAllApps()
- '''
- def stopAllApps(self):
- self.listenAdbConnected()
- try:
- self.u.app_stop_all()
- except Exception, e:
- print e
- '''
- 作用:停止uiautomator守护程序,允许其他测试框架如 appium 运行
- 参数:
- 注意:
- 例子:self.pyUIAutomator.stopUIAutomatorService()
- '''
- def stopUIAutomatorService(self):
- self.listenAdbConnected()
- try:
- self.u.service("uiautomator").stop()
- except Exception, e:
- print e
- '''
- 作用:根据传入的chooseType,获取当前界面聚焦的对象
- 参数:
- 注意:
- 例子:self.pyUIAutomator.getChoosedUIObject("focus")
- '''
- def getChoosedUIObject(self, chooseType, resourceId='', text=''):
- if chooseType.lower() == "focus":
- return self.getFocusedUIObject(resourceId=resourceId, text=text)
- elif chooseType.lower() == "select":
- return self.getSelectedUIObject(resourceId=resourceId, text=text)
- else:
- return None
- '''
- 作用:获取当前界面的focused的UIObject对象
- 参数:
- 注意:
- 例子:self.pyUIAutomator.getFocusedUIObject()
- '''
- def getFocusedUIObject(self, resourceId='', text=''):
- self.listenAdbConnected()
- focusedUIObject = None
- try:
- if resourceId != "" and text != "":
- focusedUIObject = self.u(resourceId=resourceId, text=text, focused=True)
- elif resourceId == "" and text != "":
- focusedUIObject = self.u(text=text, focused=True)
- elif resourceId != "" and text == "":
- focusedUIObject = self.u(resourceId=resourceId, focused=True)
- else:
- focusedUIObject = self.u(focused=True)
- except Exception, e:
- print "getFocusedUIObject Error:", e
- return focusedUIObject
- '''
- 作用:获取当前界面的selected的UIObject对象
- 参数:
- 注意:
- 例子:self.pyUIAutomator.getFocusedUIObject()
- '''
- def getSelectedUIObject(self, resourceId='', text=''):
- self.listenAdbConnected()
- try:
- if resourceId != "" and text != "":
- selectedUIObject = self.u(resourceId=resourceId, text=text, selected=True)
- elif resourceId == "" and text != "":
- selectedUIObject = self.u(text=text, selected=True)
- elif resourceId != "" and text == "":
- selectedUIObject = self.u(resourceId=resourceId, selected=True)
- else:
- selectedUIObject = self.u(selected=True)
- return selectedUIObject
- except Exception, e:
- print "getSelectedUIObject Error:", e
- return None
- '''
- 作用:在脚本运行过程中,监听弹框的出现,如果出现则按按钮使其消失,使得脚本中获取元素控件时不被遮挡报错
- 参数:watcherName 监听器名称
- dialogText 弹框的text
- buttonText 使弹框消失的按钮text
- 注意: 1.这个函数只是创建监听器,这些监听器生效使用u.startWatchers(),监听器失效使用u.stopWatchers();
- 2.一般使用在脚本运行实际执行界面前 声明监听器、调用 u.startWatchers(),在脚本 结束时候调用u.stopWatchers()
- 例子:self.pyUIAutomator.getFocusedUIObject()
- u = PyUIAutomator()
- u.createDilogWatcher("Normal Dialog Watcher", "我是一个普通Dialog", "确定")
- u.startWatchers()
- #这30S延时代表脚本执行
- time.sleep(30)
- u.stopWatchers()
- '''
- def createDilogWatcher(self, watcherName, dialogText, buttonText):
- self.listenAdbConnected()
- self.u.watcher(watcherName).when(text=dialogText).click(text=buttonText)
- '''
- 作用:使得创建的弹框监听器生效
- 参数:
- 注意:
- '''
- def startWatchers(self):
- self.listenAdbConnected()
- self.u.watchers.watched = True
- '''
- 作用:使得创建的弹框监听器失效
- 参数:
- 注意:
- '''
- def stopWatchers(self):
- self.listenAdbConnected()
- self.u.watchers.watched = False
- def dump_hierarchy(self):
- self.listenAdbConnected()
- return self.u.dump_hierarchy()
- class DirectionManageAndroid():
- def __init__(self):
- self.className = self.__class__.__name__
- self.grid = None
- self.remote = TvOperator()
- def goOneStep(self, pyUIAutomator, direction, keyType = UATTree.Key_Event):
- # keyDict = {'U': "up", "D": "down", "L": "left", "R": "right"}
- print "goOneStep,direction:", direction
- directionArr = direction.split("-")
- for direct in directionArr:
- LoggingUtil.getDebugLogger().info(pyFileName, self.className, get_current_function_name(),
- u"script:sendKey 执行按键:%s" % (direct))
- # self.custSendKey(keyDict[direct])
- if keyType == UATTree.Key_Event:
- pyUIAutomator.pressKeyTimes(direct)
- elif keyType == UATTree.Key_IR:
- self.remote.sendKey(direct)
- # def custSendKey(self, keyEvent):
- # if type(keyEvent) == type('') or type(keyEvent) == type(u""):
- # self.operator.sendKey(keyEvent)
- # if type(keyEvent) == type([]):
- # try:
- # self.operator.sendKey(keyEvent[0], keyEvent[1], keyEvent[2])
- # except Exception:
- # LoggingUtil.getDebugLogger().info(pyFileName, self.className, get_current_function_name(),
- # u'script:sendKey ERROR 双击按键数组%s格式出错,请按照格式:[按键字符,按键次数,按键间隔]' % (
- # keyEvent))
- '''
- 计算目标区域在当前焦点区域的方位.
- | |
- 左上角 | 上 | 右上角
- | |
- -----------------------------------
- | |
- | |
- 左 | 焦点区域 | 右
- | |
- -----------------------------------
- | |
- 左下角 | 下 | 右下角
- | |
- 区域的方位,按上图,分成4面位方向和4角位方向。
- 4面位方向:上、下、左、右。只要目标区域,和4面位方向区域有交集,就属于面位方向。
- 4角位方向:左上角、右上角、左下角、右下角。目标区域全部在4角位方向区域,才是角位方向。
- 方位定义:up、down、left、right、left-up、left-down、right-up、right-down
- :param areaL:当前焦点所在区域
- :param areaT:目标区域
- :return direction。字符串类型,方位:up、down、left、right、left-up、left-down、right-up、right-down
- '''
- ImgRectLimit = 10000
- def getTargetDirection(self, focusedBounds, destBounds):
- areaL = (focusedBounds['left'], focusedBounds['top'], focusedBounds['right'], focusedBounds['bottom'])
- areaT = (destBounds['left'], destBounds['top'], destBounds['right'], destBounds['bottom'])
- print "getTargetDirection:", areaL, areaT
- LoggingUtil.getDebugLogger().info(pyFileName, self.className,
- get_current_function_name(),
- u'script:focusMatch 当前聚焦区域坐标:%s 目标聚焦区域坐标:%s' % (str(areaL), str(areaT)))
- # 确定4个面位方位的区域的x,y轴范围
- up = [areaL[0], 0, areaL[2], areaL[1]]
- down = [areaL[0], areaL[3], areaL[2], DirectionManageAndroid.ImgRectLimit]
- left = [0, areaL[1], areaL[0], areaL[3]]
- right = [areaL[2], areaL[1], DirectionManageAndroid.ImgRectLimit, areaL[3]]
- # 检测目标区域是否和4个面位方向区域有重叠部分
- up_direct = self.hasSameArea(up, areaT)
- if up_direct:
- return "up"
- down_direct = self.hasSameArea(down, areaT)
- if down_direct:
- return "down"
- left_direct = self.hasSameArea(left, areaT)
- if left_direct:
- return "left"
- right_direct = self.hasSameArea(right, areaT)
- if right_direct:
- return "right"
- # 计算目标区域坐上角点的方位,x,y差值确定角位方向
- dL_Ux = areaT[0] - areaL[0]
- dL_Uy = areaT[1] - areaL[1]
- if (dL_Ux > 0) and (dL_Uy > 0):
- return "down-right"
- if (dL_Ux < 0) and (dL_Uy > 0):
- return "down-left"
- if (dL_Ux > 0) and (dL_Uy < 0):
- return "up-right"
- if (dL_Ux < 0) and (dL_Uy < 0):
- return "up-left"
- '''
- 检测两个区域是否有重叠部分
- '''
- def hasSameArea(self, area1, area2):
- # 计算各区域宽、高
- area1_W = area1[2] - area1[0]
- area1_H = area1[3] - area1[1]
- area2_W = area2[2] - area2[0]
- area2_H = area2[3] - area2[1]
- # 计算目标区域坐上角点的方位
- dL_Ux = area1[0] - area2[0]
- dL_Uy = area1[1] - area2[1]
- # 计算x坐标,判断是否有重叠可能。
- x_enable = False
- if dL_Ux > 0:
- if (abs(dL_Ux) - area2_W) >= 0:
- x_enable = False
- else:
- x_enable = True
- else:
- if (abs(dL_Ux) - area1_W) >= 0:
- x_enable = False
- else:
- x_enable = True
- # 计算y坐标,判断是否有重叠可能。
- y_enable = False
- if dL_Uy > 0:
- if (abs(dL_Uy) - area2_H) > 0:
- y_enable = False
- else:
- y_enable = True
- else:
- if (abs(dL_Uy) - area1_H) > 0:
- y_enable = False
- else:
- y_enable = True
- # 如果x坐标、y坐标都有可能重叠,则一定重叠。反之,没有重叠。
- return x_enable and y_enable
- def isSameBounds(self, BoundA, BoundB):
- areaA = (BoundA['left'], BoundA['top'], BoundA['right'], BoundA['bottom'])
- areaB = (BoundB['left'], BoundB['top'], BoundB['right'], BoundB['bottom'])
- if areaA[0] == areaB[0] \
- and areaA[1] == areaB[1] \
- and areaA[2] == areaB[2] \
- and areaA[3] == areaB[3]:
- return True
- else:
- return False
- def isHasAnotherBounds(self, BoundA, BoundB):
- areaA = (BoundA['left'], BoundA['top'], BoundA['right'], BoundA['bottom'])
- areaB = (BoundB['left'], BoundB['top'], BoundB['right'], BoundB['bottom'])
- if areaA[0] <= areaB[0] and areaA[1] <= areaB[1] and areaA[2] >= areaB[2] and areaA[3] >= areaB[3]:
- return True
- else:
- return False
- def isRelativePositionBounds(self, initFocusedArea, initDestTextArea, BoundA, BoundB):
- # initFocusedArea = (
- # initFocusedBound['left'], initFocusedBound['top'], initFocusedBound['right'], initFocusedBound['bottom'])
- # initDestTextArea = (
- # initFocusedBound['left'], initDestTextBound['top'], initDestTextBound['right'], initDestTextBound['bottom'])
- areaA = (BoundA['left'], BoundA['top'], BoundA['right'], BoundA['bottom'])
- areaB = (BoundB['left'], BoundB['top'], BoundB['right'], BoundB['bottom'])
- # if areaA[0] < areaB[0] and areaA[1] < areaB[1] and areaA[2] > areaB[2] and areaA[3] >areaB[3]:
- # return True
- # else:
- # return False
- if initFocusedArea[0] - initDestTextArea[0] == areaA[0] - areaB[0] and initFocusedArea[1] - initDestTextArea[
- 1] == areaA[1] - areaB[1] and initFocusedArea[2] - initDestTextArea[2] == areaA[2] - areaB[2] and \
- initFocusedArea[3] - initDestTextArea[3] == areaA[3] - areaB[3]:
- return True
- else:
- return False
- # 比较两个Bound面积大小
- def isBiggerBound(self, boundA, boundB):
- # print 'boundA:',boundA
- # print 'boundB:',boundB
- if ((boundA["bottom"] - boundA["top"]) * (boundA["right"] - boundA["left"])) >= ((
- boundB["bottom"] -
- boundB["top"]) * (
- boundB["right"] -
- boundB["left"])):
- return True
- else:
- return False
- def getRelativeBounds(self, standBounds_view1, standBounds_view2, currentBound_view1):
- currentBound_view2 = {}
- currentBound_view2["top"] = standBounds_view2["top"] - standBounds_view1["top"] + currentBound_view1["top"]
- currentBound_view2["left"] = standBounds_view2["left"] - standBounds_view1["left"] + currentBound_view1["left"]
- currentBound_view2["right"] = standBounds_view2["right"] - standBounds_view1["right"] + currentBound_view1[
- "right"]
- currentBound_view2["bottom"] = standBounds_view2["bottom"] - standBounds_view1["bottom"] + currentBound_view1[
- "bottom"]
- return currentBound_view2
- class FocusManageAndroid():
- # u是PyUIAutomator对象
- # focusManage 是DirectionManageAndroid对象
- def __init__(self, u, directionManageAndroid):
- self.className = self.__class__.__name__
- self.u = u
- self.directionManageAndroid = directionManageAndroid
- self.ReverseDirctionDict = {"up": "down", "down": "up", "left": "right", "right": "left"}
- self.featureDetect = FeatureDetect()
- self.ccard = CCardManager()
- self.imgCMP = ImageCMP()
- self.ocr = OCRConvert()
- self.remote = TvOperator()
- '''
- 作用:在RecyclerView 中 focused控件包含文字控件 用于聚焦目标焦点
- 参数:
- text:目标文字的文字内容
- className:目标文字的className
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 小米信源设置界面 聚焦到Device Settings/Sound mode
- className = "android.widget.TextView"
- focusManageAndroid.toDestFocusByText_className_for_RecyclerView("News", className)
- '''
- # 在RecyclerView 中 focused控件包含文字控件
- def toDestFocusByText_className_for_RecyclerView(self, text, className, findDirection="down", Max_Try=10, keyType = UATTree.Key_Event):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- focusedUIObject = self.u.getFocusedUIObject()
- focusedBounds = focusedUIObject.info['bounds']
- # print "focusedBounds:",focusedBounds
- destUIObject = self.u.getUiObject(text=text, className=className)
- if destUIObject:
- try:
- destBounds = destUIObject.info['bounds']
- # print "destBounds:", destBounds
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print '成功聚焦到目标焦点:', text
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:在RecyclerView 中 focused控件包含文字控件 用于聚焦目标焦点
- 参数:
- text:目标文字的文字内容
- textResourceId:目标文字的resourceId
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 小米信源设置界面 聚焦到Device Settings
- focusManageAndroid.toDestFocusByText_for_RecyclerView("Device Settings","com.android.tv:id/title")
- '''
- # 在RecyclerView 中 focused控件包含文字控件
- def toDestFocusByText_for_RecyclerView(self, text, textResourceId="", findDirection="down", Max_Try=10, keyType = UATTree.Key_Event, hb_keyDict={}):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- focusedUIObject = self.u.getFocusedUIObject()
- try:
- focusedBounds = focusedUIObject.info['bounds']
- except Exception, e:
- print "未能获取到当前聚焦焦点,聚焦框丢失,判断聚焦失败!!"
- return False
- print "focusedBounds:",focusedBounds
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- destUIObject = self.u.getUiObject(text=text, resourceId=textResourceId)
- if destUIObject:
- try:
- destBounds = destUIObject.info['bounds']
- print "destBounds:", destBounds
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print '成功聚焦到目标焦点:', text
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:在RecyclerView 中 focused控件包含文字控件 用于聚焦目标焦点,传入的resourceId为聚焦焦点的resId时的处理函数
- 参数:
- text:目标文字的文字内容
- focuseResId:整个聚焦焦点的resourceId
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 小米俄罗斯设置界面 存在复数个聚焦焦点时,使用此函数,可以规避复数焦点的问题
- '''
- def toDestFocusByText_with_FocuseResourceId(self, text, focuseResId, findDirection="down", Max_Try=10, keyType = UATTree.Key_Event, hb_keyDict = {}):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- focusedUIObject = self.u.getFocusedUIObject(resourceId=focuseResId)
- try:
- focusedBounds = focusedUIObject.info['bounds']
- except Exception, e:
- print "未能获取到当前聚焦焦点,聚焦框丢失,判断聚焦失败!!"
- return False
- print "focusedBounds:",focusedBounds
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- destUIObject = self.u.getUiObject(text=text)
- if destUIObject:
- try:
- destBounds = destUIObject.info['bounds']
- print "destBounds:", destBounds
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print '成功聚焦到目标焦点:', text
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:在RecyclerVi或listView 中 selected控件包含文字控件 用于聚焦目标焦点
- 参数:
- text:目标文字的文字内容
- textResourceId:目标文字的resourceId
- listViewResourceId:RecyclerVi或listView的resourceId
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 2841项目信源列表聚焦 聚焦到HDMI1
- focusManageAndroid.toDestSelectByText_for_RecyclerView("HDMI1","com.android.tv:id/title","com.android.tv:id/scene_transition_common")
- '''
- def toDestSelectByText_for_RecyclerView(self, text, textResourceId='', optionViewResoucreId='', listViewResourceId='', findDirection="down",
- Max_Try=10, keyType = UATTree.Key_Event, hb_keyDict={}):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- listViewUIObject = self.u.getUiObject(resourceId=listViewResourceId)
- print "listViewUIObject.info:", listViewUIObject.info
- if optionViewResoucreId != '':
- selectedUIObject = listViewUIObject.child(selected=True, resourceId=optionViewResoucreId)
- else:
- selectedUIObject = listViewUIObject.child(selected=True)
- print "selectedUIObject.info:", selectedUIObject.info
- selectedBounds = selectedUIObject.info['bounds']
- # print "focusedBounds:",focusedBounds
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- destUIObject = self.u.getUiObject(text=text, resourceId=textResourceId)
- if destUIObject:
- destBounds = destUIObject.info['bounds']
- # print "destBounds:", destBounds
- if self.directionManageAndroid.isHasAnotherBounds(selectedBounds, destBounds):
- print '成功聚焦到目标焦点:', text
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(selectedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:在界面中 中 focused控件包含content-des控件 用于聚焦目标焦点
- 参数:
- description:目标描述的文字内容
- descriptionResourceId:目标描述的resourceId
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 小米APP 聚焦到YouTube
- descriptionResourceId = "com.google.android.tvlauncher:id/banner_image"
- focusManageAndroid.toDestFocusByDescription_for_RecyclerView("YouTube",descriptionResourceId=descriptionResourceId)
- '''
- # 在RecyclerView 中 focused控件包含文字控件
- def toDestFocusByDescription_for_RecyclerView(self, description, descriptionResourceId="", findDirection="down",
- Max_Try=10 ,keyType = UATTree.Key_Event, hb_keyDict = {}):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- print "count:", count
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- focusedUIObject = self.u.getFocusedUIObject()
- focusedBounds = focusedUIObject.info['bounds']
- # print "focusedBounds:",focusedBounds
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- destUIObject = self.u.getUiObject(description=description, resourceId=descriptionResourceId)
- if destUIObject:
- try:
- destBounds = destUIObject.info['bounds']
- # print "destBounds:", destBounds
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print '成功聚焦到目标焦点:', description
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception, e:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:在界面中 中 focused控件中既没有包含content-des控件属性,也没有text控件属性,
- 采用单张图片模板匹配 用于聚焦目标焦点
- 参数:
- singleImagePath:目标聚焦的单张小图片的地址
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 小米内销APP(既没有文字text属性也没有描述属性content-des) 聚焦到ATX APP
- singleImagePath = "D:\\ATX_APP.jpg"
- focusManageAndroid.toDestFocusBySingleImage_for_RecyclerView(singleImagePath)
- '''
- # 在RecyclerView 中 focused控件包含文字控件
- def toDestFocusBySingleImage_for_RecyclerView(self, singleImagePath, findDirection="down",
- Max_Try=10 ,keyType = UATTree.Key_Event):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- print "count:", count
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- focusedUIObject = self.u.getFocusedUIObject()
- focusedBounds = focusedUIObject.info['bounds']
- srceenImgPath = os.path.join(sat_environment.getSATTmpDIR(), "SingleImage_runpath.png")
- self.ccard.takePicture(srceenImgPath)
- resultDict = self.featureDetect.matchSingleImage(srceenImgPath, [0, 0, 1920, 1080], singleImagePath)
- # destUIObject = self.u.getUiObject(description=description, resourceId=descriptionResourceId)
- if resultDict:
- try:
- destBounds_coordinate = resultDict['coordinate']
- # areaA = (BoundA['left'], BoundA['top'], BoundA['right'], BoundA['bottom'])
- destBounds = {"left": destBounds_coordinate[0], "top": destBounds_coordinate[1],
- "right": destBounds_coordinate[2], "bottom": destBounds_coordinate[3]}
- # print "destBounds:", destBounds
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print '成功聚焦到目标焦点:', singleImagePath
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception, e:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:在界面中 中 focused控件中既没有包含content-des控件属性,也没有text控件属性,
- 采用OCR识别文字 用于聚焦目标焦点
- 参数:
- text:需要OCR识别的文字
- textResourceId:文字区域的resourceId
- recyclerViewResourceId:列表recyclerView的resourceId
- ocrTextBorder:为OCR识别更准确,文字识别坐标需要扩充的边界的值(默认为10)
- OCRDict:OCR识别文字的属性 默认为百度中英文识别
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- '''
- # 在RecyclerView 中 focused控件包含文字控件
- def toDestFocusByOCRText_for_RecyclerView(self, text, textResourceId, recyclerViewResourceId, ocrTextBorder=10,
- OCRDict={"OCR_lan": "CHN_ENG", "OCR_type": 10000},
- findDirection="down",
- Max_Try=10,
- keyType = UATTree.Key_Event):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- print "count:", count
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- focusedUIObject = self.u.getFocusedUIObject()
- focusedBounds = focusedUIObject.info['bounds']
- # 寻找目标焦点坐标
- childbound = None
- recyclerViewUIObject = self.u.getUiObject(resourceId=recyclerViewResourceId)
- for i in range(recyclerViewUIObject.info["childCount"]):
- childUIObject = recyclerViewUIObject.child_by_instance(i, resourceId=textResourceId)
- try:
- childbound = childUIObject.info["bounds"]
- # 对扩大后的图片坐标进行边界判断
- childbound_Area_left = childbound["left"] - 10
- if childbound_Area_left < 0: childbound_Area_left = 0
- childbound_Area_top = childbound["top"] - 10
- if childbound_Area_top < 0: childbound_Area_top = 0
- childbound_Area_right = childbound["right"] + 10
- if childbound_Area_right > 1920: childbound_Area_right = 1920
- childbound_Area_bottom = childbound["bottom"] - 10
- if childbound_Area_bottom > 1080: childbound_Area_bottom = 1080
- childbound_Area = (childbound_Area_left, childbound_Area_top,
- childbound_Area_right, childbound_Area_bottom)
- # 小图保存地址
- tmpPic = os.path.join(getSATTmpDIR(), "uiautomator_text_ocr.png")
- # 整个界面图片保存地址
- srceenImgPath = os.path.join(sat_environment.getSATTmpDIR(), "uiautomator_OCR_runpath.png")
- self.u.screenshot(srceenImgPath)
- # self.ccard.takePicture(srceenImgPath)
- # 切割小图片
- self.imgCMP.saveCropPic(srceenImgPath, tmpPic, (
- childbound_Area[0], childbound_Area[1], childbound_Area[2], childbound_Area[3]))
- # ocr 识别
- textValueCUR = self.ocr.getStr(tmpPic, OCRDict["OCR_lan"], OCRDict["OCR_type"])
- print "textValueCUR:", textValueCUR
- print "destText:", text
- if self.ocr.cmpOcrStr(textValueCUR, text):
- break
- else:
- childbound = None
- except Exception:
- childbound = None
- pass
- if childbound:
- try:
- destBounds = childbound
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print '成功聚焦到目标焦点:', text
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception, e:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:在界面中 中 focused控件中既没有包含content-des控件属性,也没有text控件属性,
- 一般这种控件是自定义控件 class类型是android.view.View
- 采用OCR识别文字 用于聚焦目标焦点
- 参数:
- text:需要OCR识别的文字
- visableViewResourceId:可以通过UIAutomator框架获取到的控件的id
- initTextArea: 确定的一个区域下的文字坐标
- initVisableViewArea:确定的一个区域下的可获取控件的坐标
- ocrTextBorder:为OCR识别更准确,文字识别坐标需要扩充的边界的值(默认为10)
- OCRDict:OCR识别文字的属性 默认为百度中英文识别
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:小米内销APP测试
- #文字内容
- text = "应用商店"
- #图标的resourceId
- visableViewResourceId = "com.mitv.tvhome:id/di_img"
- #非聚焦的app文字坐标
- initTextArea = [90, 392, 229, 424]
- #非聚焦的app图片坐标
- initVisableViewArea = [90, 257, 227, 382]
- focusManageAndroid.toDestFocusRelativeOCRText__for_RecyclerView(text=text,
- visableViewResourceId=visableViewResourceId,
- initTextArea=initTextArea,
- initVisableViewArea=initVisableViewArea)
- '''
- # 在RecyclerView 中 focused控件包含文字控件
- def toDestFocusRelativeOCRText__for_RecyclerView(self, text, visableViewResourceId, initTextArea,
- initVisableViewArea, ocrTextBorder=5,
- OCRDict={"OCR_lan": "CHN_ENG", "OCR_type": 10000},
- findDirection="down",
- Max_Try=10,
- keyType = UATTree.Key_Event):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- initTextBounds = {"left": initTextArea[0], "top": initTextArea[1], "right": initTextArea[2],
- "bottom": initTextArea[3]}
- initvisableViewBounds = {"left": initVisableViewArea[0], "top": initVisableViewArea[1],
- "right": initVisableViewArea[2], "bottom": initVisableViewArea[3]}
- while (True):
- print "count:", count
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- focusedUIObject = self.u.getFocusedUIObject()
- focusedBounds = focusedUIObject.info['bounds']
- # 寻找目标焦点坐标
- childbound = None
- childCountUIObject = self.u.getUiObject(resourceId=visableViewResourceId)
- print "childCountUIObject.info", childCountUIObject.info
- childCount = childCountUIObject.count
- print "列表包含的子控件数量:", childCount
- for i in range(childCount):
- print "第%s次查找目标bounds" % (str(i))
- visableViewObject = self.u.getUiObject(instance=i, resourceId=visableViewResourceId)
- try:
- visableViewBound = visableViewObject.info["bounds"]
- print "initvisableViewBounds:", initvisableViewBounds
- print "initTextBounds:", initTextBounds
- print "visableViewBound:", visableViewBound
- childbound = self.directionManageAndroid.getRelativeBounds(initvisableViewBounds, initTextBounds,
- visableViewBound)
- print "childbound:", childbound
- # return False
- # childbound = childUIObject.info["bounds"]
- # 对扩大后的图片坐标进行边界判断
- childbound_Area_left = childbound["left"] - 10
- if childbound_Area_left < 0: childbound_Area_left = 0
- childbound_Area_top = childbound["top"] - 10
- if childbound_Area_top < 0: childbound_Area_top = 0
- childbound_Area_right = childbound["right"] + 10
- if childbound_Area_right > 1920: childbound_Area_right = 1920
- childbound_Area_bottom = childbound["bottom"] + 10
- if childbound_Area_bottom > 1080: childbound_Area_bottom = 1080
- childbound_Area = [childbound_Area_left, childbound_Area_top,
- childbound_Area_right, childbound_Area_bottom]
- print "childbound_Area:", childbound_Area
- # 小图保存地址
- tmpPic = os.path.join(getSATTmpDIR(), "uiautomator_text_ocr.png")
- # 整个界面图片保存地址
- srceenImgPath = os.path.join(sat_environment.getSATTmpDIR(), "uiautomator_OCR_runpath.png")
- self.u.screenshot(srceenImgPath)
- # self.ccard.takePicture(srceenImgPath)
- # 切割小图片
- self.imgCMP.saveCropPic(srceenImgPath, tmpPic, (
- childbound_Area[0], childbound_Area[1], childbound_Area[2], childbound_Area[3]))
- # ocr 识别
- textValueCUR = self.ocr.getStr(tmpPic, OCRDict["OCR_lan"], OCRDict["OCR_type"])
- print "textValueCUR:", textValueCUR
- print "destText:", text
- if self.ocr.cmpOcrStr(textValueCUR, text):
- break
- else:
- childbound = None
- except Exception, e:
- print e
- childbound = None
- pass
- print "childbound:", childbound
- # return False
- if childbound:
- try:
- destBounds = childbound
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print '成功聚焦到目标焦点:', text
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception, e:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:在RecyclerView 中 focused控件和文字控件同级 相对位置固定 用于聚焦目标焦点
- 参数:
- text:目标文字的文字内容
- textResourceId:目标文字的resourceId
- initFocusedArea:聚焦情况下的focused控件的坐标区域(x1,y1,x2,y2)
- initDestTextArea:聚焦情况下的text控件的坐标区域(x1,y1,x2,y2)
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 小米信源设置 的声音自定义界面 Device /Settings Sound mode /Custom/
- initFocusedArea = (822, 180, 1259, 221)
- initDestTextArea = (822, 116, 1259, 180)
- focusManageAndroid.toDestFocusRelativeText_for_RecyclerView("3500Hz: 0dB", "com.android.tv:id/title",
- initFocusedArea, initDestTextArea)
- '''
- # 在RecyclerView 中 focused控件和文字控件同级
- def toDestFocusRelativeText_for_RecyclerView(self, text, textResourceId, initFocusedArea, initDestTextArea,
- findDirection="down", Max_Try=10, keyType = UATTree.Key_Event):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- focusedUIObject = self.u.getFocusedUIObject()
- focusedBounds = focusedUIObject.info['bounds']
- # print "focusedBounds:",focusedBounds
- destUIObject = self.u.getUiObject(text=text, resourceId=textResourceId)
- if destUIObject:
- try:
- destBounds = destUIObject.info['bounds']
- # print "destBounds:", destBounds
- if self.directionManageAndroid.isRelativePositionBounds(initFocusedArea, initDestTextArea,
- focusedBounds,
- destBounds):
- print '成功聚焦到目标焦点:', text
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:聚焦效果View控件 包含 目标文本控件 用于聚焦目标焦点
- 参数:
- text:目标文字的文字内容
- textResourceId:目标文字的resourceId
- FocusViewResourceId:聚焦效果View的resourceId
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 小米USB界面上方Tab聚焦方法
- focusManageAndroid.toDestFocusByText_for_FocusView("Devices", "com.xiaomi.mitv.mediaexplorer:id/dev",
- "com.xiaomi.mitv.mediaexplorer:id/tab_cursor",
- findDirection="right",
- Max_Try=5)
- '''
- # 聚焦效果View控件 包含 目标文本控件
- def toDestFocusByText_for_FocusView(self, text, FocusViewResourceId, findDirection="down",
- Max_Try=10, keyType = UATTree.Key_Event, hb_keyDict={}):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- focusedUIObject = self.u.getUiObject(resourceId=FocusViewResourceId)
- focusedBounds = focusedUIObject.info['bounds']
- print "focusedBounds:", focusedBounds
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- destUIObject = self.u.getUiObject(text=text)
- if destUIObject:
- try:
- destBounds = destUIObject.info['bounds']
- print "destBounds:", destBounds
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print '成功聚焦到目标焦点:', text
- return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection] ,keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection] ,keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:RecyclerView 中焦点没有focused属性 只是子项中的View有放大效果
- 参数:
- text:目标文字的文字内容
- textResourceId:目标文字的resourceId
- zoomViewResourceId:f放大效果View的resourceId
- recyclerViewResourceId:列表recyclerView 的resourceId
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查找次数
- 注意:
- 例子:
- 小米USB Images 浏览界面
- focusManageAndroid.toDestZoomByText_for_RecyclerView("Pattern", "com.xiaomi.mitv.mediaexplorer:id/album_item_name",
- "com.xiaomi.mitv.mediaexplorer:id/album_item_bg",
- "com.xiaomi.mitv.mediaexplorer:id/all_albums_view")
- '''
- # RecyclerView 中焦点没有focused属性 只是子项中的View有放大效果
- def toDestZoomByText_for_RecyclerView(self, text, textResourceId, zoomViewResourceId, recyclerViewResourceId,
- findDirection="down",
- Max_Try=20,
- keyType=UATTree.Key_Event):
- # 按照传入的方向寻找Max_Try次,如果仍未聚焦到选中area,则按照传入方向的反方向 反向寻找 2*Max_Try 次
- count = 0
- Max_Try = Max_Try
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- # focusedUIObject = self.u.getUiObject(resourceId=FocusViewResourceId)
- # focusedBounds = focusedUIObject.info['bounds']
- # print "focusedBounds:", focusedBounds
- destUIObject = self.u.getUiObject(text=text, resourceId=textResourceId)
- if destUIObject:
- try:
- # 获取目标文本的bounds
- destBounds = destUIObject.info['bounds']
- # print "destBounds:", destBounds
- zoomUiObject = self.u.getUiObject(resourceId=recyclerViewResourceId)
- # print "uiObject.info: ", uiObject.info
- childCount = zoomUiObject.info['childCount']
- zoomBound = {u'top': 0, u'left': 0, u'right': 0, u'bottom': 0}
- zoomIndex = -1
- for i in range(childCount):
- childObject = zoomUiObject.child_by_instance(i, resourceId=zoomViewResourceId)
- # print "childObject.info:", childObject.info
- childounds = childObject.info['bounds']
- # print "child:", str(i), "bounds:", childounds
- if self.directionManageAndroid.isBiggerBound(childounds, zoomBound):
- zoomBound = childounds
- zoomIndex = i
- zoomTextBound = zoomUiObject.child_by_instance(i, resourceId=textResourceId).info[
- "bounds"]
- zoomText = zoomUiObject.child_by_instance(i, resourceId=textResourceId).info["text"]
- # print zoomBound, zoomIndex, zoomTextBound, zoomText
- print "toDestZoomByText_for_RecyclerView 当前聚焦文字:", zoomText
- if str(zoomText) == str(text):
- print '成功聚焦到目标焦点:', text
- return True
- # if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- # print '成功聚焦到目标焦点:', text
- # return True
- else:
- count = count + 1
- direction = self.directionManageAndroid.getTargetDirection(zoomTextBound, destBounds)
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- except Exception:
- # 出现控件出现一半的时候,获取控件信息会报错
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- # 如果界面中没有目标文字的控件出现,则按照传入的方向寻找Max_Try次;仍然未找到 则反方向寻找2*Max_Try次
- else:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到目标焦点!!" % (str(Max_Try))
- return False
- '''
- 作用:获取RecyclerView 中所有文字名称的列表
- 参数:
- recyclerViewResourceId:列表recyclerView 的resourceId
- textResourceId:item中文本区域的的resourceId
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查看次数,执行Max_Try 次findDirection 后 仍无新控件被刷出 则返回所有文件的列表
- name_list:最终返回的列表
- 注意:
- 例子:
- 小米USB Music 浏览界面 获取所有的音乐文件
- recyclerViewResourceId = "com.xiaomi.mitv.mediaexplorer:id/all_music_view"
- textResourceId = "com.xiaomi.mitv.mediaexplorer:id/item_title"
- recyclerViewItemNameList = focusManageAndroid.getRecyclerViewItemNameList(recyclerViewResourceId,textResourceId)
- print "recyclerViewItemNameList:", recyclerViewItemNameList
- '''
- def getRecyclerViewItemNameList(self, recyclerViewResourceId, textResourceId, findDirection="down",
- Max_Try=10, name_list=[], keyType = UATTree.Key_Event):
- count = 0
- isNOTChange = False
- old_name_list = name_list
- while (True):
- if count > Max_Try and isNOTChange:
- return name_list
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- recyclerViewUIObject = self.u.getUiObject(resourceId=recyclerViewResourceId)
- for i in range(recyclerViewUIObject.info["childCount"]):
- childUIObject = recyclerViewUIObject.child_by_instance(i, resourceId=textResourceId)
- try:
- childText = childUIObject.info["text"]
- if childText not in name_list:
- name_list.append(childUIObject.info["text"])
- except Exception:
- pass
- if old_name_list == name_list:
- isNOTChange = True
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- isNOTChange = False
- self.pressKeyByType(findDirection, keyType)
- self.getRecyclerViewItemNameList(recyclerViewResourceId, textResourceId, findDirection,
- Max_Try, name_list)
- '''
- 作用:获取RecyclerView 中所有文字名称的列表
- 参数:
- keyText:寻找目标Text的key的Text
- keyResourceId:寻找目标Text的key的resourceId
- recyclerViewResourceId:列表recyclerView 的resourceId
- textResourceId:目标text的中文本区域的的resourceId
- findDirection: 目标文字控件被隐藏时寻找的方向
- Max_Try:最多查看次数,执行Max_Try 次findDirection 后 仍无新控件被刷出 则返回""
- 注意:
- 例子:
- 小米USB Music 音乐播放界面 通过音乐名称获取音乐时长
- keyResourceId = "com.xiaomi.mimusic2:id/item_textview"
- recyclerViewResourceId = "com.xiaomi.mimusic2:id/music_list_view"
- textResourceId = "com.xiaomi.mimusic2:id/music_list_item_duration"
- findText = focusManageAndroid.getRecyclerViewItemTextByKeyText("鸭子", keyResourceId,
- recyclerViewResourceId,
- textResourceId)
- print "findText:", findText
- '''
- def getRecyclerViewItemTextByKeyText(self, keyText, keyResourceId, recyclerViewResourceId, textResourceId,
- findDirection="down",
- Max_Try=20,
- keyType = UATTree.Key_Event):
- count = 0
- Reversecount = 0
- Reverse_Max_Try = Max_Try * 2
- while (True):
- if count >= Max_Try and Reversecount >= Reverse_Max_Try:
- break
- # 等待聚焦效果刷新完成,稳定之后再获取相关的属性
- time.sleep(0.5)
- recyclerViewUIObject = self.u.getUiObject(resourceId=recyclerViewResourceId)
- iCounnt = -1
- findText = ""
- print "recyclerViewUIObject.info:", recyclerViewUIObject.info
- for i in range(recyclerViewUIObject.info["childCount"]):
- print "i:", i
- try:
- childUIObject = recyclerViewUIObject.child_by_instance(i, resourceId=keyResourceId)
- if str(childUIObject.info["text"]) == str(keyText):
- iCounnt = i
- findUIObject = recyclerViewUIObject.child_by_instance(i, resourceId=textResourceId)
- findText = findUIObject.info["text"]
- return str(findText)
- except Exception:
- iCounnt = -1
- pass
- if iCounnt == -1:
- if count < Max_Try:
- count = count + 1
- self.pressKeyByType(findDirection, keyType)
- else:
- Reversecount = Reversecount + 1
- self.pressKeyByType(self.ReverseDirctionDict[findDirection], keyType)
- print "执行%s 次查找,仍未找到keyText:%s!!" % (str(Max_Try), str(keyText))
- return ""
- def focusFirstItemFromRecyclerView(self, recyclerView_resId, child_class, Max_Try=20, keyType = UATTree.Key_Event):
- return self.focusItemByIndexFromRecyclerView(recyclerView_resId, child_class, 0, Max_Try, keyType)
- def focusItemByIndexFromRecyclerView(self, recyclerView_resId, child_class, target_index, Max_Try=20,
- keyType = UATTree.Key_Event, hb_keyDict={}):
- count = 0
- recyclerView = self.u.getUiObject(resourceId=recyclerView_resId)
- while(True):
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- firstItemUIObject = recyclerView.child_by_instance(target_index, className = child_class)
- print "firstItemUIObject.info:", firstItemUIObject.info
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- destBounds = firstItemUIObject.info['bounds']
- print "目标坐标:", destBounds
- focusedUIObject = self.u.getFocusedUIObject()
- focusedBounds = focusedUIObject.info['bounds']
- print "当前坐标:",focusedBounds
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
- print "已将焦点归位至第一位!!!"
- return True
- else:
- if count >= Max_Try:
- print "已尝试至最大次数%s次,仍未能使焦点归位至第一位!!!"%Max_Try
- return False
- direction = self.directionManageAndroid.getTargetDirection(focusedBounds, destBounds)
- print "目标方位:",direction
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- count += 1
- def focusTargetSeekBar(self, target_resId, chooseType, Max_Try=20, keyType = UATTree.Key_Event, findFocusCount = 0):
- count = 0
- while(True):
- targetUIObject = self.u.getUiObject(resourceId=target_resId)
- print "targetUIObject.info:", targetUIObject.info
- destBounds = targetUIObject.info['bounds']
- print "目标坐标:", destBounds
- try:
- if chooseType.lower() == "focus":
- choosingUIObject = self.u.getFocusedUIObject()
- objBounds = choosingUIObject.info['bounds']
- elif chooseType.lower() == "select":
- choosingUIObject = self.u.getSelectedUIObject()
- objBounds = choosingUIObject.info['bounds']
- print "当前坐标:",objBounds
- except Exception,e:
- print "获取焦点失败!Error:",e
- if findFocusCount < 3:
- self.u.pressKeyTimes("down")
- return self.focusTargetSeekBar(target_resId, chooseType, findFocusCount = findFocusCount + 1)
- else:
- print "尝试%s次操作!!!仍未能找到聚焦点!!!无法聚焦到目标"%findFocusCount
- return False
- if self.directionManageAndroid.isHasAnotherBounds(objBounds, destBounds):
- print "已聚焦至目标seekbar!!!"
- return True
- else:
- if count >= Max_Try:
- print "已尝试至最大次数%s次,仍未能聚焦至目标seekbar!!!"%Max_Try
- return False
- direction = self.directionManageAndroid.getTargetDirection(objBounds, destBounds)
- print "目标方位:",direction
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- count += 1
- def toDestTargetByResourceId_for_RecyclerView(self, resourceId, chooseType, Max_Try=20,
- keyType = UATTree.Key_Event, findFocusCount = 0, hb_keyDict={}):
- count = 0
- while(True):
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- targetUIObject = self.u.getUiObject(resourceId=resourceId)
- print "targetUIObject.info:", targetUIObject.info
- destBounds = targetUIObject.info['bounds']
- print "目标坐标:", destBounds
- if hb_keyDict != {}:
- # 执行心跳按键
- self.executeHeartBeatKey(hb_keyDict)
- try:
- if chooseType.lower() == "focus":
- choosingUIObject = self.u.getFocusedUIObject()
- objBounds = choosingUIObject.info['bounds']
- elif chooseType.lower() == "select":
- choosingUIObject = self.u.getSelectedUIObject()
- objBounds = choosingUIObject.info['bounds']
- print "当前坐标:",objBounds
- except Exception,e:
- print "获取焦点失败!Error:",e
- if findFocusCount < 3:
- self.u.pressKeyTimes("down")
- return self.toDestTargetByResourceId_for_RecyclerView(resourceId, chooseType, findFocusCount = findFocusCount + 1)
- else:
- print "尝试%s次操作!!!仍未能找到聚焦点!!!无法聚焦到目标"%findFocusCount
- return False
- if self.directionManageAndroid.isHasAnotherBounds(objBounds, destBounds):
- print "已聚焦至目标组件!!!"
- return True
- else:
- if count >= Max_Try:
- print "已尝试至最大次数%s次,仍未能聚焦至目标组件!!!"%Max_Try
- return False
- direction = self.directionManageAndroid.getTargetDirection(objBounds, destBounds)
- print "目标方位:",direction
- self.directionManageAndroid.goOneStep(self.u, direction, keyType)
- count += 1
- def pressKeyByType(self, keyName, keyType = UATTree.Key_Event, times = 1, duration = 1.0):
- if keyType == UATTree.Key_Event:
- return self.u.pressKeyTimes(keyName, times, duration)
- elif keyType == UATTree.Key_IR:
- return self.remote.sendKey(keyName, times, duration)
- else:
- return False
- '''
- 执行心跳按键的函数。传入UATree里parent['others']['heartbeat_key']中的参数,会根据参数的配置执行心跳按键
- '''
- def executeHeartBeatKey(self, hb_keyDict):
- try:
- eventList = hb_keyDict["event"]
- irList = hb_keyDict["ir"]
- if eventList != "":
- LoggingUtil.printLog("Executing heartbeat_key by EventKey!!!KeyList:%s" % eventList)
- for key in eventList:
- self.u.pressKeyTimes(key)
- elif irList != "":
- LoggingUtil.printLog("Executing heartbeat_key by irKey!!!KeyList:%s" % irList)
- for key in irList:
- self.remote.sendKey(key)
- except Exception,e:
- LoggingUtil.printLog(u"[executeHeartBeatKey]: 心跳按键配置异常,无法正常执行心跳按键。\n %s"%e)
- if __name__ == "__main__":
- u = PyUIAutomator()
- dm = DirectionManageAndroid()
- fm = FocusManageAndroid(u, dm)
- fm.toDestFocusByText_with_FocuseResourceId(text="Picture", focuseResId="com.mediatek.wwtv.tvcenter:id/menu_item_frame")
- # directionMange = DirectionManageAndroid()
- # focusManage = FocusManageAndroid(u, directionMange)
- # focusObj = focusManage.u.getFocusedUIObject()
- # print "focusObj.info:",focusObj.info
- # childCount = focusObj.info["childCount"]
- # for i in range(childCount):
- # childUI = focusObj.child_by_instance(i, className = "android.widget.TextView")
- # print childUI.info["text"]
- # focusManage.toDestFocusByText_for_RecyclerView(text="Picture mode",textResourceId="",
- # findDirection="down")
- # focusManage.focusTargetSeekBar("com.android.tv.settings:id/seekbar_freq_300")
- # recyclerViewUIObject = u.getUiObject(resourceId="com.xiaomi.mitv.mediaexplorer:id/photo_list")
- # print "recyclerViewUIObject.info", recyclerViewUIObject.info
- # for i in range(recyclerViewUIObject.info["childCount"]):
- # childUI = recyclerViewUIObject.child_by_instance(i)
- # print "cound %s child.info:"%i, childUI.info
- # focusManage.focusFirstItemFromRecyclerView(recyclerViewUIObject, child_class="android.widget.LinearLayout")
- # focusedUIObject = pyui.getFocusedUIObject()
- # print 'focusedUIObject:', focusedUIObject
- # if focusedUIObject:
- # print focusedUIObject.info
|