diff --git a/module/config/server.py b/module/config/server.py index 899284329..32c9e0b53 100644 --- a/module/config/server.py +++ b/module/config/server.py @@ -20,6 +20,13 @@ VALID_CLOUD_SERVER = { } VALID_CLOUD_PACKAGE = set(list(VALID_CLOUD_SERVER.values())) +DICT_PACKAGE_TO_ACTIVITY = { + 'com.miHoYo.hkrpg': 'com.mihoyo.combosdk.ComboSDKActivity', + 'com.miHoYo.hkrpg.bilibili': 'com.mihoyo.combosdk.ComboSDKActivity', + 'com.HoYoverse.hkrpgoversea': 'com.mihoyo.combosdk.ComboSDKActivity', + 'com.miHoYo.cloudgames.hkrpg': 'com.mihoyo.cloudgame.ui.SplashActivity', +} + def set_lang(lang_: str): """ diff --git a/module/device/method/adb.py b/module/device/method/adb.py index 8f7a66c57..8bfa20b8c 100644 --- a/module/device/method/adb.py +++ b/module/device/method/adb.py @@ -8,6 +8,7 @@ from adbutils.errors import AdbError from lxml import etree from module.base.decorator import Config +from module.config.server import DICT_PACKAGE_TO_ACTIVITY from module.device.connection import Connection from module.device.method.utils import (ImageTruncated, PackageNotInstalled, RETRY_TRIES, handle_adb_error, handle_unknown_host_service, remove_prefix, retry_sleep) @@ -233,7 +234,7 @@ class Adb(Connection): raise OSError("Couldn't get focused app") @retry - def app_start_adb(self, package_name=None, allow_failure=False): + def _app_start_adb_monkey(self, package_name=None, allow_failure=False): """ Args: package_name (str): @@ -241,6 +242,9 @@ class Adb(Connection): Returns: bool: If success to start + + Raises: + PackageNotInstalled: """ if not package_name: package_name = self.package @@ -257,26 +261,104 @@ class Adb(Connection): raise PackageNotInstalled(package_name) elif 'inaccessible' in result: # /system/bin/sh: monkey: inaccessible or not found - pass + return False else: # Events injected: 1 # ## Network stats: elapsed time=4ms (0ms mobile, 0ms wifi, 4ms not connected) return True - result = self.adb_shell(['dumpsys', 'package', package_name]) - res = re.search(r'android.intent.action.MAIN:\s+\w+ ([\w.\/]+) filter \w+\s+' - r'.*\s+Category: "android.intent.category.LAUNCHER"', - result) - if res: - activity_name = res.group(1) - else: + @retry + def _app_start_adb_am(self, package_name=None, activity_name=None, allow_failure=False): + """ + Args: + package_name (str): + activity_name (str): + allow_failure (bool): + + Returns: + bool: If success to start + + Raises: + PackageNotInstalled: + """ + if not package_name: + package_name = self.package + if not activity_name: + result = self.adb_shell(['dumpsys', 'package', package_name]) + res = re.search(r'android.intent.action.MAIN:\s+\w+ ([\w.\/]+) filter \w+\s+' + r'.*\s+Category: "android.intent.category.LAUNCHER"', + result) + if res: + # com.bilibili.azurlane/com.manjuu.azurlane.MainActivity + activity_name = res.group(1) + try: + activity_name = activity_name.split('/')[-1] + except IndexError: + logger.error(f'No activity name from {activity_name}') + return False + else: + if allow_failure: + return False + else: + logger.error(result) + raise PackageNotInstalled(package_name) + + ret = self.adb_shell(['am', 'start', '-a', 'android.intent.action.MAIN', '-c', + 'android.intent.category.LAUNCHER', '-n', f'{package_name}/{activity_name}']) + # Invalid activity + # Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=... } + # Error type 3 + # Error: Activity class {.../...} does not exist. + if 'Error: Activity class' in ret: if allow_failure: return False else: - logger.error(result) - raise PackageNotInstalled(package_name) - self.adb_shell(['am', 'start', '-a', 'android.intent.action.MAIN', '-c', - 'android.intent.category.LAUNCHER', '-n', activity_name]) + logger.error(ret) + return False + # Already running + # Warning: Activity not started, intent has been delivered to currently running top-most instance. + if 'Warning: Activity not started' in ret: + logger.info('App activity is already started') + return True + # Success + # Starting: Intent... + return True + + # No @retry decorator since _app_start_adb_am and _app_start_adb_monkey have @retry already + # @retry + def app_start_adb(self, package_name=None, activity_name=None, allow_failure=False): + """ + Args: + package_name (str): + If None, to get from config + activity_name (str): + If None, to get from DICT_PACKAGE_TO_ACTIVITY + If still None, launch from monkey + If monkey failed, fetch activity name and launch from am + allow_failure (bool): + True for no PackageNotInstalled raising, just return False + + Returns: + bool: If success to start + + Raises: + PackageNotInstalled: + """ + if not package_name: + package_name = self.package + if not activity_name: + activity_name = DICT_PACKAGE_TO_ACTIVITY.get(package_name) + + if activity_name: + if self._app_start_adb_am(package_name, activity_name, allow_failure): + return True + if self._app_start_adb_monkey(package_name, allow_failure): + return True + if self._app_start_adb_am(package_name, activity_name, allow_failure): + return True + + logger.error('app_start_adb: All trials failed') + return False @retry def app_stop_adb(self, package_name=None): diff --git a/module/device/method/uiautomator_2.py b/module/device/method/uiautomator_2.py index 6cb3cb8d6..04a55883f 100644 --- a/module/device/method/uiautomator_2.py +++ b/module/device/method/uiautomator_2.py @@ -8,6 +8,7 @@ from adbutils.errors import AdbError from lxml import etree from module.base.utils import * +from module.config.server import DICT_PACKAGE_TO_ACTIVITY from module.device.connection import Connection from module.device.method.utils import (ImageTruncated, PackageNotInstalled, RETRY_TRIES, handle_adb_error, handle_unknown_host_service, possible_reasons, retry_sleep) @@ -223,11 +224,24 @@ class Uiautomator2(Connection): return result['package'] @retry - def app_start_uiautomator2(self, package_name=None): + def app_start_uiautomator2(self, package_name=None, activity_name=None): + """ + Args: + package_name (str): + If None, to get from config + activity_name (str): + If None, to get from DICT_PACKAGE_TO_ACTIVITY + + Returns: + + """ if not package_name: package_name = self.package + if not activity_name: + activity_name = DICT_PACKAGE_TO_ACTIVITY.get(package_name) + try: - self.u2.app_start(package_name) + self.u2.app_start(package_name, activity_name) except u2.exceptions.BaseError as e: # BaseError: package "com.bilibili.azurlane" not found logger.error(e) diff --git a/tasks/battle_pass/battle_pass.py b/tasks/battle_pass/battle_pass.py index 000c3ce3f..03b1758a8 100644 --- a/tasks/battle_pass/battle_pass.py +++ b/tasks/battle_pass/battle_pass.py @@ -23,6 +23,14 @@ from tasks.item.assets.assets_item_ui import SWITCH_CLICK class BattlePassTab(Switch): + def add_state(self, state, check_button, click_button=None): + if click_button is not None: + # Limit click_button.button + left = SWITCH_CLICK.area[0] + for button in click_button.buttons: + button._button = (left, button._button[1], button._button[2], button._button[3]) + return super().add_state(state, check_button, click_button) + def handle_additional(self, main: UI): if main.handle_reward(): return True @@ -43,14 +51,6 @@ SWITCH_BATTLE_PASS_TAB.add_state( class BattlePassMissionTab(Switch): - def add_state(self, state, check_button, click_button=None): - if click_button is not None: - # Limit click_button.button - left = SWITCH_CLICK.area[0] - for button in click_button.buttons: - button._button = (left, button._button[1], button._button[2], button._button[3]) - return super().add_state(state, check_button, click_button) - def get(self, main): """ Args: diff --git a/tasks/combat/prepare.py b/tasks/combat/prepare.py index 98dcf718a..3f76ecd87 100644 --- a/tasks/combat/prepare.py +++ b/tasks/combat/prepare.py @@ -131,7 +131,8 @@ class CombatPrepare(UI): logger.warning(f'Combat wave costs {cost} but has multiple waves, ' f'probably wave amount is preset') self.combat_set_wave(1) - skip_first_screenshot = True + # Don't skip_first_screenshot, combat_set_wave may not have screenshot updated + # skip_first_screenshot = True timeout.reset() continue else: diff --git a/tasks/login/cloud.py b/tasks/login/cloud.py index 7ef05b431..895909135 100644 --- a/tasks/login/cloud.py +++ b/tasks/login/cloud.py @@ -167,6 +167,8 @@ class LoginAndroidCloud(ModuleBase): season_pass = round(season_pass / 24, 2) elif '分钟' in text: season_pass = round(season_pass / 24 / 60, 3) + elif text == '': + season_pass = 0 else: logger.error(f'Unexpected season pass text: {text}')