diff --git a/scripts/project_update.py b/scripts/project_update.py index 4384357..a47521d 100644 --- a/scripts/project_update.py +++ b/scripts/project_update.py @@ -1,10 +1,12 @@ import os.path from pathlib import Path import re +from xml.dom import minidom import javaproperties import requests from lxml import etree +import xml.etree.ElementTree as ET from scripts.context import Context from scripts.task import Task @@ -12,33 +14,53 @@ from utils import FileUtils from utils.logger_utils import app_logger -def update_dependency_version(content, dependency_name, new_version): - """ - 更新 Gradle 依赖的版本号 +def process_manifest(input_path, output_path): + # 解析XML文件 + tree = ET.parse(input_path) + root = tree.getroot() - :param content: Gradle 文件内容 - :param dependency_name: 依赖名称(可以是完整字符串或部分匹配) - :param new_version: 新版本号 - :return: 更新后的内容 - """ - # 匹配 implementation 声明,捕获组用于保留前缀和后缀 - pattern = rf"(implementation\s*\(\s*['\"]{re.escape(dependency_name)}:)([^'\"]+)(['\"]\s*\))" + # 定义命名空间映射 + android_namespace = 'http://schemas.android.com/apk/res/android' + ET.register_namespace('android', android_namespace) + namespaces = {'android': android_namespace} - # 替换版本号部分 - updated_content = re.sub(pattern, rf"\g<1>{new_version}\g<3>", content) + # 处理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) - return updated_content + # 查找并删除指定的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') -def get_latest_version(url): - try: - response = requests.get(url) - root = etree.fromstring(response.content) - latest = root.xpath("//latest/text()") or root.xpath("//version[last()]/text()") - return latest[0] if latest else None - except Exception as e: - app_logger().error(f"Error: {e}") - return None + # 去除空行 + 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): @@ -82,6 +104,56 @@ def update_gradle_variable(content, variable_name, new_value): return updated_content +def modify_text_with_regex(original_text, key, new_value): + """ + 使用正则表达式修改文本中指定key的值,支持带引号和数字类型 + + 参数: + original_text -- 原始文本内容 + key -- 要修改的键名 + new_value -- 新的值 + + 返回: + 修改后的文本内容 + """ + # 改进的正则模式:更精确地匹配带引号的值和数字值 + # 匹配带引号的值(单引号或双引号)或数字值 + pattern = re.compile( + r'(final def ' + re.escape(key) + r' = )' # 前缀部分 + r'(?:' # 非捕获组,用于分组不同情况 + r'([\'"])(.*?)\2' # 带引号的值(单引号或双引号) + r'|' # 或者 + r'(\d+)' # 数字值(整数) + r')' + ) + + # 查找匹配 + match = pattern.search(original_text) + + if not match: + print(f"未找到键: {key}") + return original_text + + # 检查是带引号的情况还是数字情况 + quote_type = match.group(2) # 引号类型(单引号或双引号) + is_number = match.group(4) is not None # 是否是数字类型 + + # 构造替换字符串 + if quote_type: + # 有引号的情况,保持原有引号类型 + replacement = f'\g<1>{quote_type}{new_value}{quote_type}' + elif is_number: + # 数字类型,直接替换数字 + replacement = f'\g<1>{new_value}' + else: + # 其他情况,保持原样替换 + replacement = f'\g<1>{new_value}' + + # 执行替换,只替换第一个匹配项 + modified_text = pattern.sub(replacement, original_text, count=1) + return modified_text + + def update_gradle_property(content, key, new_value): # 匹配两种格式: # 1. resValue "string", "key", "value" @@ -95,10 +167,10 @@ def update_gradle_property(content, key, new_value): LAUNCHER_CODE_PATH = f"LauncherCode/src/com/launchercode".replace("/", os.sep) -GAME_ACTIVITY_PATH = f"LauncherCode/src/com/launchercode/GameActivity.kt".replace("/", os.sep) +GAME_ACTIVITY_PATH = f"launcher-game/src/com/game/launcher/activity/GLGameActivity.kt".replace("/", os.sep) GAME_ACTIVITY_PATH_2 = f"LauncherCode/src/com/launchercode/activity/GameActivity.kt".replace("/", os.sep) -ANDROID_MANIFEST_PATH = f"lawnchair/AndroidManifest.xml".replace("/", os.sep) -STRING_PATH = f"LauncherCode/res/values/strings.xml".replace("/", os.sep) +ANDROID_MANIFEST_PATH = f"launcher-game/AndroidManifest.xml".replace("/", os.sep) +STRING_PATH = f"launcher-game/res/values/strings.xml".replace("/", os.sep) LAUNCER_STRING_PATH = f"LauncherCode/src/com/launchercode/LauncherStringsValue.kt".replace("/", os.sep) @@ -114,21 +186,19 @@ class ProjectUpdate(Task): :return: """ - build_gradle_path = os.path.join(self.context.temp_project_path, "build.gradle") + build_gradle_path = os.path.join(self.context.temp_project_path, "ad.gradle") text = open(build_gradle_path, "r", encoding="utf-8").read() - text = text.replace("com.fingerheart.launcher.game.free.sdjws", self.context.package_name) + text = text.replace(self.context.original_package, self.context.package_name) open(build_gradle_path, "w", encoding="utf-8").write(text) xml_path = os.path.join(self.context.temp_project_path, "lawnchair/res/xml") - # com.launchercode.SplashActivity - # TODO 这里还需要改启动项 for root, dirs, files in os.walk(xml_path): for file in files: temp_xml_path = os.path.join(root, file) text = open(temp_xml_path, "r", encoding="utf-8").read() - text = text.replace("com.fingerheart.launcher.game.free.sdjws", self.context.package_name) + text = text.replace(self.context.original_package, self.context.package_name) open(temp_xml_path, "w", encoding="utf-8").write(text) pass pass @@ -178,9 +248,9 @@ storePassword=123456 os.path.join(self.context.temp_project_path, "google-services.json"), True) - dst_path = os.path.join(self.context.temp_project_path, f"lawnchair{os.sep}assets") + dst_path = os.path.join(self.context.temp_project_path, f"launcher-game{os.sep}assets") - for file in list(filter(lambda f: not (f == "google_fonts.json" or f == "pag_wallpaper_slide.pag"), + for file in list(filter(lambda f: not (f == "google_fonts.json" or f == "pag_gl_slide.pag"), os.listdir(dst_path))): FileUtils.delete(os.path.join(dst_path, file), True) pass @@ -212,7 +282,7 @@ storePassword=123456 temp_tart_path = os.path.join(root, file) if temp_tart_path.find("__MACOSX") > 0: continue - temp_dst = temp_tart_path.replace(tag, "res") + temp_dst = temp_tart_path.replace(tag, "launcher-game" + os.sep + "res") app_logger().debug(f"copy icon = {temp_tart_path} -> {temp_dst}") FileUtils.copy(temp_tart_path, temp_dst, True) pass @@ -232,6 +302,10 @@ storePassword=123456 temp_dst = dst + "_res" if os.path.exists(dst): FileUtils.delete(dst, True) + + if os.path.exists(temp_dst): + FileUtils.delete(temp_dst, True) + FileUtils.decompress(res_path, temp_dst) build_path = os.path.join(temp_dst, "build") @@ -243,11 +317,16 @@ storePassword=123456 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") - text = text.replace("compileSdkVersion", """ - namespace "com.unity3d.player" - compileSdkVersion""") + 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'", """ @@ -257,15 +336,26 @@ plugins { """) 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(self.build_gradle_path, "r", encoding="utf-8").read() + 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(self.build_gradle_path, "w", encoding="utf-8").write(text) + 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("WebActivity", "com.unity3d.player.UnityPlayerActivity") + 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", @@ -295,7 +385,7 @@ plugins { dst = os.path.join(dst, "drawable-xxhdpi") target_root_path = os.path.join(self.context.temp_project_path, - f"LauncherCode{os.sep}res{os.sep}drawable-xxhdpi") + f"launcher-game{os.sep}res{os.sep}drawable-xxhdpi") image_list = list(map(lambda f: Path(f).stem, os.listdir(target_root_path))) @@ -318,21 +408,17 @@ plugins { :return: """ - build_gradle_path = os.path.join(self.context.temp_project_path, "build.gradle") + build_gradle_path = os.path.join(self.context.temp_project_path, "ad.gradle") text = open(build_gradle_path, "r", encoding="UTF-8").read() - text = update_gradle_property(text, "admob_app_id", self.context.admob_app_id) - text = update_gradle_property(text, "game_services_project_id", self.context.game_services_project_id) - text = update_gradle_property(text, "facebook_app_id", self.context.facebook_app_id) - text = update_gradle_property(text, "facebook_client_token", self.context.facebook_client_token) - text = update_gradle_property(text, "derived_app_name", self.context.get_app_name()) - text = update_gradle_variable(text, "versionDisplayName", self.context.version_display_name) - text = update_gradle_variable(text, "version_code", self.context.version_code) - text = update_dependency_version(text, f"straw:hachisdk_unity_{self.context.package_name}", - self.context.sdk_prolink_version) - text = update_dependency_version(text, f"com.game:hachisdk_unity_{self.context.package_name}", - self.context.sdk_version) + text = modify_text_with_regex(text, "admob_app_id", self.context.admob_app_id) + text = modify_text_with_regex(text, "game_services_project_id", self.context.game_services_project_id) + text = modify_text_with_regex(text, "facebook_app_id", self.context.facebook_app_id) + text = modify_text_with_regex(text, "facebook_client_token", self.context.facebook_client_token) + text = modify_text_with_regex(text, "appName", self.context.get_app_name()) + text = modify_text_with_regex(text, "appVersionName", self.context.version_display_name) + text = modify_text_with_regex(text, "appVersionCode", self.context.version_code) open(build_gradle_path, "w", encoding="UTF-8").write(text) pass @@ -346,28 +432,20 @@ plugins { raise Exception("配置文件中没有配置 tkg_custom") text = open(os.path.join(self.context.temp_project_path, STRING_PATH), "r", encoding="utf-8").read() - text = text.replace("https://harmonitun.com/privacy.html", privacy) - text = text.replace("https://harmonitun.com/TermsOfUse.html", + text = text.replace("https://doanvanquy.com/privacy.html", privacy) + text = text.replace("https://doanvanquy.com/TermsOfUse.html", privacy.replace("privacy.html", "TermsOfUse.html")) - text = text.replace("harmounitun@outlook.com", tkg_custom) open(os.path.join(self.context.temp_project_path, STRING_PATH), "w", encoding="utf-8").write(text) - text = open(os.path.join(self.context.temp_project_path, LAUNCER_STRING_PATH), "r", encoding="utf-8").read() - text = text.replace("https://harmonitun.com/privacy.html", privacy) - text = text.replace("https://harmonitun.com/TermsOfUse.html", - privacy.replace("privacy.html", "TermsOfUse.html")) - text = text.replace("harmounitun@outlook.com", tkg_custom) - open(os.path.join(self.context.temp_project_path, LAUNCER_STRING_PATH), "w", encoding="utf-8").write(text) - pass - - def update_code_dir(self): - # code_path = os.path.join(self.context.temp_project_path, GAME_ACTIVITY_PATH) - # for i in os.listdir(code_path): - # os + # text = open(os.path.join(self.context.temp_project_path, LAUNCER_STRING_PATH), "r", encoding="utf-8").read() + # text = text.replace("https://harmonitun.com/privacy.html", privacy) + # text = text.replace("https://harmonitun.com/TermsOfUse.html", + # privacy.replace("privacy.html", "TermsOfUse.html")) + # text = text.replace("harmounitun@outlook.com", tkg_custom) + # open(os.path.join(self.context.temp_project_path, LAUNCER_STRING_PATH), "w", encoding="utf-8").write(text) pass def execute(self): - self.update_code_dir() global GAME_ACTIVITY_PATH path = os.path.join(self.context.temp_project_path, GAME_ACTIVITY_PATH) if not os.path.exists(path): @@ -375,7 +453,6 @@ plugins { # GAME_ACTIVITY_PATH = GAME_ACTIVITY_PATH_2 pass self.build_gradle_path = os.path.join(self.context.temp_project_path, "build.gradle") - self.init_sdk_version() self.update_package_name() self.update_keystore() self.update_config() @@ -385,33 +462,3 @@ plugins { self.update_gradle_config() self.update_string() pass - - def get_sdk_version(self) -> str: - for i in range(3): - try: - url = f"https://repo.dgtverse.cn/repository/tk_my/com/game/hachisdk_unity_{self.context.package_name}/maven-metadata.xml" - version = get_latest_version(url) - if version: - return version - pass - except Exception as e: - pass - raise Exception("sdk error.") - - def get_prolink_version(self) -> str: - for i in range(3): - try: - url = f"https://repo.dgtverse.cn/repository/tk_my/straw/hachisdk_unity_{self.context.package_name}/maven-metadata.xml" - print(url) - version = get_latest_version(url) - if version: - return version - except Exception as e: - print(e) - pass - raise Exception("sdk prolink error.") - - def init_sdk_version(self): - self.context.sdk_version = self.get_sdk_version() - self.context.sdk_prolink_version = self.get_prolink_version() - pass