import os import re import xml.etree.ElementTree as ET from xml.dom import minidom from scripts.task import Task from utils import FileUtils from utils.logger_utils import app_logger GAME_ACTIVITY_PATH = f"launcher-game/src/com/game/launcher/activity/GLGameActivity.kt".replace("/", os.sep) ANDROID_MANIFEST_PATH = f"launcher-game/AndroidManifest.xml".replace("/", os.sep) def process_manifest(input_path, output_path): # 解析XML文件 tree = ET.parse(input_path) root = tree.getroot() # 定义命名空间映射 android_namespace = 'http://schemas.android.com/apk/res/android' ET.register_namespace('android', android_namespace) namespaces = {'android': android_namespace} # 处理application标签,移除所有属性 application = root.find('application') if application is not None: # 保存所有子节点 children = list(application) # 清除application标签 root.remove(application) # 创建新的application标签(无属性) new_application = ET.Element('application') # 添加回所有子节点 for child in children: new_application.append(child) # 将新的application标签添加回root root.append(new_application) # 查找并删除指定的activity节点 activity_to_remove = new_application.find( ".//activity[@android:name='com.unity3d.player.UnityPlayerActivity']", namespaces=namespaces ) if activity_to_remove is not None: new_application.remove(activity_to_remove) # 保存处理后的XML,保留android命名空间前缀 rough_string = ET.tostring(root, 'utf-8') reparsed = minidom.parseString(rough_string) pretty_xml = reparsed.toprettyxml(indent=" ", encoding='utf-8') # 去除空行 lines = pretty_xml.decode('utf-8').split('\n') non_empty_lines = [line for line in lines if line.strip() != ''] pretty_xml = '\n'.join(non_empty_lines).encode('utf-8') with open(output_path, 'wb') as f: f.write(pretty_xml) print(f"处理完成,结果已保存到 {output_path}") def uncomment_line(content, line_pattern): """ 取消指定行的注释 :param content: 文件内容 :param line_pattern: 要取消注释的行内容(不含前导//和空格) :return: 更新后的内容 """ # 匹配以//开头,后跟任意空格,然后是目标行内容 pattern = rf'^(\s*)//\s*({re.escape(line_pattern)}\s*)$' # 替换为去注释版本(保留原有缩进) replacement = rf'\1\2' updated_content = re.sub(pattern, replacement, content, flags=re.MULTILINE) return updated_content class ProjectUpdateGameRes(Task): def update_game_result(self): if not self.context.update_res_unity: app_logger().info("No update game res found") return """ 更新游戏资源 :return: """ if self.context.game_type == "unity_native": res_path = self.context.res_unity_path dst = os.path.join(self.context.temp_project_path, "unityLibrary") temp_dst = dst + "_res" if os.path.exists(dst): result = FileUtils.delete(dst, True) app_logger().info(f"删除unityLibrary结果 : {result}") if os.path.exists(temp_dst): result = FileUtils.delete(temp_dst, True) app_logger().info(f"删除temp unityLibrary结果 : {result}") FileUtils.decompress(res_path, temp_dst) build_path = os.path.join(temp_dst, "build") if os.path.exists(build_path): FileUtils.delete(build_path, True) if os.listdir(temp_dst).index("unityLibrary") >= 0: FileUtils.copy(os.path.join(temp_dst, "unityLibrary"), dst) else: FileUtils.copy(temp_dst, dst) android_manifest_xml_path = os.path.join(dst, "src", "main", "AndroidManifest.xml") process_manifest(android_manifest_xml_path, android_manifest_xml_path) text = open(os.path.join(dst, "build.gradle"), "r", encoding="utf-8").read() text = text.replace("implementation", "api") if not 'namespace "com.unity3d.player"' in text: text = text.replace("compileSdkVersion", """ namespace "com.unity3d.player" compileSdkVersion""") text = text.replace("unityStreamingAssets.tokenize(', ')", '[".unity3d", ".bundle", ".version", ".bytes", ".hash"]') text = text.replace("apply plugin: 'com.android.library'", """ plugins { id 'com.android.library' } """) open(os.path.join(dst, "build.gradle"), "w", encoding="utf-8").write(text) lines = open(os.path.join(dst, "build.gradle"), "r", encoding="utf-8").readlines() new_lines = [] for line in lines: if line.find("com.game:hachisdk") > 0: continue new_lines.append(line) open(os.path.join(dst, "build.gradle"), "w", encoding="utf-8").writelines(new_lines) # 引用Unity项目 text = open(os.path.join(self.context.temp_project_path, "ad.gradle"), "r", encoding="utf-8").read() text = uncomment_line(text, "implementation projects.unityLibrary") open(os.path.join(self.context.temp_project_path, "ad.gradle"), "w", encoding="utf-8").write(text) text = open(os.path.join(self.context.temp_project_path, "settings.gradle"), "r", encoding="utf-8").read() text = uncomment_line(text, "include ':unityLibrary'") open(os.path.join(self.context.temp_project_path, "settings.gradle"), "w", encoding="utf-8").write(text) # launcher 引用 unityActivity text = open(os.path.join(self.context.temp_project_path, GAME_ACTIVITY_PATH), "r", encoding="utf-8").read() text = text.replace("GLGameWebActivity", "com.unity3d.player.UnityPlayerActivity") open(os.path.join(self.context.temp_project_path, GAME_ACTIVITY_PATH), "w", encoding="utf-8").write(text) text = open(os.path.join(self.context.temp_project_path, ANDROID_MANIFEST_PATH), "r", encoding="utf-8").read() text = text.replace("@style/LauncherGameIntroTheme", "@style/UnityThemeSelector") open(os.path.join(self.context.temp_project_path, ANDROID_MANIFEST_PATH), "w", encoding="utf-8").write(text) else: raise Exception(f"不支持的游戏类型 : {self.context.game_type}") pass def execute(self): self.update_game_result() self.context.save_cache_config("res_unity", self.context.config_res_unity_md5) pass