|
@@ -1,2389 +1,2395 @@
|
|
|
-# -*- 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) #得到UIAutomatorServer实例对象
|
|
|
- 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()
|
|
|
- '''
|
|
|
- 废弃,改用sat_environment.getAdbDeviceSatatus()
|
|
|
- '''
|
|
|
- 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 killAdb(self):
|
|
|
- return u2.killAdb()
|
|
|
-
|
|
|
- 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)
|
|
|
-
|
|
|
- '''
|
|
|
- 用uiautomator view属性键作为paramDIct的键,传入的paramDict里的参数,必须有效。
|
|
|
- 参考session.Selector里的__fields字典
|
|
|
- '''
|
|
|
- def getUiObject2(self, paramDict):
|
|
|
- # print "getUiObject2,paramDict:",paramDict
|
|
|
- uiObject = None
|
|
|
- if paramDict.__len__>0:
|
|
|
- try:
|
|
|
- uiObject = self.u(**paramDict)
|
|
|
- except Exception,e:
|
|
|
- print "UIAutomator未启动,请确认是否为开机状态"
|
|
|
- uiObject = None
|
|
|
- # print uiObject,uiObject.info
|
|
|
- return uiObject
|
|
|
-
|
|
|
- '''
|
|
|
- 作用:获取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='', bounds = '',instance=-1):
|
|
|
-
|
|
|
- if text != "":
|
|
|
- if type(text) is not type([]):
|
|
|
- obj = self.getUiObjectTest(className,resourceId,text,description,bounds,instance)
|
|
|
- return obj
|
|
|
- if type[text] is type([]):
|
|
|
- count = 0
|
|
|
- for t in text:
|
|
|
- try:
|
|
|
- obj = self.getUiObjectTest(className,resourceId,t,description,bounds,instance)
|
|
|
- objInfo = obj.info
|
|
|
- print "文本%s对应的option已找到"%t
|
|
|
- return obj
|
|
|
- except Exception,e:
|
|
|
- nextText = text[count+1]
|
|
|
- print"文本%s对应的option未找到,匹配下一个文本%s"%(t,nextText)
|
|
|
- count += 1
|
|
|
- print "所有文本均已匹配完毕,未找到对应option"
|
|
|
- return None
|
|
|
-
|
|
|
- else:
|
|
|
- obj = self.getUiObjectTest(className,resourceId,text,description,bounds,instance)
|
|
|
- return obj
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- def getUiObjectTest(self, className='', resourceId='', text='', description='', bounds = '',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\
|
|
|
- bounds == "" and instance == -1:
|
|
|
- print "没有参数带入,找不到对象"
|
|
|
- return uiObject
|
|
|
-
|
|
|
- if className != "" and resourceId != "" and text != "" and description != "" and \
|
|
|
- bounds != "" and instance != -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, text=text, description=description,
|
|
|
- bounds=bounds,instance=instance)
|
|
|
- # 缺少一个元素的
|
|
|
- #缺instance
|
|
|
- if className != "" and resourceId != "" and text != "" and description != "" and \
|
|
|
- bounds != "" and instance == -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, text=text, bounds = bounds,
|
|
|
- description=description)
|
|
|
- #缺bounds
|
|
|
- if className != "" and resourceId != "" and text != "" and description != "" and \
|
|
|
- bounds == "" and instance != -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, text=text,
|
|
|
- description=description,instance = instance)
|
|
|
- #缺description
|
|
|
- if className != "" and resourceId != "" and text != "" and description == "" and\
|
|
|
- bounds != "" and instance != -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, text=text,
|
|
|
- bounds=bounds,instance=instance)
|
|
|
- #缺text
|
|
|
- if className != "" and resourceId != "" and text == "" and description != "" and\
|
|
|
- bounds != "" and instance != -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, description=description,
|
|
|
- bounds=bounds,instance=instance)
|
|
|
- #缺resouceId
|
|
|
- if className != "" and resourceId == "" and text != "" and description != "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(className=className, text=text, description=description,
|
|
|
- bounds=bounds,instance=instance)
|
|
|
- # lack of className
|
|
|
- if className == "" and resourceId != "" and text != "" and description != "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(resourceId=resourceId, text=text, description=description,
|
|
|
- bounds=bounds,instance=instance)
|
|
|
-
|
|
|
- # 缺少两个元素的
|
|
|
- # lack of className and resourceId
|
|
|
- if className == "" and resourceId == "" and text != "" and description != "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(text=text, description=description,bounds=bounds,
|
|
|
- instance=instance)
|
|
|
- # lack of className and text
|
|
|
- if className == "" and resourceId != "" and text == "" and description != "" and \
|
|
|
- bounds != "" and instance != -1:
|
|
|
- uiObject = self.u(resourceId=resourceId, description=description, bounds=bounds,
|
|
|
- instance=instance)
|
|
|
- #lack of className and description
|
|
|
- if className == "" and resourceId != "" and text != "" and description == "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(resourceId=resourceId, text=text,bounds=bounds,
|
|
|
- instance=instance)
|
|
|
- # lack of className and bounds
|
|
|
- if className == "" and resourceId != "" and text != "" and description != "" and \
|
|
|
- bounds == "" and instance != -1:
|
|
|
- uiObject = self.u(resourceId=resourceId, text=text, description=description,
|
|
|
- instance=instance)
|
|
|
- # lack of className and instance
|
|
|
- if className == "" and resourceId != "" and text != "" and description != "" and \
|
|
|
- bounds != "" and instance == -1:
|
|
|
- uiObject = self.u(resourceId=resourceId, text=text, description=description,
|
|
|
- bounds=bounds)
|
|
|
- # lack of resourceId and text
|
|
|
- if className != "" and resourceId == "" and text == "" and description != "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(className=className, description=description,bounds=bounds,
|
|
|
- instance=instance)
|
|
|
- # lack of resourceId and description
|
|
|
- if className != "" and resourceId == "" and text != "" and description == "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(className=className, text=text,bounds = bounds,
|
|
|
- instance=instance)
|
|
|
- # lack of resourceId and bounds
|
|
|
- if className != "" and resourceId != "" and text == "" and description != "" and \
|
|
|
- bounds == "" and instance != -1:
|
|
|
- uiObject = self.u(className=className, text=text, description=description,
|
|
|
- instance=instance)
|
|
|
- # lack of resourceId and instance
|
|
|
- if className != "" and resourceId == "" and text != "" and description != "" and \
|
|
|
- bounds != "" and instance == -1:
|
|
|
- uiObject = self.u(className=className, text=text, description=description,
|
|
|
- bounds=bounds)
|
|
|
- # lack of text and description
|
|
|
- if className != "" and resourceId != "" and text == "" and description == "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, bounds=bounds,
|
|
|
- instance=instance)
|
|
|
- # lack of text and bounds
|
|
|
- if className != "" and resourceId != "" and text == "" and description != "" and \
|
|
|
- bounds=="" and instance != -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId,
|
|
|
- description=description,instance=instance)
|
|
|
- # lack of text and instance
|
|
|
- if className != "" and resourceId != "" and text == "" and description != "" and \
|
|
|
- bounds!="" and instance == -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId,
|
|
|
- description=description,bounds=bounds)
|
|
|
- # lack of description and bounds
|
|
|
- if className != "" and resourceId != "" and text != "" and description == "" and \
|
|
|
- bounds=="" and instance != -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, text = text,
|
|
|
- instance=instance)
|
|
|
- # lack of description and instance
|
|
|
- if className != "" and resourceId != "" and text != "" and description == "" and \
|
|
|
- bounds!="" and instance == -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, text = text,
|
|
|
- bounds=bounds)
|
|
|
- # lack of bounds and instance
|
|
|
- if className != "" and resourceId != "" and text != "" and description != "" and \
|
|
|
- bounds=="" and instance == -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, text = text,
|
|
|
- description=description)
|
|
|
-
|
|
|
- # 缺少3个元素
|
|
|
- # lack of className and resourceId and text
|
|
|
- if className == "" and resourceId == "" and text == "" and description != "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(description=description, bounds=bounds,instance=instance)
|
|
|
- # lack of className and resourceId and description
|
|
|
- if className == "" and resourceId == "" and text != "" and description == "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(text = text,bounds=bounds,instance=instance)
|
|
|
- # lack of className and resourceId and bounds
|
|
|
- if className == "" and resourceId == "" and text != "" and description != "" and \
|
|
|
- bounds =="" and instance != -1:
|
|
|
- uiObject = self.u(text = text,description=description,instance=instance)
|
|
|
- # lack of className and resourceId and instance
|
|
|
- if className == "" and resourceId == "" and text != "" and description != "" and \
|
|
|
- bounds!="" and instance == -1:
|
|
|
- uiObject = self.u(text = text,description=description,bounds=bounds)
|
|
|
- # lack of className and text and description
|
|
|
- if className == "" and resourceId != "" and text == "" and description == "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(resourceId=resourceId,bounds=bounds,instance=instance)
|
|
|
- # lack of className and text and bounds
|
|
|
- if className == "" and resourceId != "" and text == "" and description != "" and \
|
|
|
- bounds=="" and instance != -1:
|
|
|
- uiObject = self.u(resourceId=resourceId,description=description,instance=instance)
|
|
|
- # lack of className and text and instance
|
|
|
- if className == "" and resourceId != "" and text == "" and description != "" and \
|
|
|
- bounds!="" and instance == -1:
|
|
|
- uiObject = self.u(resourceId=resourceId,description=description,bounds=bounds)
|
|
|
- # lack of className and description and bounds
|
|
|
- if className == "" and resourceId != "" and text != "" and description == "" and \
|
|
|
- bounds=="" and instance != -1:
|
|
|
- uiObject = self.u(resourceId=resourceId, text = text,instance=instance)
|
|
|
- # lack of className and description and instance
|
|
|
- if className == "" and resourceId != "" and text != "" and description == "" and \
|
|
|
- bounds!="" and instance == -1:
|
|
|
- uiObject = self.u(resourceId=resourceId, text = text,bounds=bounds)
|
|
|
- # lack of resourceId and text and description
|
|
|
- if className != "" and resourceId == "" and text == "" and description == "" and \
|
|
|
- bounds!="" and instance != -1:
|
|
|
- uiObject = self.u(className=className,bounds=bounds,instance=instance)
|
|
|
- # lack of resourceId and text and bounds
|
|
|
- if className != "" and resourceId == "" and text == "" and description != "" and \
|
|
|
- bounds=="" and instance != -1:
|
|
|
- uiObject = self.u(className=className,description=description,instance=instance)
|
|
|
- # lack of resourceId and text and instance
|
|
|
- if className != "" and resourceId == "" and text == "" and description != "" and \
|
|
|
- bounds!="" and instance == -1:
|
|
|
- uiObject = self.u(className=className,description=description,bounds=bounds)
|
|
|
- # lack of resourceId and description and bounds
|
|
|
- if className != "" and resourceId == "" and text != "" and description == "" and \
|
|
|
- bounds =="" and instance != -1:
|
|
|
- uiObject = self.u(className=className,text = text,instance=instance)
|
|
|
- # lack of resourceId and description and instance
|
|
|
- if className != "" and resourceId == "" and text != "" and description == "" and \
|
|
|
- bounds!="" and instance == -1:
|
|
|
- uiObject = self.u(className=className, text = text,bounds=bounds)
|
|
|
- # lack of resourceId and bounds and instance
|
|
|
- if className != "" and resourceId == "" and text != "" and description != "" and \
|
|
|
- bounds =="" and instance == -1:
|
|
|
- uiObject = self.u(className=className, text = text,description=description)
|
|
|
- # lack of text and description and bounds
|
|
|
- if className != "" and resourceId != "" and text == "" and description == "" and \
|
|
|
- bounds=="" and instance != -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId,instance=instance)
|
|
|
- # lack of text and description and instance
|
|
|
- if className != "" and resourceId != "" and text == "" and description == "" and \
|
|
|
- bounds!="" and instance == -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId,bounds=bounds)
|
|
|
- # lack of description and bounds and instance
|
|
|
- if className != "" and resourceId != "" and text != "" and description == "" and \
|
|
|
- bounds =="" and instance == -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId, text = text)
|
|
|
-
|
|
|
- # 缺少4个元素
|
|
|
- # lack of className and resourceId and text and description
|
|
|
- if className == "" and resourceId == "" and text == "" and description == "" and \
|
|
|
- bounds !="" and instance != -1:
|
|
|
- uiObject = self.u(bounds=bounds,instance=instance)
|
|
|
- # lack of className and resourceId and text and bounds
|
|
|
- if className == "" and resourceId == "" and text == "" and description != "" and \
|
|
|
- bounds =="" and instance != -1:
|
|
|
- uiObject = self.u(description=description,instance=instance)
|
|
|
- # lack of className and resourceId and text and instance
|
|
|
- if className == "" and resourceId == "" and text == "" and description != "" and \
|
|
|
- bounds !="" and instance == -1:
|
|
|
- uiObject = self.u(description=description,bounds=bounds)
|
|
|
- # lack of className and resourceId and description and bounds
|
|
|
- if className == "" and resourceId == "" and text != "" and description == "" and \
|
|
|
- bounds =="" and instance != -1:
|
|
|
- uiObject = self.u(text = text,instance=instance)
|
|
|
- # lack of className and resourceId and description and instance
|
|
|
- if className == "" and resourceId == "" and text != "" and description == "" and \
|
|
|
- bounds !="" and instance == -1:
|
|
|
- uiObject = self.u(text = text,bounds=bounds)
|
|
|
- # lack of resourceid and text and description and bounds
|
|
|
- if className != "" and resourceId == "" and text == "" and description == "" and \
|
|
|
- bounds =="" and instance != -1:
|
|
|
- uiObject = self.u(className=className,instance=instance)
|
|
|
- # lack of resourceid and text and description and instance
|
|
|
- if className != "" and resourceId == "" and text == "" and description == "" and \
|
|
|
- bounds !="" and instance == -1:
|
|
|
- uiObject = self.u(className=className,bounds=bounds)
|
|
|
- # lack of text and description and bounds and instance
|
|
|
- if className != "" and resourceId != "" and text == "" and description == "" and \
|
|
|
- bounds =="" and instance == -1:
|
|
|
- uiObject = self.u(className=className, resourceId=resourceId)
|
|
|
-
|
|
|
- # 缺少5个元素的
|
|
|
- # only className
|
|
|
- if className != "" and resourceId == "" and text == "" and description == "" and \
|
|
|
- bounds =="" and instance == -1:
|
|
|
- uiObject = self.u(className=className)
|
|
|
- # only resourceid
|
|
|
- if className == "" and resourceId != "" and text == "" and description == "" and \
|
|
|
- bounds =="" and instance == -1:
|
|
|
- uiObject = self.u(resourceId=resourceId)
|
|
|
- # only text
|
|
|
- if className == "" and resourceId == "" and text != "" and description == "" and \
|
|
|
- bounds =="" and instance == -1:
|
|
|
- uiObject = self.u(text = text)
|
|
|
- # only description
|
|
|
- if className == "" and resourceId == "" and text == "" and description != "" and \
|
|
|
- bounds =="" and instance == -1:
|
|
|
- uiObject = self.u(description=description)
|
|
|
- # only bounds
|
|
|
- if className == "" and resourceId == "" and text == "" and description == "" and \
|
|
|
- bounds !="" and instance == -1:
|
|
|
- uiObject = self.u(bounds=bounds)
|
|
|
- # only instance
|
|
|
- if className == "" and resourceId == "" and text == "" and description == "" and \
|
|
|
- bounds =="" and instance == -1:
|
|
|
- uiObject = self.u(instance=instance)
|
|
|
- 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, moveKey=["down","up"]):
|
|
|
- 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)))
|
|
|
- if self.hasSameArea(areaL,areaT):
|
|
|
- focusCP = [(areaL[2] + areaL[0])/2,(areaL[3]+areaL[1])/2]
|
|
|
- destCP = [(areaT[2] + areaT[0])/2,(areaT[3]+areaT[1])/2]
|
|
|
- return self.getPointDirection(focusCP,destCP)
|
|
|
- # 确定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):
|
|
|
- if "down" in moveKey:
|
|
|
- return "down-right"
|
|
|
- else:
|
|
|
- return "right-down"
|
|
|
- if (dL_Ux < 0) and (dL_Uy > 0):
|
|
|
- if "down" in moveKey:
|
|
|
- return "down-left"
|
|
|
- else:
|
|
|
- return "left-down"
|
|
|
- if (dL_Ux > 0) and (dL_Uy < 0):
|
|
|
- if "down" in moveKey:
|
|
|
- return "up-right"
|
|
|
- else:
|
|
|
- return "right-up"
|
|
|
- if (dL_Ux < 0) and (dL_Uy < 0):
|
|
|
- if "down" in moveKey:
|
|
|
- return "up-left"
|
|
|
- else:
|
|
|
- return "left-up"
|
|
|
-
|
|
|
- '''
|
|
|
- 计算点p2相对p1的方位。按p1 45°斜线划分上下左右。
|
|
|
- '''
|
|
|
- def getPointDirection(self,p1,p2):
|
|
|
- print "getPointDirection,p1,p2:",p1,p2
|
|
|
- dx = p2[0] - p1[0]
|
|
|
- dy = p2[1] - p1[1]
|
|
|
- if dx >= 0 and abs(dy) < abs(dx):
|
|
|
- return "right"
|
|
|
- if dx <= 0 and abs(dy) < abs(dx):
|
|
|
- return "left"
|
|
|
- if dy >= 0 and abs(dy) >= abs(dx):
|
|
|
- return "down"
|
|
|
- if dy <= 0 and abs(dy) >= abs(dx):
|
|
|
- return "up"
|
|
|
- return "center"
|
|
|
-
|
|
|
-
|
|
|
- '''
|
|
|
- 检测两个区域是否有重叠部分
|
|
|
- '''
|
|
|
-
|
|
|
- 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
|
|
|
-
|
|
|
-
|
|
|
- # 在RecyclerView 中 focused控件包含bounds控件
|
|
|
- def toDestFocusByBounds_for_RecyclerView(self, bounds, boundsResourceId="", 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']
|
|
|
- if hb_keyDict != {}:
|
|
|
- # 执行心跳按键
|
|
|
- self.executeHeartBeatKey(hb_keyDict)
|
|
|
- try:
|
|
|
- destBounds = bounds
|
|
|
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds,destBounds):
|
|
|
- print "success to focus the target:",bounds
|
|
|
- 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
|
|
|
-
|
|
|
- # class&Bounds
|
|
|
- def toDestFocusByClassBounds_for_RecyclerView(self, className, bounds,classResourceId="", 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()
|
|
|
- print "zhouyifocusedUIObject",focusedUIObject
|
|
|
- print "zhouyifocusedUIObject.info", focusedUIObject.info
|
|
|
- if hb_keyDict != {}:
|
|
|
- # 执行心跳按键
|
|
|
- self.executeHeartBeatKey(hb_keyDict)
|
|
|
- destUIObject = self.u.getUiObject(className=className, bounds = bounds,resourceId=classResourceId)
|
|
|
- print "destUIObject",destUIObject
|
|
|
- try:
|
|
|
- destUIObjectInfo = destUIObject.info
|
|
|
- print "destUIObjectInfo",destUIObjectInfo
|
|
|
- except Exception,e:
|
|
|
- print "异常:",e
|
|
|
- # print "destUIObject.info",destUIObjectInfo
|
|
|
- try:
|
|
|
- # destBounds = destUIObject.info['bounds']
|
|
|
- destBounds = bounds
|
|
|
- print "destBounds:", destBounds
|
|
|
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds,destBounds):
|
|
|
- print "c&b success to focus the target:",bounds
|
|
|
- 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
|
|
|
-
|
|
|
- # class
|
|
|
- def toDestFocusByClass_for_RecyclerView(self, className, classResourceId="", 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()
|
|
|
- print "zhouyifocusedUIObject", focusedUIObject
|
|
|
- print "zhouyifocusedUIObject.info", focusedUIObject.info
|
|
|
- if hb_keyDict != {}:
|
|
|
- # 执行心跳按键
|
|
|
- self.executeHeartBeatKey(hb_keyDict)
|
|
|
- destUIObject = self.u.getUiObject(className=className, resourceId=classResourceId)
|
|
|
- print "destUIObject", destUIObject
|
|
|
- try:
|
|
|
- destUIObjectInfo = destUIObject.info
|
|
|
- print "destUIObjectInfo", destUIObjectInfo
|
|
|
- except Exception, e:
|
|
|
- print "异常:", e
|
|
|
- # print "destUIObject.info",destUIObjectInfo
|
|
|
- try:
|
|
|
- destBounds = destUIObject.info['bounds']
|
|
|
- print "destBounds:", destBounds
|
|
|
- if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
|
|
|
- print '成功聚焦到目标焦点:', bounds
|
|
|
- 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
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- # zhouyi
|
|
|
- def toDestTargetByBounds_for_RecyclerView(self, bounds, 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(bounds=bounds)
|
|
|
- # print "targetUIObject",targetUIObject
|
|
|
- # print "zhouyibounds",bounds
|
|
|
- # print "targetUIObject.info:", targetUIObject.info
|
|
|
- # destBounds = targetUIObject.info['bounds']
|
|
|
- destBounds = 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.toDestTargetByBounds_for_RecyclerView(bounds, 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
|
|
|
-
|
|
|
- '''
|
|
|
- 作用:在界面中 中 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):
|
|
|
- print "pressKeyByType:",keyName,keyType
|
|
|
- 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
|
|
|
+# -*- 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) #得到UIAutomatorServer实例对象
|
|
|
+ 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()
|
|
|
+ '''
|
|
|
+ 废弃,改用sat_environment.getAdbDeviceSatatus()
|
|
|
+ '''
|
|
|
+ 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 killAdb(self):
|
|
|
+ return u2.killAdb()
|
|
|
+
|
|
|
+ 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)
|
|
|
+
|
|
|
+ '''
|
|
|
+ 用uiautomator view属性键作为paramDIct的键,传入的paramDict里的参数,必须有效。
|
|
|
+ 参考session.Selector里的__fields字典
|
|
|
+ '''
|
|
|
+ def getUiObject2(self, paramDict):
|
|
|
+ # print "getUiObject2,paramDict:",paramDict
|
|
|
+ uiObject = None
|
|
|
+ if paramDict.__len__>0:
|
|
|
+ try:
|
|
|
+ uiObject = self.u(**paramDict)
|
|
|
+ except Exception,e:
|
|
|
+ print "UIAutomator未启动,请确认是否为开机状态"
|
|
|
+ uiObject = None
|
|
|
+ # print uiObject,uiObject.info
|
|
|
+ return uiObject
|
|
|
+
|
|
|
+ '''
|
|
|
+ 作用:获取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='', bounds = '',instance=-1):
|
|
|
+
|
|
|
+ if text != "":
|
|
|
+ if type(text) is not type([]):
|
|
|
+ obj = self.getUiObjectTest(className,resourceId,text,description,bounds,instance)
|
|
|
+ return obj
|
|
|
+ if type(text) is type([]):
|
|
|
+ count = 0
|
|
|
+ for t in text:
|
|
|
+ try:
|
|
|
+ obj = self.getUiObjectTest(className,resourceId,t,description,bounds,instance)
|
|
|
+ objInfo = obj.info
|
|
|
+ print "文本%s对应的option已找到"%t
|
|
|
+ return obj
|
|
|
+ except Exception,e:
|
|
|
+ nextText = text[count+1]
|
|
|
+ print"文本%s对应的option未找到,匹配下一个文本%s"%(t,nextText)
|
|
|
+ count += 1
|
|
|
+ print "所有文本均已匹配完毕,未找到对应option"
|
|
|
+ class object():
|
|
|
+ exists = False
|
|
|
+ obj = object()
|
|
|
+ return obj
|
|
|
+ else:
|
|
|
+ obj = self.getUiObjectTest(className,resourceId,text,description,bounds,instance)
|
|
|
+ return obj
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ def getUiObjectTest(self, className='', resourceId='', text='', description='', bounds = '',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\
|
|
|
+ bounds == "" and instance == -1:
|
|
|
+ print "没有参数带入,找不到对象"
|
|
|
+ return uiObject
|
|
|
+
|
|
|
+ if className != "" and resourceId != "" and text != "" and description != "" and \
|
|
|
+ bounds != "" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, text=text, description=description,
|
|
|
+ bounds=bounds,instance=instance)
|
|
|
+ # 缺少一个元素的
|
|
|
+ #缺instance
|
|
|
+ if className != "" and resourceId != "" and text != "" and description != "" and \
|
|
|
+ bounds != "" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, text=text, bounds = bounds,
|
|
|
+ description=description)
|
|
|
+ #缺bounds
|
|
|
+ if className != "" and resourceId != "" and text != "" and description != "" and \
|
|
|
+ bounds == "" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, text=text,
|
|
|
+ description=description,instance = instance)
|
|
|
+ #缺description
|
|
|
+ if className != "" and resourceId != "" and text != "" and description == "" and\
|
|
|
+ bounds != "" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, text=text,
|
|
|
+ bounds=bounds,instance=instance)
|
|
|
+ #缺text
|
|
|
+ if className != "" and resourceId != "" and text == "" and description != "" and\
|
|
|
+ bounds != "" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, description=description,
|
|
|
+ bounds=bounds,instance=instance)
|
|
|
+ #缺resouceId
|
|
|
+ if className != "" and resourceId == "" and text != "" and description != "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, text=text, description=description,
|
|
|
+ bounds=bounds,instance=instance)
|
|
|
+ # lack of className
|
|
|
+ if className == "" and resourceId != "" and text != "" and description != "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId, text=text, description=description,
|
|
|
+ bounds=bounds,instance=instance)
|
|
|
+
|
|
|
+ # 缺少两个元素的
|
|
|
+ # lack of className and resourceId
|
|
|
+ if className == "" and resourceId == "" and text != "" and description != "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(text=text, description=description,bounds=bounds,
|
|
|
+ instance=instance)
|
|
|
+ # lack of className and text
|
|
|
+ if className == "" and resourceId != "" and text == "" and description != "" and \
|
|
|
+ bounds != "" and instance != -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId, description=description, bounds=bounds,
|
|
|
+ instance=instance)
|
|
|
+ #lack of className and description
|
|
|
+ if className == "" and resourceId != "" and text != "" and description == "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId, text=text,bounds=bounds,
|
|
|
+ instance=instance)
|
|
|
+ # lack of className and bounds
|
|
|
+ if className == "" and resourceId != "" and text != "" and description != "" and \
|
|
|
+ bounds == "" and instance != -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId, text=text, description=description,
|
|
|
+ instance=instance)
|
|
|
+ # lack of className and instance
|
|
|
+ if className == "" and resourceId != "" and text != "" and description != "" and \
|
|
|
+ bounds != "" and instance == -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId, text=text, description=description,
|
|
|
+ bounds=bounds)
|
|
|
+ # lack of resourceId and text
|
|
|
+ if className != "" and resourceId == "" and text == "" and description != "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, description=description,bounds=bounds,
|
|
|
+ instance=instance)
|
|
|
+ # lack of resourceId and description
|
|
|
+ if className != "" and resourceId == "" and text != "" and description == "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, text=text,bounds = bounds,
|
|
|
+ instance=instance)
|
|
|
+ # lack of resourceId and bounds
|
|
|
+ if className != "" and resourceId != "" and text == "" and description != "" and \
|
|
|
+ bounds == "" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, text=text, description=description,
|
|
|
+ instance=instance)
|
|
|
+ # lack of resourceId and instance
|
|
|
+ if className != "" and resourceId == "" and text != "" and description != "" and \
|
|
|
+ bounds != "" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, text=text, description=description,
|
|
|
+ bounds=bounds)
|
|
|
+ # lack of text and description
|
|
|
+ if className != "" and resourceId != "" and text == "" and description == "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, bounds=bounds,
|
|
|
+ instance=instance)
|
|
|
+ # lack of text and bounds
|
|
|
+ if className != "" and resourceId != "" and text == "" and description != "" and \
|
|
|
+ bounds=="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId,
|
|
|
+ description=description,instance=instance)
|
|
|
+ # lack of text and instance
|
|
|
+ if className != "" and resourceId != "" and text == "" and description != "" and \
|
|
|
+ bounds!="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId,
|
|
|
+ description=description,bounds=bounds)
|
|
|
+ # lack of description and bounds
|
|
|
+ if className != "" and resourceId != "" and text != "" and description == "" and \
|
|
|
+ bounds=="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, text = text,
|
|
|
+ instance=instance)
|
|
|
+ # lack of description and instance
|
|
|
+ if className != "" and resourceId != "" and text != "" and description == "" and \
|
|
|
+ bounds!="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, text = text,
|
|
|
+ bounds=bounds)
|
|
|
+ # lack of bounds and instance
|
|
|
+ if className != "" and resourceId != "" and text != "" and description != "" and \
|
|
|
+ bounds=="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, text = text,
|
|
|
+ description=description)
|
|
|
+
|
|
|
+ # 缺少3个元素
|
|
|
+ # lack of className and resourceId and text
|
|
|
+ if className == "" and resourceId == "" and text == "" and description != "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(description=description, bounds=bounds,instance=instance)
|
|
|
+ # lack of className and resourceId and description
|
|
|
+ if className == "" and resourceId == "" and text != "" and description == "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(text = text,bounds=bounds,instance=instance)
|
|
|
+ # lack of className and resourceId and bounds
|
|
|
+ if className == "" and resourceId == "" and text != "" and description != "" and \
|
|
|
+ bounds =="" and instance != -1:
|
|
|
+ uiObject = self.u(text = text,description=description,instance=instance)
|
|
|
+ # lack of className and resourceId and instance
|
|
|
+ if className == "" and resourceId == "" and text != "" and description != "" and \
|
|
|
+ bounds!="" and instance == -1:
|
|
|
+ uiObject = self.u(text = text,description=description,bounds=bounds)
|
|
|
+ # lack of className and text and description
|
|
|
+ if className == "" and resourceId != "" and text == "" and description == "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId,bounds=bounds,instance=instance)
|
|
|
+ # lack of className and text and bounds
|
|
|
+ if className == "" and resourceId != "" and text == "" and description != "" and \
|
|
|
+ bounds=="" and instance != -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId,description=description,instance=instance)
|
|
|
+ # lack of className and text and instance
|
|
|
+ if className == "" and resourceId != "" and text == "" and description != "" and \
|
|
|
+ bounds!="" and instance == -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId,description=description,bounds=bounds)
|
|
|
+ # lack of className and description and bounds
|
|
|
+ if className == "" and resourceId != "" and text != "" and description == "" and \
|
|
|
+ bounds=="" and instance != -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId, text = text,instance=instance)
|
|
|
+ # lack of className and description and instance
|
|
|
+ if className == "" and resourceId != "" and text != "" and description == "" and \
|
|
|
+ bounds!="" and instance == -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId, text = text,bounds=bounds)
|
|
|
+ # lack of resourceId and text and description
|
|
|
+ if className != "" and resourceId == "" and text == "" and description == "" and \
|
|
|
+ bounds!="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className,bounds=bounds,instance=instance)
|
|
|
+ # lack of resourceId and text and bounds
|
|
|
+ if className != "" and resourceId == "" and text == "" and description != "" and \
|
|
|
+ bounds=="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className,description=description,instance=instance)
|
|
|
+ # lack of resourceId and text and instance
|
|
|
+ if className != "" and resourceId == "" and text == "" and description != "" and \
|
|
|
+ bounds!="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className,description=description,bounds=bounds)
|
|
|
+ # lack of resourceId and description and bounds
|
|
|
+ if className != "" and resourceId == "" and text != "" and description == "" and \
|
|
|
+ bounds =="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className,text = text,instance=instance)
|
|
|
+ # lack of resourceId and description and instance
|
|
|
+ if className != "" and resourceId == "" and text != "" and description == "" and \
|
|
|
+ bounds!="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, text = text,bounds=bounds)
|
|
|
+ # lack of resourceId and bounds and instance
|
|
|
+ if className != "" and resourceId == "" and text != "" and description != "" and \
|
|
|
+ bounds =="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, text = text,description=description)
|
|
|
+ # lack of text and description and bounds
|
|
|
+ if className != "" and resourceId != "" and text == "" and description == "" and \
|
|
|
+ bounds=="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId,instance=instance)
|
|
|
+ # lack of text and description and instance
|
|
|
+ if className != "" and resourceId != "" and text == "" and description == "" and \
|
|
|
+ bounds!="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId,bounds=bounds)
|
|
|
+ # lack of description and bounds and instance
|
|
|
+ if className != "" and resourceId != "" and text != "" and description == "" and \
|
|
|
+ bounds =="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId, text = text)
|
|
|
+
|
|
|
+ # 缺少4个元素
|
|
|
+ # lack of className and resourceId and text and description
|
|
|
+ if className == "" and resourceId == "" and text == "" and description == "" and \
|
|
|
+ bounds !="" and instance != -1:
|
|
|
+ uiObject = self.u(bounds=bounds,instance=instance)
|
|
|
+ # lack of className and resourceId and text and bounds
|
|
|
+ if className == "" and resourceId == "" and text == "" and description != "" and \
|
|
|
+ bounds =="" and instance != -1:
|
|
|
+ uiObject = self.u(description=description,instance=instance)
|
|
|
+ # lack of className and resourceId and text and instance
|
|
|
+ if className == "" and resourceId == "" and text == "" and description != "" and \
|
|
|
+ bounds !="" and instance == -1:
|
|
|
+ uiObject = self.u(description=description,bounds=bounds)
|
|
|
+ # lack of className and resourceId and description and bounds
|
|
|
+ if className == "" and resourceId == "" and text != "" and description == "" and \
|
|
|
+ bounds =="" and instance != -1:
|
|
|
+ uiObject = self.u(text = text,instance=instance)
|
|
|
+ # lack of className and resourceId and description and instance
|
|
|
+ if className == "" and resourceId == "" and text != "" and description == "" and \
|
|
|
+ bounds !="" and instance == -1:
|
|
|
+ uiObject = self.u(text = text,bounds=bounds)
|
|
|
+ # lack of resourceid and text and description and bounds
|
|
|
+ if className != "" and resourceId == "" and text == "" and description == "" and \
|
|
|
+ bounds =="" and instance != -1:
|
|
|
+ uiObject = self.u(className=className,instance=instance)
|
|
|
+ # lack of resourceid and text and description and instance
|
|
|
+ if className != "" and resourceId == "" and text == "" and description == "" and \
|
|
|
+ bounds !="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className,bounds=bounds)
|
|
|
+ # lack of text and description and bounds and instance
|
|
|
+ if className != "" and resourceId != "" and text == "" and description == "" and \
|
|
|
+ bounds =="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className, resourceId=resourceId)
|
|
|
+
|
|
|
+ # 缺少5个元素的
|
|
|
+ # only className
|
|
|
+ if className != "" and resourceId == "" and text == "" and description == "" and \
|
|
|
+ bounds =="" and instance == -1:
|
|
|
+ uiObject = self.u(className=className)
|
|
|
+ # only resourceid
|
|
|
+ if className == "" and resourceId != "" and text == "" and description == "" and \
|
|
|
+ bounds =="" and instance == -1:
|
|
|
+ uiObject = self.u(resourceId=resourceId)
|
|
|
+ # only text
|
|
|
+ if className == "" and resourceId == "" and text != "" and description == "" and \
|
|
|
+ bounds =="" and instance == -1:
|
|
|
+ uiObject = self.u(text = text)
|
|
|
+ # only description
|
|
|
+ if className == "" and resourceId == "" and text == "" and description != "" and \
|
|
|
+ bounds =="" and instance == -1:
|
|
|
+ uiObject = self.u(description=description)
|
|
|
+ # only bounds
|
|
|
+ if className == "" and resourceId == "" and text == "" and description == "" and \
|
|
|
+ bounds !="" and instance == -1:
|
|
|
+ uiObject = self.u(bounds=bounds)
|
|
|
+ # only instance
|
|
|
+ if className == "" and resourceId == "" and text == "" and description == "" and \
|
|
|
+ bounds =="" and instance == -1:
|
|
|
+ uiObject = self.u(instance=instance)
|
|
|
+ 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, moveKey=["down","up"]):
|
|
|
+ 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)))
|
|
|
+ if self.hasSameArea(areaL,areaT):
|
|
|
+ focusCP = [(areaL[2] + areaL[0])/2,(areaL[3]+areaL[1])/2]
|
|
|
+ destCP = [(areaT[2] + areaT[0])/2,(areaT[3]+areaT[1])/2]
|
|
|
+ return self.getPointDirection(focusCP,destCP)
|
|
|
+ # 确定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):
|
|
|
+ if "down" in moveKey:
|
|
|
+ return "down-right"
|
|
|
+ else:
|
|
|
+ return "right-down"
|
|
|
+ if (dL_Ux < 0) and (dL_Uy > 0):
|
|
|
+ if "down" in moveKey:
|
|
|
+ return "down-left"
|
|
|
+ else:
|
|
|
+ return "left-down"
|
|
|
+ if (dL_Ux > 0) and (dL_Uy < 0):
|
|
|
+ if "down" in moveKey:
|
|
|
+ return "up-right"
|
|
|
+ else:
|
|
|
+ return "right-up"
|
|
|
+ if (dL_Ux < 0) and (dL_Uy < 0):
|
|
|
+ if "down" in moveKey:
|
|
|
+ return "up-left"
|
|
|
+ else:
|
|
|
+ return "left-up"
|
|
|
+
|
|
|
+ '''
|
|
|
+ 计算点p2相对p1的方位。按p1 45°斜线划分上下左右。
|
|
|
+ '''
|
|
|
+ def getPointDirection(self,p1,p2):
|
|
|
+ print "getPointDirection,p1,p2:",p1,p2
|
|
|
+ dx = p2[0] - p1[0]
|
|
|
+ dy = p2[1] - p1[1]
|
|
|
+ if dx >= 0 and abs(dy) < abs(dx):
|
|
|
+ return "right"
|
|
|
+ if dx <= 0 and abs(dy) < abs(dx):
|
|
|
+ return "left"
|
|
|
+ if dy >= 0 and abs(dy) >= abs(dx):
|
|
|
+ return "down"
|
|
|
+ if dy <= 0 and abs(dy) >= abs(dx):
|
|
|
+ return "up"
|
|
|
+ return "center"
|
|
|
+
|
|
|
+
|
|
|
+ '''
|
|
|
+ 检测两个区域是否有重叠部分
|
|
|
+ '''
|
|
|
+
|
|
|
+ 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
|
|
|
+
|
|
|
+
|
|
|
+ # 在RecyclerView 中 focused控件包含bounds控件
|
|
|
+ def toDestFocusByBounds_for_RecyclerView(self, bounds, boundsResourceId="", 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']
|
|
|
+ if hb_keyDict != {}:
|
|
|
+ # 执行心跳按键
|
|
|
+ self.executeHeartBeatKey(hb_keyDict)
|
|
|
+ try:
|
|
|
+ destBounds = bounds
|
|
|
+ if self.directionManageAndroid.isHasAnotherBounds(focusedBounds,destBounds):
|
|
|
+ print "success to focus the target:",bounds
|
|
|
+ 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
|
|
|
+
|
|
|
+ # class&Bounds
|
|
|
+ def toDestFocusByClassBounds_for_RecyclerView(self, className, bounds,classResourceId="", 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()
|
|
|
+ print "zhouyifocusedUIObject",focusedUIObject
|
|
|
+ print "zhouyifocusedUIObject.info", focusedUIObject.info
|
|
|
+ if hb_keyDict != {}:
|
|
|
+ # 执行心跳按键
|
|
|
+ self.executeHeartBeatKey(hb_keyDict)
|
|
|
+ destUIObject = self.u.getUiObject(className=className, bounds = bounds,resourceId=classResourceId)
|
|
|
+ print "destUIObject",destUIObject
|
|
|
+ try:
|
|
|
+ destUIObjectInfo = destUIObject.info
|
|
|
+ print "destUIObjectInfo",destUIObjectInfo
|
|
|
+ except Exception,e:
|
|
|
+ print "异常:",e
|
|
|
+ # print "destUIObject.info",destUIObjectInfo
|
|
|
+ try:
|
|
|
+ # destBounds = destUIObject.info['bounds']
|
|
|
+ destBounds = bounds
|
|
|
+ print "destBounds:", destBounds
|
|
|
+ if self.directionManageAndroid.isHasAnotherBounds(focusedBounds,destBounds):
|
|
|
+ print "c&b success to focus the target:",bounds
|
|
|
+ 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
|
|
|
+
|
|
|
+ # class
|
|
|
+ def toDestFocusByClass_for_RecyclerView(self, className, classResourceId="", 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()
|
|
|
+ print "zhouyifocusedUIObject", focusedUIObject
|
|
|
+ print "zhouyifocusedUIObject.info", focusedUIObject.info
|
|
|
+ if hb_keyDict != {}:
|
|
|
+ # 执行心跳按键
|
|
|
+ self.executeHeartBeatKey(hb_keyDict)
|
|
|
+ destUIObject = self.u.getUiObject(className=className, resourceId=classResourceId)
|
|
|
+ print "destUIObject", destUIObject
|
|
|
+ try:
|
|
|
+ destUIObjectInfo = destUIObject.info
|
|
|
+ print "destUIObjectInfo", destUIObjectInfo
|
|
|
+ except Exception, e:
|
|
|
+ print "异常:", e
|
|
|
+ # print "destUIObject.info",destUIObjectInfo
|
|
|
+ try:
|
|
|
+ destBounds = destUIObject.info['bounds']
|
|
|
+ print "destBounds:", destBounds
|
|
|
+ if self.directionManageAndroid.isHasAnotherBounds(focusedBounds, destBounds):
|
|
|
+ print '成功聚焦到目标焦点:', bounds
|
|
|
+ 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
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ # zhouyi
|
|
|
+ def toDestTargetByBounds_for_RecyclerView(self, bounds, 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(bounds=bounds)
|
|
|
+ # print "targetUIObject",targetUIObject
|
|
|
+ # print "zhouyibounds",bounds
|
|
|
+ # print "targetUIObject.info:", targetUIObject.info
|
|
|
+ # destBounds = targetUIObject.info['bounds']
|
|
|
+ destBounds = 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.toDestTargetByBounds_for_RecyclerView(bounds, 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
|
|
|
+
|
|
|
+ '''
|
|
|
+ 作用:在界面中 中 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='', FocusViewClass='',FocusViewDesc='',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)
|
|
|
+ if FocusViewResourceId is not '':
|
|
|
+ focusedUIObject = self.u.getUiObject(resourceId=FocusViewResourceId)
|
|
|
+ else:
|
|
|
+ focusedUIObject = self.u.getUiObject(description=FocusViewDesc,className=FocusViewClass)
|
|
|
+
|
|
|
+ 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):
|
|
|
+ print "pressKeyByType:",keyName,keyType
|
|
|
+ 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
|