def main(device: AdbDevice = None): """ Initializes the global state, sets up a ThreadPoolExecutor and launches the Nimses app. :param device: the device to control, if `None`, chooses the first and only device """ executor = ThreadPoolExecutor(3) state = { "device": device if device is not None else adb.device(), # The Android device to control "executor": executor, # The executor where the magic happens "last_image": None, # The last image "last_ad": 0, # The amount of updates since the last ad "ad_closed": True, # Whether the last ad has been closed "ad_time": 0 # When to close the app (in the future) } device.app_start(NIMSES_PACKAGE, NIMSES_MAIN_ACTIVITY) # Prepare future variable future = Future() future.set_result(None) while True: if future.done(): future = executor.submit(lambda: log_error(lambda: handle_new_ad( find_inline_ads(screen_shot_android(device)), device, state))) sleep(0.1)
def handle_new_ad(ad: Tuple[Tuple[int, int], np.ndarray], device: AdbDevice, state: dict): """ Handles a newly identified ad, whether or not there actually is one. This method also makes sure, that ads are closed again. Some ads open the Play Store, so this method also moves back to Nimses. :param ad: a tuple with the ad location (optional) and the screen shot. :param device: the Android device that should be controlled :param state: the global state of this application """ def close_ad(): """ Closes the currently open ad (really just switches to the main activity) """ if not state["ad_closed"] and state["ad_time"] < time(): device.app_start(NIMSES_PACKAGE, NIMSES_MAIN_ACTIVITY) state["ad_closed"] = True logger.info("Closed ad") pt, image = ad app = device.current_app() logger.info("Current app %s", app) logger.info("Ad open? %s", not state["ad_closed"]) if np.array_equal(image, state["last_image"]) \ or state["last_ad"] > 10: output = device.shell(["am", "force-stop", NIMSES_PACKAGE]) logger.info(f"[ADB] {output}") device.app_start(NIMSES_PACKAGE, NIMSES_MAIN_ACTIVITY) state["last_ad"] = 0 state["ad_closed"] = True logger.info("Restarted Nimses") elif app["package"] == NIMSES_PACKAGE: if app["activity"] == NIMSES_MAIN_ACTIVITY: # Ad found, click it if pt: device.click(pt[0], pt[1]) state["last_ad"] = 0 state["ad_closed"] = True logger.info("Clicked %d, %d", pt[0], pt[1]) # No ad, scroll along else: state["last_ad"] += 1 w, h = device.window_size() sx = w // 2 sy = h // 4 * 3 dx = w // 2 dy = h // 4 * 1 device.swipe(sx, sy, dx, dy, 1.0) logger.info("Scrolled from %d %d to %d %d", sx, sy, dx, dy) elif app["activity"] in NIMSES_AD_ACTIVITIES: if state["ad_closed"]: state["ad_time"] = time() + 35 state["ad_closed"] = False logger.info("Close ad at: %s", strftime("%H:%M:%S", localtime(state["ad_time"]))) else: close_ad() elif app["package"] == PLAYSTORE_PACKAGE: device.app_start(NIMSES_PACKAGE, NIMSES_MAIN_ACTIVITY) logger.info("Closed Play Store") else: device.app_start(NIMSES_PACKAGE, NIMSES_MAIN_ACTIVITY)