灵虚御风
醉饮千觞不知愁,忘川来生空余恨!

导航

 
  1 import os, importlib
  2 import uiautomator2 as u2
  3 import traceback
  4 
  5 from android import AndroidDevice
  6 from log import *
  7 
  8 ANDROID_MIXIN_BASE_LIST = []
  9 ANDROID_VERSION_LIST = []
 10 android_device_root_path = os.path.join(os.path.dirname(os.path.abspath(__file__)))
 11 for root,dirs,files in os.walk(android_device_root_path):
 12     for f in files:
 13         if f.endswith('_mixin.py'):
 14             mixin_package = f.replace('.py', '')
 15             mixin_class_name = ''.join([x.capitalize() for x in mixin_package.split('_')])
 16             #mixin_package = '.join'(['android', mixin_package, mixin_class_name])
 17             if mixin_package not in [m[0] for m in ANDROID_MIXIN_BASE_LIST]:
 18                 ANDROID_MIXIN_BASE_LIST.append([mixin_package, mixin_class_name])
 19     for dir in dirs:
 20         if dir.isdigit():
 21             ANDROID_VERSION_LIST.append(int(dir))
 22         elif dir.replace('_','',1).isdigit() and dir.count('_') < 2:
 23             ANDROID_VERSION_LIST.append(float(dir.replace('_', '.')))
 24 ANDROID_VERSION_LIST.sort(reverse=True)
 25 
 26 class AndroidUiDevice(AndroidDevice):
 27     """Android Device library for Android OS functions automation
 28 
 29         This library is based on AndroidDevice library
 30 
 31         Pre-requirements
 32             install uiautomator2 on host.
 33 
 34         Using Library
 35         --------------
 36 
 37         Author:
 38         tonglinx.ding@intel.com
 39         shuang.zheng@intel.com
 40 
 41         """
 42     def __init__(self, version=None, uart_handle=None, **kwargs):
 43         ''' __init__ for android device Library.
 44 
 45         '''
 46         self._version = version
 47         self._d = None
 48         super().__init__(version, uart_handle, **kwargs)
 49 
 50         mixin_class_list = self._get_mixin_classes(self._version)
 51         # log_info(mixin_class_list)
 52         AndroidUiDevice.__bases__ = tuple(mixin_class_list) + (AndroidDevice, object,)
 53 
 54     def init(self, serial=None, ip=None, port=':5555', log_path=None):
 55         ''' connect androide device.
 56 
 57         '''
 58         if log_path is not None:
 59             self._log_path = log_path
 60         self._ip = ip + port
 61         self._serial = serial
 62         self._adb = f'adb -s {self._ip if self._ip is not None else self._serial} '
 63         self.connect()
 64 
 65     def is_connected(self):
 66         rmsg = self._run_command(f'{self._adb}shell pwd', timeout=10)
 67         if '/' in rmsg:
 68             log_info(f'The device can be used normally!')
 69             return True
 70         else:
 71             return False
 72 
 73     def connect(self):
 74         if self._ip is not None:
 75             self._run_command('adb connect ' + self._ip)
 76             time.sleep(2)
 77             self._d = u2.connect(self._ip)
 78         elif self._serial is not None:
 79             self._d = u2.connect(self._serial)
 80         else:
 81             raise Exception('No device IP or serial number was received!')
 82         return self.is_connected()
 83 
 84     def disconnect(self):
 85         if self._ip is not None:
 86             self._run_command('adb disconnect ' + self._ip)
 87         elif self._serial is not None:
 88             pass
 89         else:
 90             raise Exception('No device IP or serial number was received!')
 91         # return (not self.is_connected())
 92         return None
 93 
 94     def rerun_uiautomator(func):
 95         def wrapper(self, **kwargs):
 96             try:
 97                 if self._d is None:
 98                     raise Exception('No u2 object was created!')
 99                 return func(self, **kwargs)
100             except Exception:
101                 try:
102                     os.system(f'python3 -m uiautomator2 init {self._serial if self._serial is not None else self._ip}')
103                 except Exception:
104                     os.system(f'python -m uiautomator2 init {self._serial if self._serial is not None else self._ip}')
105                 self._d.uiautomator.stop()
106                 log_info('Stopping uiautomator2!')
107                 time.sleep(3)
108                 self._d.uiautomator.start()
109                 log_info('Starting uiautomator2!')
110                 time.sleep(6)
111                 try:
112                     return func(self, **kwargs)
113                 except Exception as e:
114                     raise Exception(e)
115         return wrapper
116 
117     @rerun_uiautomator
118     def scroll(self, **kwargs):
119         '''
120         :param scroll_type: vertical or horizontal
121         :param direction: toBeginning or toEnd or forward or to or backward
122         :param index: The first few scrollbars
123         :param steps: The step size of each roll
124         :param for example resourceId='xxxx' multiple parameters can be passed
125         :type scroll_type: str
126         :type direction: str
127         :type index: int
128         :type steps: int, float
129         '''
130         scroll_type = kwargs.pop('scroll_type', 'vertical')
131         direction = kwargs.pop('direction', 'toBeginning')
132         index = kwargs.pop('index', 0)
133         steps = kwargs.pop('steps', 20)
134         try:
135             scroll_obj = self._d(scrollable=True)
136             if not len(scroll_obj) or index > len(scroll_obj) - 1:
137                 raise Exception("", "Scrollbar is missing or out of index, please check before calling")
138             log_info("===scrollbar count:{}====".format(len(scroll_obj)))
139             if scroll_type == "vertical":
140                 if not direction or direction == "forward":
141                     scroll_obj[index].scroll(steps=steps)
142                 if direction == 'to':
143                     if kwargs != {}:
144                         scroll_obj[index].scroll.to(**kwargs)
145                         log_info(f'Successfully vertical to {kwargs}')
146                     else:
147                         raise Exception('The specified location was not passed in!')
148                 if direction == "backward":
149                     scroll_obj[index].scroll.vert.backward()
150                     log_info('Successfully vertical backward')
151                 if direction == "toEnd":
152                     scroll_obj[index].scroll.toEnd()
153                     log_info('Successfully vertical toEnd')
154                 if direction == "toBeginning":
155                     scroll_obj[index].scroll.toBeginning()
156                     log_info('Successfully vertical toBeginning')
157             elif scroll_type == "horizontal":
158                 if not direction or direction == "forward":
159                     scroll_obj[index].scroll.horiz.forward()
160                     log_info('Successfully horizontal forward')
161                 if direction == 'to':
162                     if kwargs != {}:
163                         scroll_obj[index].scroll.horiz.to(**kwargs)
164                         log_info(f'Successfully horizontal to {kwargs}')
165                     else:
166                         raise Exception('The specified location was not passed in!')
167                 if direction == "toEnd":
168                     scroll_obj[index].scroll.horiz.toEnd()
169                     log_info(f'Successfully horizontal toEnd')
170                 if direction == "toBeginning":
171                     scroll_obj[index].scroll.horiz.toBeginning()
172                     log_info(f'Successfully horizontal toBeginning')
173         except Exception:
174             log_error(traceback.format_exc())
175             raise
176 
177     @console_log
178     def run_adb_command(self, func, return_output=True, timeout=30, **kwargs):
179         '''
180         Please pay attention to the case of func yourself
181         '''
182         if func in AndroidUiDevice().__dir__():
183             if func == 'device_info':
184                 out = eval(f'self.{func}()')
185             else:
186                 out = eval(f'self.{func}(**kwargs)')
187         else:
188             out = super(AndroidUiDevice, self)._run_command(self._adb + func, timeout=timeout)
189         return out if return_output is True else None
190 
191     @console_log
192     def poweroff(self):
193         out = self.run_adb_command("reboot -p")
194         return out
195 
196     @rerun_uiautomator
197     def device_info(self):
198         return self._d.device_info
199 
200     @rerun_uiautomator
201     def click(self, **kwargs):
202         '''
203         If you're going to use xpath
204             :param xpath: xpath statement
205             :param timeout: Timeout period
206         If you want to use elements
207             :param for example resourceId='xxxx' multiple parameters can be passed
208             :param timeout: Wait for the timeout period
209             :param index: 
210         If you want to use coordinates
211             :param x: The x-coordinate that needs to be clicked
212             :param y: The y-coordinate that needs to be clicked
213         :type xpath: str
214         :type timeout: int, float
215         :type x: int, float
216         :type y: int, float
217         '''
218         timeout = kwargs.pop('timeout', 0.5)
219         if 'xpath' in kwargs:
220             try:
221                 self._d.xpath(kwargs.get('xpath')).click(timeout=timeout)
222                 log_info(f'Successfully click {kwargs.get("xpath")}')
223             except Exception:
224                 raise Exception(f'Failed click {kwargs.get("xpath")}')
225         elif 'x' in kwargs and 'y' in kwargs:
226             try:
227                 self._d.click(**kwargs)
228                 log_info(f'Successfully Click Coordinates {kwargs.get("x")} x {kwargs.get("y")}')
229             except Exception:
230                 raise Exception(f'The coordinates are not clicked {kwargs.get("x")} x {kwargs.get("y")}')
231         else:
232             if len(self._d(**kwargs)) == 0:
233                 raise Exception(f'No elements found, {kwargs}')
234             self._d(**kwargs).click(timeout=timeout)
235             log_info(f'Successfully click {kwargs}')
236 
237     @rerun_uiautomator
238     def long_click(self, **kwargs):
239         '''
240         If you're going to use xpath
241             :param xpath: str
242             :param timeout: seconds wait element show up
243             :param duration: seconds of pressed
244         If you want to use elements
245             :param for example resourceId='xxxx' multiple parameters can be passed
246             :param timeout: seconds wait element show up
247             :param duration: seconds of pressed
248         If you want to use coordinates
249             :param x: The x-coordinate that needs to be clicked
250             :param y: The y-coordinate that needs to be clicked 
251             :param duration: seconds of pressed
252         :type xpath: str
253         :type timeout: int, float
254         :type duration: int, float
255         :type x: int, float
256         :type y: int, float
257         '''
258         duration = kwargs.pop('duration', 0.5)
259         timeout = kwargs.pop('timeout', 0.5)
260         if 'xpath' in kwargs:
261             try:
262                 self._d.xpath(kwargs.get('xpath')).long_click(duration=duration, timeout=timeout)
263                 log_info(f'Successfully long click {kwargs.get("xpath")}')
264             except Exception:
265                 raise Exception(f'Failed long click {kwargs.get("xpath")}')
266         elif 'x' in kwargs and 'y' in kwargs:
267             try:
268                 self._d.long_click(**kwargs, duration=duration)
269                 log_info(f'Successfully long click coordinates {kwargs.get("x")} x {kwargs.get("y")}')
270             except Exception:
271                 raise Exception(f'The coordinates are not long clicked {kwargs.get("x")} x {kwargs.get("y")}')
272         else:
273             if len(self._d(**kwargs)) == 0:
274                 raise Exception(f'No elements found, {kwargs}')
275             self._d(**kwargs).long_click(duration=duration, timeout=timeout)
276             log_info(f'Successfully long click {kwargs}')
277 
278     @rerun_uiautomator
279     def double_click(self, **kwargs):
280         '''
281         :param x: The x-coordinate that needs to be clicked
282         :param y: The y-coordinate that needs to be clicked
283         :param duration: The interval between double-clicks
284         :type x: int, float
285         :type y: int, float
286         :type duration: int, float
287         '''
288         duration = kwargs.pop('duration', 0.1)
289         try:
290             self._d.double_click(**kwargs,  duration=duration)
291             log_info(f'Successfully double click {kwargs.get("x")} x {kwargs.get("y")}')
292         except Exception:
293             raise Exception(f'Failed double click {kwargs.get("x")} x {kwargs.get("y")}')
294 
295     @rerun_uiautomator
296     def drag(self, **kwargs):
297         '''
298         :param sx: original x-coordinates
299         :param sy: original y-coordinates
300         :param ex: destination x-coordinates
301         :param ey: destination y-coordinates
302         :param duration: The speed at which the drag
303         :type sx: int, float
304         :type sy: int, float
305         :type ex: int, float
306         :type ey: int, float
307         :type duration: int, float
308         '''
309         duration = kwargs.pop('duration', 0.5)
310         try:
311             self._d.drag(**kwargs, duration=duration)
312             log_info(f'Successfully drag {kwargs.get("sx")} x {kwargs.get("sy")} to {kwargs.get("ex")} x {kwargs.get("ey")}')
313         except Exception:
314             raise Exception(f'failed drag {kwargs.get("sx")} x {kwargs.get("sy")} to {kwargs.get("ex")} x {kwargs.get("ey")}')
315 
316     @rerun_uiautomator
317     def drag_to(self, **kwargs):
318         '''
319         If you're going to use xpath
320             :param xpath: xpath statement
321             :param ex: destination x-coordinates
322             :param ey: destination y-coordinates
323             :param duration: The speed at which the drag
324         If you want to use elements
325             :param for example resourceId='xxxx' multiple parameters can be passed
326             :param ex: destination x-coordinates
327             :param ey: destination y-coordinates
328             :param duration: The speed at which the drag
329         :type xpath: str
330         :type ex: int, float
331         :type ey: int, float
332         :type duration: int, float
333         '''
334         ex = kwargs.pop('ex')
335         ey = kwargs.pop('ey')
336         duration = kwargs.pop('duration', 0.5)
337         if 'xpath' in kwargs:
338             try:
339                 self._d.xpath(**kwargs).drag_to(ex, ey, duration)
340                 log_info(f'Successfully drag {kwargs} to {ex} x {ey}')
341             except Exception:
342                 raise Exception(f'failed drag {kwargs} to {ex} x {ey}')
343         else:
344             if len(self._d(**kwargs)) == 0:
345                 raise Exception(f'No elements found, {kwargs}')
346             self._d(**kwargs).drag_to(ex, ey, duration)
347             log_info(f'Successfully drag {kwargs} to {ex} x {ey}')
348 
349     @rerun_uiautomator
350     def swipe(self, **kwargs):
351         '''
352         If you're going to use xpath
353             :param xpath: xpath statement
354             :param direction: one of ("left", "right", "up", "down")
355             :param steps: move steps, one step is about 5ms
356         If you want to use elements
357             :param for example resourceId='xxxx' multiple parameters can be passed
358             :param direction: one of ("left", "right", "up", "down")
359             :param steps: move steps, one step is about 5ms
360         If you want to use coordinates
361             :param fx: original x-coordinates
362             :param fy: original y-coordinates
363             :param tx: destination x-coordinates
364             :param ty: destination y-coordinates
365             :param duration: duration
366             :param steps: 1 steps is about 5ms, if set, duration will be ignore
367         :type xpath: str
368         :type direction: str, float
369         :type steps: int, float
370         :type fx: int, float
371         :type fy: int, float
372         :type tx: int, float
373         :type ty: int, float
374         :type duration: int, float
375         '''
376         direction = kwargs.pop('direction', None)
377         steps = kwargs.pop('steps', None)
378         duration = kwargs.pop('duration', None)
379         if 'xpath' in kwargs:
380             try:
381                 self._d.xpath(kwargs.get('xpath')).swipe(direction=direction, steps=steps)
382                 log_info(f'Successfully swipe {kwargs.get("xpath")} to {direction}')
383             except Exception:
384                 raise Exception(f'Failed swipe {kwargs.get("xpath")}')
385         elif 'fx' and 'fy' and 'tx' and 'ty' in kwargs:
386             try:
387                 self._d.swipe(**kwargs, duration=duration, steps=steps)
388                 log_info(f'Successfully swipe {kwargs.get("fx")} x {kwargs.get("fy")} to {kwargs.get("tx")} x {kwargs.get("ty")}')
389             except Exception:
390                 raise Exception(f'Failed swipe {kwargs.get("fx")} x {kwargs.get("fy")} to {kwargs.get("tx")} x {kwargs.get("ty")}')
391         else:
392             if len(self._d(**kwargs)) == 0:
393                 raise Exception(f'No elements found, {kwargs}')
394             self._d(**kwargs).swipe(direction=direction, steps=steps)
395             log_info(f'Successfully swipe to {direction}')
396 
397     @rerun_uiautomator
398     def screenshot(self, **kwargs):
399         '''
400         :param filename: The name of the screenshot file
401         :param displayid: Screen ID
402         :param log_path: log file path
403         :type filename: str
404         :type displayid: str
405         :type log_path: str
406         '''
407         self._take_screenshot(**kwargs)
408 
409     @rerun_uiautomator
410     def press(self, **kwargs):
411         '''
412         :param key: press key via name or key code.
413         :type key: int, str
414         '''
415         try:
416             self._d.press(**kwargs)
417             log_info(f'Successfully press {kwargs}')
418         except Exception:
419             raise Exception(f'Failed press {kwargs}')
420 
421     @rerun_uiautomator
422     def send_keys(self, **kwargs):
423         '''
424         If you're going to use xpath:
425             :param text: the text entered
426             :param xpath: xpath statement
427         If you want to use elements
428             :param for example resourceId='xxxx' multiple parameters can be passed
429             :param text: the text entered
430         :type text: str
431         :type xpath: str
432         '''
433         text = kwargs.pop('text', '')
434         if 'xpath' in kwargs:
435             self._d.xpath(kwargs.get('xpath')).send_keys(text=text)
436             if text == self.get_text(xpath=kwargs.get('xpath')):
437                 log_info(f'Successfully to write text: {text} for {self._d.xpath(kwargs.get("xpath"))}')
438             else:
439                 raise Exception(f'Failed to write text: {text} for {self._d.xpath(kwargs.get("xpath"))}')
440         else:
441             self._d(**kwargs).send_keys(text=text)
442             if text == self.get_text(**kwargs):
443                 log_info(f'Successfully to write text: {text} for {kwargs}')
444             else:
445                 raise Exception(f'Failed to write text: {text} for {kwargs}')
446 
447     @rerun_uiautomator
448     def info(self):
449         return self._d.info
450 
451     @rerun_uiautomator
452     def center(self, **kwargs):
453         '''
454         If you're going to use xpath:
455             :param xpath: xpath statement
456         If you want to use elements
457             :param for example resourceId='xxxx' multiple parameters can be passed
458         :type xpath: str
459         '''
460         if 'xpath' in kwargs:
461             try:
462                 out = self._d.xpath(kwargs.get('xpath')).center()
463                 log_info(f'The center point is {out}')
464             except:
465                 raise Exception('The center was not found!')
466         else:
467             try:
468                 out = self._d(**kwargs).center()
469                 log_info(f'The center point is {out}')
470             except Exception:
471                 raise Exception('The center was not found!')
472         return out
473 
474     @rerun_uiautomator
475     def bounds(self, **kwargs):
476         '''
477         If you're going to use xpath:
478             :param xpath: xpath statement
479         If you want to use elements
480             :param for example resourceId='xxxx' multiple parameters can be passed
481         :type xpath: str
482         '''
483         if 'xpath' in kwargs:
484             try:
485                 out = self._d.xpath(kwargs.get('xpath')).bounds()
486                 log_info(f'The bounds point is {out}')
487             except:
488                 raise Exception('The bounds was not found!')
489         else:
490             try:
491                 out = self._d(**kwargs).bounds()
492                 log_info(f'The bounds point is {out}')
493             except Exception:
494                 raise Exception('The bounds was not found!')
495         return out
496 
497     @rerun_uiautomator
498     def get_text(self, **kwargs):
499         '''
500         If you're going to use xpath:
501             :param xpath: xpath statement
502         If you want to use elements
503             :param for example resourceId='xxxx' multiple parameters can be passed
504         :type xpath: str
505         '''
506         if 'xpath' in kwargs:
507             try:
508                 out = self._d.xpath(kwargs.get('xpath')).get_text()
509                 log_info(f'The text is {out}')
510             except Exception:
511                 raise Exception('Text not obtained')
512         else:
513             try:
514                 out = self._d(**kwargs).get_text()
515                 log_info(f'The text is {out}')
516             except Exception:
517                 raise Exception('Text not obtained')
518         return out
519 
520     @rerun_uiautomator
521     def wait_gone(self, **kwargs):
522         '''
523         If you're going to use xpath:
524             :param xpath: xpath statement
525             :param timeout: wait for the element timeout
526         If you want to use elements
527             :param for example resourceId='xxxx' multiple parameters can be passed
528             :param timeout: wait for the element timeout
529         :type xpath: str
530         :type timeout: float, int
531         '''
532         timeout = kwargs.pop('timeout', 3)
533         if 'xpath' in kwargs:
534             try:
535                 self._d.xpath(kwargs.get('xpath')).wait_gone(timeout=timeout)
536                 log_info(f'Successfully wait gone {self._d.xpath(kwargs.get("xpath"))}')
537             except Exception:
538                 raise Exception(f'Failed wait gone {self._d.xpath(kwargs.get("xpath"))}')
539         else:
540             if len(self._d(**kwargs)) == 0:
541                 raise Exception(f'No elements found, {kwargs}')
542             self._d(**kwargs).wait_gone(timeout=timeout)
543             log_info(f'Successfully wait gone {kwargs}')
544 
545     @rerun_uiautomator
546     def wait(self, **kwargs):
547         '''
548         If you're going to use xpath:
549             :param xpath: xpath statement
550             :param timeout: wait for the element timeout
551         If you want to use elements
552             :param for example resourceId='xxxx' multiple parameters can be passed
553             :param timeout: wait for the element timeout
554         :type xpath: str
555         :type timeout: float, int
556         '''
557         timeout = kwargs.pop('timeout', 3)
558         if 'xpath' in kwargs:
559             try:
560                 self._d.xpath(kwargs.get('xpath')).wait(timeout=timeout)
561                 log_info(f'Successfully wait {self._d.xpath(kwargs.get("xpath"))}')
562             except Exception:
563                 raise Exception(f'Failed wait {self._d.xpath(kwargs.get("xpath"))}')
564         else:
565             if len(self._d(**kwargs)) == 0:
566                 raise Exception(f'No elements found, {kwargs}')
567             self._d(**kwargs).wait(timeout=timeout)
568             log_info(f'Successfully wait {kwargs}')
569 
570     @rerun_uiautomator
571     def exists(self, **kwargs):
572         '''
573         If you're going to use xpath:
574             :param xpath: xpath statement
575             :param timeout: wait for the element timeout
576         If you want to use elements
577             :param for example resourceId='xxxx' multiple parameters can be passed
578             :param timeout: wait for the element timeout
579         :type xpath: str
580         :type timeout: float, int
581         '''
582         timeout = kwargs.pop('timeout', 3)
583         if 'xpath' in kwargs:
584             try:
585                 self._d.xpath(kwargs.get('xpath')).exists(timeout=timeout)
586                 log_info(f'Successfully exists {self._d.xpath(kwargs.get("xpath"))}')
587             except Exception:
588                 raise Exception(f'Failed exists {self._d.xpath(kwargs.get("xpath"))}')
589         else:
590             if len(self._d(**kwargs)) == 0:
591                 raise Exception(f'No elements found, {kwargs}')
592             self._d(**kwargs).exists(timeout=timeout)
593             log_info(f'Successfully exists {kwargs}')
594 
595     @rerun_uiautomator
596     def app_start(self, **kwargs):
597         '''
598         :param package_name: The name of the package that launches the app
599         :param activity: The name of the activity that launches the app
600         :param wait: wait until app started. default False
601         :param stop: Stop app before starting the activity. (require activity)
602         :param use_monkey: use monkey command to start app when activity is not given
603         :type package_name: str
604         :type activity: str
605         :type wait: bool
606         :type stop: bool
607         :type use_monkey: bool
608         '''
609         self._d.app_start(**kwargs)
610         data = self.app_current()
611         if not kwargs.get('activity'):
612             if data.get('package') == kwargs.get('package_name'):
613                 log_info(f'The app was successfully launched: {kwargs.get("package_name")}')
614             else:
615                 raise Exception(f'The app was failed launched: {kwargs.get("package_name")}')
616         else:
617             if data.get('package') == kwargs.get('package_name') and data.get('activity') == kwargs.get('activity'):
618                 log_info(f'The app was successfully launched: {kwargs.get("package_name") + "/" + kwargs.get("activity")}')
619             else:
620                 raise Exception(f'The app was failed launched: {kwargs.get("package_name") + "/" + kwargs.get("activity")}')
621 
622     @rerun_uiautomator
623     def app_stop(self, **kwargs):
624         '''
625         :param package_name: The name of the package that stops the app
626         :type package_name: str
627         '''
628         self._d.app_stop(**kwargs)
629         data = self.app_current()
630         if data.get('package') != kwargs.get('package_name'):
631             log_info(f'The app: {kwargs.get("package_name")} was stopped successfully!')
632         else:
633             raise Exception(f'The app: {kwargs.get("package_name")} was stopped failed!')
634 
635     @rerun_uiautomator
636     def app_current(self):
637         return self._d.app_current()
638 
639     def clickBy(self, **kwargs):
640         self.click(**kwargs)
641 
642     def pressBack(self):
643         self.press(key='back')
644 
645     def pressHome(self):
646         self.press(key='home')
647 
648     def pressEnter(self):
649         self.press(key='enter')
650 
651     def pressDpadUp(self):
652         self.press(key='up')
653 
654     def pressDpadDown(self):
655         self.press(key='down')
656 
657     def pressDpadLeft(self):
658         self.press(key='left')
659 
660     def pressDpadRight(self):
661         self.press(key='right')
662 
663     def pressDpadCenter(self):
664         self.press(key='center')
665 
666     def pressMenu(self):
667         self.press(key='menu')
668 
669     def pressSearch(self):
670         self.press(key='search')
671 
672     def longClickBy(self, **kwargs):
673         self.long_click(**kwargs)
674 
675     def existBy(self, **kwargs):
676         self.exists(**kwargs)
677 
678     def getTextBy(self, **kwargs):
679         self.get_text(**kwargs)
680 
681     def _get_mixin_classes(self, version):
682         android_version = None
683         platform = None
684         if version:
685             if version.count('_') == 0:
686                 android_version = self._version
687             elif version.count('_') == 1:
688                 platform = self._version.split('_')[0]
689                 android_version = self._versin.split('_')[1]
690             else:
691                 raise Exception('unsupported android device version: {}, only support [PLATFORM]_[ANDROID VERSION]'.format(self._version))
692         if android_version and android_version.isdigit():
693             android_version = int(android_version)
694         elif android_version and (android_version.replace('.','',1).isdigit() and android_version.count('.') < 2):
695             android_version = float(android_version)
696         elif android_version:
697             raise Exception('unsupported android version: '+ self._version)
698         # log_info('android_version '+str(android_version))
699         # log_info('platform '+ str(platform))
700         post_mixin_package = None
701 
702         def get_platform_mixin_cls(base_package, platform, module, class_name):
703             if platform:
704                 m = '.'.join([base_package, platform, module])
705             else:
706                 m = '.'.join([base_package, module])
707             # log_info(m)
708             try:
709                 mod = importlib.import_module(m)
710                 cls = getattr(mod, class_name)
711                 return cls
712             except:
713                 return None
714 
715         mixin_class_list = []
716         for mixin_info in ANDROID_MIXIN_BASE_LIST:
717             m = mixin_info[0]
718             c = mixin_info[1]
719             cls = None
720             if android_version:
721                 start = 0
722                 for i in range(len(ANDROID_VERSION_LIST)):
723                     if android_version < ANDROID_VERSION_LIST[i]:
724                         start = i + 1
725                     else:
726                         break
727                 if start >= len(ANDROID_VERSION_LIST):
728                     cls = get_platform_mixin_cls('android', platform, m, c)
729                 else:
730                     for i in range(start, len(ANDROID_VERSION_LIST)):
731                         base_package = 'android.'+str(ANDROID_VERSION_LIST[i]).replace('.', '_')
732                         cls = get_platform_mixin_cls(base_package, platform, m, c)
733                         if cls:
734                             break
735                         else:
736                             continue
737             else:
738                 # log_info('no android version')
739                 base_package = 'android'
740                 cls = get_platform_mixin_cls(base_package, platform, m, c)
741             
742             if not cls:
743                 log_warn('failed to import mixin class: {} in {}'.format(c, 'LinuxDevice'))
744             else:
745                 mixin_class_list.append(cls)
746                 # log_info(cls)
747 
748         return mixin_class_list
android_ui_devices

 uiautomar2 的使用

参考:https://blog.csdn.net/Xsk215/article/details/131871938

adb shell input keyevent 命令用于模拟物理按键的输入事件,其参数是按键的键码(keycode)。键码是一个整数值,代表不同的按键,具体的键码可以在 Android 官方文档中找到
 参考文档:https://www.cnblogs.com/lethe1203/p/18114698
 1 import uiautomator2 as u2
 2 
 3 d = u2.connect('10.239.81.47')
 4 print(d.info)
 5 d(resourceId="android:id/edit").send_keys('123')
 6 x1,y2 = d.xpath('//*[@resource-id="com.android.systemui:id/grid_nav"]').center()
 7 d.double_click(x1, y2)
 8 d.xpath('//*[@resource-id="com.android.car.carlauncher:id/apps_grid"]/android.widget.LinearLayout[11]/android.widget.ImageView[1]').click()
 9 d.xpath('//*[@resource-id="com.android.car.settings:id/top_level_recycler_view"]/androidx.recyclerview.widget.RecyclerView[1]/android.widget.RelativeLayout[13]/android.widget.LinearLayout[1]').click()
10 
11 
12 d(resourceId="android:id/title", text="About").click()
13 data = d(resourceId="android:id/title", text="IP address").get_text()
14 print(data)
15 data2 = d(resourceId="android:id/summary", text="10.239.81.47").get_text()
16 print(data2)
ui 点击,获取,输入案例

 

1. adb devices:查看当前连接的设备列表。

 2. adb shell:进入模拟器或设备的shell 模式。可以在里面执行Linux 命令。

 3. adb push < 源文件 > < 目标文件 > :将文件拷贝到模拟器或设备中。

 4. adb pull < 源文件 > < 目标文件 > : 从模拟器或设备中将文件拷回电脑中。

 5. adb install <apk 文件> 安装 apk 应用到设备上。

 6. adb uninstall < 应用包名称 > :从设备中卸载应用。

 7. adb logcat  :查看 LogCat 的日志。

 8. adb start-server:启动 Adb server 服务,用于与设备连接。

 9. adb kill-server:终止 Adb server 服务。

 10. adb reboot:重启模拟器或设备。

 11. adb root:重新启动Adb 为Root 权限。

 12. adb remount:重新挂载系统,允许写入更改到系统分区。

 13. adb backup :备份设备数据。

 14. adb restore:恢复之前备份的设备数据。

 15. adb help:查看Adb 命令的使用说明。

 16. adb shell pm list packages:列出当前正在运行的应用的包名

称。

17. adb shell pm path <应用包名称>:查看特定应用的包路径。

18. adb shell am start <应用包名称>:启动特定应用。

19. adb shell pm clear <应用包名称>:清除特定应用的缓存数据。

20. adb shell input text <文本>:向当前活动窗口输入文本

posted on 2024-01-23 16:02  没有如果,只看将来  阅读(7)  评论(0编辑  收藏  举报