2025-07-08 00:58:35 +00:00
|
|
|
|
import hashlib
|
|
|
|
|
import os
|
|
|
|
|
from pathlib import Path
|
2025-07-10 16:10:25 +00:00
|
|
|
|
import re
|
2025-07-08 00:58:35 +00:00
|
|
|
|
|
|
|
|
|
from scripts.context import Context
|
|
|
|
|
from scripts.task import Task
|
|
|
|
|
from utils import FileUtils
|
|
|
|
|
|
|
|
|
|
|
2025-07-10 16:10:25 +00:00
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|
2025-07-08 00:58:35 +00:00
|
|
|
|
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)
|
2025-07-10 16:10:25 +00:00
|
|
|
|
values_path = "LauncherCode/res/values".replace("/", os.sep)
|
2025-07-08 00:58:35 +00:00
|
|
|
|
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"
|
|
|
|
|
|
2025-07-10 16:10:25 +00:00
|
|
|
|
lawn_layout = "res/layout".replace("/", os.sep)
|
|
|
|
|
|
2025-07-11 02:12:01 +00:00
|
|
|
|
qucikset_manifest = "quickstep/AndroidManifest-launcher.xml".replace("/", os.sep)
|
|
|
|
|
lawn_manifest = "AndroidManifest.xml".replace("/", os.sep)
|
|
|
|
|
|
2025-07-15 14:03:08 +00:00
|
|
|
|
pag_file = "lawnchair/assets/pag_wallpaper_slide.pag".replace("/", os.sep)
|
|
|
|
|
|
2025-07-08 00:58:35 +00:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2025-07-10 16:10:25 +00:00
|
|
|
|
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
|
|
|
|
|
|
2025-07-08 00:58:35 +00:00
|
|
|
|
def execute(self):
|
2025-07-10 16:10:25 +00:00
|
|
|
|
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")
|
2025-07-15 14:03:08 +00:00
|
|
|
|
self.add_proguard_key("pag_wallpaper_slide")
|
2025-07-10 16:10:25 +00:00
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
|
2025-07-08 00:58:35 +00:00
|
|
|
|
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))
|
2025-07-10 16:10:25 +00:00
|
|
|
|
self.update_proguard(os.path.join(self.context.temp_project_path, values_path))
|
2025-07-08 00:58:35 +00:00
|
|
|
|
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))
|
2025-07-11 02:12:01 +00:00
|
|
|
|
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))
|
2025-07-10 16:10:25 +00:00
|
|
|
|
|
|
|
|
|
self.update_proguard(os.path.join(self.context.temp_project_path, lawn_layout))
|
|
|
|
|
|
2025-07-15 14:03:08 +00:00
|
|
|
|
target_pag_file = os.path.join(self.context.temp_project_path, pag_file)
|
|
|
|
|
FileUtils.move(target_pag_file,
|
2025-07-15 14:31:20 +00:00
|
|
|
|
target_pag_file.replace("pag_wallpaper_slide",
|
|
|
|
|
self.context.proguard_dict.get("pag_wallpaper_slide")))
|
2025-07-08 00:58:35 +00:00
|
|
|
|
pass
|
2025-07-10 16:10:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|