import hashlib import os from pathlib import Path import re from scripts.context import Context from scripts.task import Task from utils import FileUtils def extract_launcher_ids(xml_content): """ 修复版:提取所有以 "launcher_" 开头的 android:id 值 """ pattern = r'android:id\s*=\s*"@\+id/(launcher_\w+)"' matches = re.findall(pattern, xml_content) return matches # def extract_launcher_ids(xml_content): # """提取所有 android:id 值""" # pattern = r'android:id\s*=\s*"@\+id/([^"]+)"' # return re.findall(pattern, xml_content) def string_to_md5(text): # 将字符串编码为UTF-8字节 text_bytes = text.encode('utf-8') # 创建MD5哈希对象并更新字节数据 md5_hash = hashlib.md5(text_bytes) # 返回十六进制哈希字符串 return md5_hash.hexdigest() def generate_encryption_key(key: str, s_len: int = -1, target_package_name: str = "") -> str: # if game_editor == "Cocos": # return key handle_key = target_package_name + key + target_package_name processed_key = string_to_md5(handle_key) while processed_key[0].isdigit(): processed_key = processed_key[1:] # 移除首字符 # 计算目标长度 if s_len > 0: target_length = s_len else: target_length = len(key) # 取前N位(根据原始key长度),不足则全部保留 # 如果处理后的key为空(极小概率),则返回空字符串 return processed_key[:target_length] if processed_key else "" layout_path = "LauncherCode/res/layout".replace("/", os.sep) values_path = "LauncherCode/res/values".replace("/", os.sep) drawable_xxhdpi_path = "LauncherCode/res/drawable-xxhdpi".replace("/", os.sep) drawable_path = "LauncherCode/res/drawable".replace("/", os.sep) code_path = "LauncherCode/src".replace("/", os.sep) android_manifest_path = "lawnchair/AndroidManifest.xml".replace("/", os.sep) xml_path = "lawnchair/res/xml".replace("/", os.sep) launcher_code_path = "lawnchair/src".replace("/", os.sep) src_code_path = "src".replace("/", os.sep) launchercode = "launchercode" lawn_layout = "res/layout".replace("/", os.sep) qucikset_manifest = "quickstep/AndroidManifest-launcher.xml".replace("/", os.sep) lawn_manifest = "AndroidManifest.xml".replace("/", os.sep) pag_file = "lawnchair/assets/pag_wallpaper_slide.pag".replace("/", os.sep) class ProjectProguard(Task): def __init__(self, context: Context): super().__init__(context) self.context.proguard_dict = { launchercode: generate_encryption_key(launchercode, target_package_name=self.context.package_name)} def add_proguard_key(self, key: str) -> str: value = self.context.proguard_dict.get(key) if value: return value value = generate_encryption_key(key, target_package_name=self.context.package_name) self.context.proguard_dict[key] = value return value def rename_files_in_dir(self, dir_path: str): for root, dirs, files in os.walk(dir_path): for file in files: file_path = os.path.join(root, file) name = Path(file).stem add_proguard_key = self.add_proguard_key(name) FileUtils.move(file_path, os.path.join(root, file.replace(name, add_proguard_key)) .replace(launchercode, self.context.proguard_dict.get(launchercode)), overwrite=True) def update(self, file_path: str): text = open(file_path, "r", encoding="UTF-8").read() for key, value in self.context.proguard_dict.items(): text = text.replace(key, value) pass open(file_path, "w", encoding="UTF-8").write(text) def update_proguard(self, dir_path: str): if os.path.isdir(dir_path): for root, dirs, files in os.walk(dir_path): for file in files: if file.endswith(".xml") or file.endswith(".java") or file.endswith(".kt"): file_path = os.path.join(root, file) self.update(file_path) else: self.update(dir_path) pass def update_id(self, file_path: str): for root, dirs, files in os.walk(file_path): for file in files: xml_file = os.path.join(root, file) text = open(xml_file, "r", encoding="UTF-8").read() ids = extract_launcher_ids(text) for id in ids: self.add_proguard_key(id) def write_proguard(self): file_path = os.path.join(self.context.temp_project_path, "proguard.pro") lines = open(file_path, "r", encoding="UTF-8").readlines() lines.append(f""" -repackageclasses '{self.context.package_name}' # 将所有类移动到 '{self.context.package_name}' 包下 -flattenpackagehierarchy '{self.context.package_name}' # 扁平化包结构 """) open(file_path, "w", encoding="UTF-8").writelines(lines) pass def execute(self): self.write_proguard() self.add_proguard_key("LauncherMyNoActionBar") self.add_proguard_key("LauncherIntroTheme") self.add_proguard_key("LauncherGameIntroTheme") self.add_proguard_key("LauncherTransparentTheme") self.add_proguard_key("launchergamead") self.add_proguard_key("launcher_help_detail") self.add_proguard_key("launcher_help") self.add_proguard_key("launcher_uninstall") self.add_proguard_key("launcher_onboard") self.add_proguard_key("pag_wallpaper_slide") self.update_id(os.path.join(self.context.temp_project_path, lawn_layout)) self.update_id(os.path.join(self.context.temp_project_path, layout_path)) self.rename_files_in_dir(os.path.join(self.context.temp_project_path, layout_path)) self.rename_files_in_dir(os.path.join(self.context.temp_project_path, drawable_xxhdpi_path)) self.rename_files_in_dir(os.path.join(self.context.temp_project_path, drawable_path)) self.rename_files_in_dir(os.path.join(self.context.temp_project_path, code_path)) self.context.proguard_dict = { k: v for k, v in sorted( self.context.proguard_dict.items(), key=lambda item: len(item[0]), reverse=True ) } self.update_proguard(os.path.join(self.context.temp_project_path, layout_path)) self.update_proguard(os.path.join(self.context.temp_project_path, values_path)) self.update_proguard(os.path.join(self.context.temp_project_path, drawable_xxhdpi_path)) self.update_proguard(os.path.join(self.context.temp_project_path, drawable_path)) self.update_proguard(os.path.join(self.context.temp_project_path, code_path)) self.update_proguard(os.path.join(self.context.temp_project_path, android_manifest_path)) self.update_proguard(os.path.join(self.context.temp_project_path, xml_path)) self.update_proguard(os.path.join(self.context.temp_project_path, launcher_code_path)) self.update_proguard(os.path.join(self.context.temp_project_path, src_code_path)) self.update_proguard(os.path.join(self.context.temp_project_path, qucikset_manifest)) self.update_proguard(os.path.join(self.context.temp_project_path, lawn_manifest)) self.update_proguard(os.path.join(self.context.temp_project_path, lawn_layout)) target_pag_file = os.path.join(self.context.temp_project_path, pag_file) FileUtils.move(target_pag_file, target_pag_file.replace("pag_wallpaper_slide", self.context.proguard_dict.get("pag_wallpaper_slide"))) pass if __name__ == "__main__": file = "../project/com_punch_prankster_puzzle_fwaes_free_launcher_fgsaw223908/LauncherCode/res/layout/a60034437eae19e7b00.xml".replace( "/", os.sep) text = open(file, "r", encoding="UTF-8").read() print(text) temp = extract_launcher_ids(text) print(temp) pass