auto_build_launcher/scripts/project_proguard.py

185 lines
7.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
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.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, lawn_layout))
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