def airtest_init(self, serialno=None): if self.airtest: self.airtest_deinit() if serialno is None: adb_list, index = self.get_devices() if len(adb_list) > 0: serialno = adb_list[index] else: logger.error('No devices available!') return logger.info('启动 airtest ,尝试 adb 连接...') logger.info(f'ADB connect {serialno}') try: self.airtest = Android(serialno, cap_method=CAP_METHOD.JAVACAP, ori_method=ORI_METHOD.ADB, touch_method=TOUCH_METHOD.MAXTOUCH) except: self.serialno = None self.airtest = None raise self.serialno = serialno self.render = [ round(i) for i in self.airtest.get_render_resolution(True) ] if self.render[2] * 9 > self.render[3] * 16: self.scale, self.border = (1080 / self.render[3], ( round(self.render[2] - self.render[3] * 16 / 9) >> 1, 0)) else: self.scale, self.border = (1920 / self.render[2], ( 0, round(self.render[3] - self.render[2] * 9 / 16) >> 1)) self.airtest.maxtouch.install_and_setup() # 载入点击信息 self.click_map = { i: [ round(i.value[j] / self.scale + self.border[j] + self.render[j]) for j in range(2) ] for i in Click } # 载入图片信息 self.image_map = { i: [cv2.imread(i.value[0]), i.value[1:]] for i in Image }
class AirDevice: """ 安卓相关获取的命令 """ def __init__(self): self.android = Android() self.adb = self.android.adb @property def screen(self): """获取屏幕宽高""" info = self.android.display_info return info.get('width'), info.get('height') @property def device_id(self): """当前设备ID""" return self.android.uuid @property def get_top_activity(self): """获取顶级活动""" return self.android.get_top_activity() @property def get_default_ime(self): """获取默认的输入法""" return self.adb.shell( "settings get secure default_input_method").strip() @property def get_ipv4(self): """[summary] 获取手机的IP地址 """ return self.android.get_ip_address() def close_yosemite_ime(self, ime): """关闭airtest输入法""" self.adb.shell("ime disable %s" % YOSEMITE_IME_SERVICE) self.adb.shell("ime set %s" % ime)
def pmgrant(self, package): pmg = Android(serialno="AUY9WSEAD6DIHM95", touch_method="ADBTOUCH") pmg.shell( 'pm grant {0} android.permission.READ_EXTERNAL_STORAGE'.format( package)) pmg.shell( 'pm grant {0} android.permission.WRITE_EXTERNAL_STORAGE'.format( package))
def setUpClass(self): self.android = Android()
class TestAndroid(unittest.TestCase): @classmethod def setUpClass(self): self.android = Android() @classmethod def tearDownClass(self): try_remove('screen.mp4') def _install_test_app(self): if PKG not in self.android.list_app(): self.android.install_app(APK) def test_serialno(self): self.assertIsNotNone(self.android.serialno) def test_adb(self): self.assertIsInstance(self.android.adb, ADB) def test_display_info(self): self.assertIs(self.android.display_info, self.android.adb.display_info) self.assertIn("width", self.android.display_info) self.assertIn("height", self.android.display_info) self.assertIn("orientation", self.android.display_info) self.assertIn("rotation", self.android.display_info) def test_minicap(self): minicap = self.android.minicap self.assertIsInstance(minicap, Minicap) self.assertIs(minicap.adb.display_info, self.android.display_info) def test_minitouch(self): self.assertIsInstance(self.android.minitouch, Minitouch) def test_list_app(self): self._install_test_app() self.assertIn(PKG, self.android.list_app()) self.assertIn(PKG, self.android.list_app(third_only=True)) def test_path_app(self): self._install_test_app() app_path = self.android.path_app(PKG) self.assertIn(PKG, app_path) self.assertTrue(app_path.startswith("/")) with self.assertRaises(AirtestError): self.android.path_app('com.netease.this.is.error') def test_check_app(self): self._install_test_app() self.assertTrue(self.android.check_app(PKG)) with self.assertRaises(AirtestError): self.android.check_app('com.netease.this.is.error') def test_snapshot(self): self._install_test_app() for i in (CAP_METHOD.ADBCAP, CAP_METHOD.MINICAP, CAP_METHOD.JAVACAP): filename = "./screen.png" if os.path.exists(filename): os.remove(filename) self.android.cap_method = i self.android.wake() screen = self.android.snapshot(filename=filename) self.assertIsInstance(screen, numpy.ndarray) self.assertTrue(os.path.exists(filename)) os.remove(filename) def test_snapshot_thread(self): def assert_exists_and_remove(filename): self.assertTrue(os.path.exists(filename)) os.remove(filename) class ScreenshotThread(Thread): def __init__(self, dev, assert_true): self.dev = dev self._running = True self.assert_true = assert_true super(ScreenshotThread, self).__init__() self.dev.snapshot("screen_thread.jpg") assert_exists_and_remove("screen_thread.jpg") def terminate(self): self._running = False def run(self): while self._running: filename = "screen_thread.jpg" self.dev.snapshot(filename) assert_exists_and_remove(filename) time.sleep(2) task = ScreenshotThread(self.android, self.assertTrue) task.daemon = True task.start() for i in range(10): self.android.snapshot("screen.jpg") assert_exists_and_remove("screen.jpg") time.sleep(2) task.terminate() def test_shell(self): self.assertEqual(self.android.shell('echo nimei').strip(), 'nimei') def test_keyevent(self): self.android.keyevent("BACK") def test_wake(self): self.android.wake() def test_screenon(self): self.assertIn(self.android.is_screenon(), (True, False)) def test_home(self): self.android.home() def test_text(self): self.android.ime_method = IME_METHOD.ADBIME self.android.text('test text') self.android.ime_method = IME_METHOD.YOSEMITEIME self.android.text(u'你好') def test_touch(self): for i in (TOUCH_METHOD.ADBTOUCH, TOUCH_METHOD.MINITOUCH, TOUCH_METHOD.MAXTOUCH): self.android.touch_method = i self.android.touch((100, 100)) def test_swipe(self): for i in (TOUCH_METHOD.ADBTOUCH, TOUCH_METHOD.MINITOUCH, TOUCH_METHOD.MAXTOUCH): self.android.touch_method = i self.android.swipe((100, 100), (300, 300)) self.android.swipe((100, 100), (300, 300), fingers=1) self.android.swipe((100, 100), (300, 300), fingers=2) self.android.touch_method = TOUCH_METHOD.ADBTOUCH self.android.swipe((100, 100), (300, 300), fingers=3) self.android.touch_method = TOUCH_METHOD.MINITOUCH with self.assertRaises(Exception): self.android.swipe((100, 100), (300, 300), fingers=3) def test_recording(self): if self.android.sdk_version >= 19: filepath = "screen.mp4" if os.path.exists(filepath): os.remove(filepath) self.android.start_recording(max_time=30, bit_rate=500000) time.sleep(10) self.android.stop_recording() self.assertTrue(os.path.exists("screen.mp4")) time.sleep(2) # Record the screen with the lower quality os.remove(filepath) self.android.start_recording(bit_rate_level=1) time.sleep(10) self.android.stop_recording() self.assertTrue(os.path.exists("screen.mp4")) os.remove(filepath) time.sleep(2) self.android.start_recording(bit_rate_level=0.5) time.sleep(10) self.android.stop_recording() self.assertTrue(os.path.exists("screen.mp4")) def test_start_recording_error(self): if self.android.sdk_version >= 19: with self.assertRaises(AirtestError): self.android.start_recording(max_time=30) time.sleep(3) self.android.start_recording(max_time=30) self.android.stop_recording() def test_stop_recording_error(self): with self.assertRaises(AirtestError): self.android.stop_recording() def test_interrupt_recording(self): filepath = "screen.mp4" if os.path.exists(filepath): os.remove(filepath) self.android.start_recording(max_time=30) time.sleep(3) self.android.stop_recording(is_interrupted=True) self.assertFalse(os.path.exists(filepath)) def test_get_top_activity(self): self._install_test_app() self.android.start_app(PKG) pkg, activity, pid = self.android.get_top_activity() self.assertEqual(pkg, PKG) self.assertEqual(activity, 'org.cocos2dx.javascript.AppActivity') self.assertIsInstance(int(pid), int) def test_is_keyboard_shown(self): self.android.is_keyboard_shown() def test_is_locked(self): self.android.is_locked() def test_unlock(self): self.android.unlock() def test_pinch(self): for i in (TOUCH_METHOD.MINITOUCH, TOUCH_METHOD.MAXTOUCH): self.android.touch_method = i self.android.pinch(in_or_out='in') self.android.pinch(in_or_out='out') self.android.touch_method = TOUCH_METHOD.ADBTOUCH with self.assertRaises(Exception): self.android.pinch(in_or_out='in') def test_swipe_along(self): coordinates_list = [(100, 300), (300, 300), (100, 500), (300, 600)] for i in (TOUCH_METHOD.MINITOUCH, TOUCH_METHOD.MAXTOUCH): self.android.touch_method = i self.android.swipe_along(coordinates_list) self.android.swipe_along(coordinates_list, duration=3, steps=10) self.android.touch_method = TOUCH_METHOD.ADBTOUCH with self.assertRaises(Exception): self.android.swipe_along(coordinates_list) def test_two_finger_swipe(self): for i in (TOUCH_METHOD.MINITOUCH, TOUCH_METHOD.MAXTOUCH): self.android.touch_method = i self.android.two_finger_swipe((100, 100), (200, 200)) self.android.two_finger_swipe((100, 100), (200, 200), duration=3, steps=10) self.android.two_finger_swipe((100, 100), (200, 200), offset=(-20, 100)) self.android.two_finger_swipe((100, 100), (200, 200), offset=(-1000, 100)) self.android.touch_method = TOUCH_METHOD.ADBTOUCH with self.assertRaises(Exception): self.android.two_finger_swipe((100, 100), (200, 200))
def startPackage(self): android = Android() android.start_app('com.dashengzhangyou.pykf.lailaiguangdong') time.sleep(5)
class TestAndroid(unittest.TestCase): @classmethod def setUpClass(self): self.android = Android() @classmethod def tearDownClass(self): try_remove('screen.mp4') def _install_test_app(self): if PKG not in self.android.list_app(): self.android.install_app(APK) def test_serialno(self): self.assertIsNotNone(self.android.serialno) def test_adb(self): self.assertIsInstance(self.android.adb, ADB) def test_display_info(self): self.assertIs(self.android.display_info, self.android.adb.display_info) self.assertIn("width", self.android.display_info) self.assertIn("height", self.android.display_info) self.assertIn("orientation", self.android.display_info) self.assertIn("rotation", self.android.display_info) def test_minicap(self): minicap = self.android.minicap self.assertIsInstance(minicap, Minicap) self.assertIs(minicap.adb.display_info, self.android.display_info) def test_minitouch(self): self.assertIsInstance(self.android.minitouch, Minitouch) def test_list_app(self): self._install_test_app() self.assertIn(PKG, self.android.list_app()) self.assertIn(PKG, self.android.list_app(third_only=True)) def test_path_app(self): self._install_test_app() app_path = self.android.path_app(PKG) self.assertIn(PKG, app_path) self.assertTrue(app_path.startswith("/")) with self.assertRaises(AirtestError): self.android.path_app('com.netease.this.is.error') def test_check_app(self): self._install_test_app() self.assertTrue(self.android.check_app(PKG)) with self.assertRaises(AirtestError): self.android.check_app('com.netease.this.is.error') def test_snapshot(self): self._install_test_app() for i in (CAP_METHOD.ADBCAP, CAP_METHOD.MINICAP, CAP_METHOD.MINICAP_STREAM, CAP_METHOD.JAVACAP): filename = "./screen.png" if os.path.exists(filename): os.remove(filename) self.android.cap_method = i self.android.wake() screen = self.android.snapshot(filename=filename) self.assertIsInstance(screen, numpy.ndarray) self.assertTrue(os.path.exists(filename)) os.remove(filename) def test_shell(self): self.assertEqual(self.android.shell('echo nimei').strip(), 'nimei') def test_keyevent(self): self.android.keyevent("BACK") def test_wake(self): self.android.wake() def test_screenon(self): self.assertIn(self.android.is_screenon(), (True, False)) def test_home(self): self.android.home() def test_text(self): self.android.ime_method = IME_METHOD.ADBIME self.android.text('test text') self.android.ime_method = IME_METHOD.YOSEMITEIME self.android.text(u'你好') def test_touch(self): for i in (TOUCH_METHOD.ADBTOUCH, TOUCH_METHOD.MINITOUCH): self.android.touch_method = i self.android.touch((100, 100)) def test_swipe(self): for i in (TOUCH_METHOD.ADBTOUCH, TOUCH_METHOD.MINITOUCH): self.android.touch_method = i self.android.swipe((100, 100), (300, 300)) self.android.swipe((100, 100), (300, 300), fingers=1) self.android.swipe((100, 100), (300, 300), fingers=2) self.android.touch_method = TOUCH_METHOD.ADBTOUCH self.android.swipe((100, 100), (300, 300), fingers=3) self.android.touch_method = TOUCH_METHOD.MINITOUCH with self.assertRaises(Exception): self.android.swipe((100, 100), (300, 300), fingers=3) def test_recording(self): if self.android.sdk_version >= 19: filepath = "screen.mp4" if os.path.exists(filepath): os.remove(filepath) self.android.start_recording(max_time=30, bit_rate=500000, vertical=False) time.sleep(3) self.android.stop_recording() self.assertTrue(os.path.exists("screen.mp4")) def test_start_recording_error(self): if self.android.sdk_version >= 19: with self.assertRaises(AirtestError): self.android.start_recording(max_time=30) time.sleep(3) self.android.start_recording(max_time=30) self.android.stop_recording() def test_stop_recording_error(self): with self.assertRaises(AirtestError): self.android.stop_recording() def test_interrupt_recording(self): filepath = "screen.mp4" if os.path.exists(filepath): os.remove(filepath) self.android.start_recording(max_time=30) time.sleep(3) self.android.stop_recording(is_interrupted=True) self.assertFalse(os.path.exists(filepath)) def test_get_top_activity(self): self._install_test_app() self.android.start_app(PKG) pkg, activity, pid = self.android.get_top_activity() self.assertEqual(pkg, PKG) self.assertEqual(activity, 'org.cocos2dx.javascript.AppActivity') self.assertIsInstance(int(pid), int) def test_is_keyboard_shown(self): self.android.is_keyboard_shown() def test_is_locked(self): self.android.is_locked() def test_unlock(self): self.android.unlock() def test_pinch(self): self.android.pinch(in_or_out='in') self.android.pinch(in_or_out='out')
class Base(): def __init__(self, serialno=None): logger.debug("Base init") self.lock = threading.Lock() self.terminate_flag = False self.suspend_flag = False self.serialno = None self.airtest = None if serialno: self.airtest_init(serialno) def __del__(self): logger.debug("Base delete") del self.airtest def get_devices(self): try: adb_list = [i for i, j in ADB().devices() if j == 'device'] index = adb_list.index( self.serialno ) if self.serialno and self.serialno in adb_list else 0 return adb_list, index except: traceback.print_exc() logger.error('Get devices failed!') return [], 0 def airtest_init(self, serialno=None): if self.airtest: self.airtest_deinit() if serialno is None: adb_list, index = self.get_devices() if len(adb_list) > 0: serialno = adb_list[index] else: logger.error('No devices available!') return logger.info('启动 airtest ,尝试 adb 连接...') logger.info(f'ADB connect {serialno}') try: self.airtest = Android(serialno, cap_method=CAP_METHOD.JAVACAP, ori_method=ORI_METHOD.ADB, touch_method=TOUCH_METHOD.MAXTOUCH) except: self.serialno = None self.airtest = None raise self.serialno = serialno self.render = [ round(i) for i in self.airtest.get_render_resolution(True) ] if self.render[2] * 9 > self.render[3] * 16: self.scale, self.border = (1080 / self.render[3], ( round(self.render[2] - self.render[3] * 16 / 9) >> 1, 0)) else: self.scale, self.border = (1920 / self.render[2], ( 0, round(self.render[3] - self.render[2] * 9 / 16) >> 1)) self.airtest.maxtouch.install_and_setup() # 载入点击信息 self.click_map = { i: [ round(i.value[j] / self.scale + self.border[j] + self.render[j]) for j in range(2) ] for i in Click } # 载入图片信息 self.image_map = { i: [cv2.imread(i.value[0]), i.value[1:]] for i in Image } def airtest_deinit(self): del self.airtest self.airtest = None self.serialno = None def __airtest_restart(self): self.sleep(.1) traceback.print_exc() logger.info('尝试重新启动airtest...') self.airtest_init(self.serialno) def sleep(self, x, part=.1): timer = time.time() + x - part while True: while self.suspend_flag and not self.terminate_flag: time.sleep(.5) if self.terminate_flag: sys.exit(0) if time.time() >= timer: break time.sleep(part) time.sleep(max(0, timer + part - time.time())) def click_coordinate(self, pos): logger.debug(pos) with self.lock: while True: try: self.airtest.touch(pos) break except: self.__airtest_restart() continue def click(self, key, wait=500): logger.debug(key) self.click_coordinate(self.click_map[key]) self.sleep(wait * .001) def screen_shot(self, forwordLagency=.5, backwordLagency=.5): self.sleep(forwordLagency) while True: try: self.im = cv2.resize( self.airtest.snapshot()[self.render[1] + self.border[1]:self.render[1] + self.render[3] - self.border[1], self.render[0] + self.border[0]:self.render[0] + self.render[2] - self.border[0]], (1920, 1080), interpolation=cv2.INTER_CUBIC) self.sleep(backwordLagency) break except: self.__airtest_restart() continue return True def image_compare(self, img_key, click_flag=False): key_value = self.image_map[img_key] img = key_value[0] rect = key_value[1][0] threshold = .1 if len(key_value[1]) <= 1 else key_value[1][1] loc = cv2.minMaxLoc( cv2.matchTemplate(self.im[rect[1]:rect[3], rect[0]:rect[2]], img, cv2.TM_SQDIFF_NORMED)) value = loc[0] logger.debug(f'Compare {img_key}, {threshold > value}, value= {value}') if click_flag and threshold > value: self.click_coordinate((rect[0] + loc[2][0] + (img.shape[1] >> 1), rect[1] + loc[2][1] + (img.shape[0] >> 1))) return threshold > value def image_click(self, img_key): return self.image_compare(img_key, True) def image_wait(self, img, flag=True, wait=.5): while self.screen_shot(wait, .5): if self.image_compare(img) == flag: break
def out_screen(): if Android().is_screenon(): os.popen("adb shell input keyevent 26") # 点击电源灭屏 else: pass
def bright_screen(): if Android().is_screenon(): pass else: os.popen("adb shell input keyevent 26") # 点击电源亮屏
def setUpClass(cls): cls.dev = Android() cls.dev.ori_method = "ADBORI"
def setUpClass(cls): cls.dev = Android() cls.dev.rotation_watcher.get_ready()
def setUpClass(cls): cls.android = Android() cls.filepath = "screen.mp4"
def setUpClass(cls): cls.dev = Android() cls.dev.rotation_watcher.get_ready() cls.minicap = Minicap(cls.dev.adb, rotation_watcher=cls.dev.rotation_watcher)
def __init__(self): self.android = Android() self.adb = self.android.adb
from airtest.core.api import * from airtest.core.api import connect_device from airtest.core.android.android import Android dev = Android() print(dev.list_app()) # for p in dev.list_app(): # # print(p) print(shell('ls'))