From edb8fff9fcd003f94b37d9e39ad1df48d94a3884 Mon Sep 17 00:00:00 2001
From: juneix <81808039+juneix@users.noreply.github.com>
Date: Tue, 21 Apr 2026 19:19:27 +0800
Subject: [PATCH] v1.1
---
.github/patch_android.py | 92 +++++++++++++++-------------------------
1 file changed, 34 insertions(+), 58 deletions(-)
diff --git a/.github/patch_android.py b/.github/patch_android.py
index d533efa..ff9093f 100644
--- a/.github/patch_android.py
+++ b/.github/patch_android.py
@@ -4,38 +4,33 @@ import sys
import shutil
import argparse
-# 根据命令行参数决定打包中文版还是英文版
-# 用法: python patch_android.py --lang zh 或 --lang en
+# 根据命令行参数决定打包语言版本
parser = argparse.ArgumentParser()
parser.add_argument("--lang", choices=["zh", "en"], default="zh", help="打包语言版本")
args = parser.parse_args()
LANG = args.lang
PKG_NAME = "juneix.embyx"
-PKG_PATH = PKG_NAME.replace(".", "/") # juneix/embyx
+PKG_PATH = PKG_NAME.replace(".", "/")
APP_NAME = "EmbyX"
-ICON_SRC = f"{LANG}/icon.png" # zh/icon.png 或 en/icon.png
+ICON_SRC = f"{LANG}/icon.png"
# ── 0. 从 HTML 徽章提取版本号 ─────────────────────────────────────────────────
-# HTML 中的版本徽章格式为 ">v1.1<",两个版本的徽章内容保持一致,统一读 zh/index.html
-# 修改规格:如需从其他文件读取版本,修改下方 VERSION_SRC 路径即可
VERSION_SRC = "zh/index.html"
-version_name = "1.0" # 默认回退值
-version_code = 100 # 对应 v1.0
+version_name = "1.0"
+version_code = 100
if os.path.exists(VERSION_SRC):
with open(VERSION_SRC, "r", encoding="utf-8") as f:
html = f.read()
- # 匹配徽章文本,例如 ">v1.1<" 或 ">v2.0<"(非贪婪,只取第一个)
+ # 匹配徽章文本,例如 ">v1.1<" 或 ">v2.0<"
m = re.search(r">v(\d+)\.(\d+)(?:\.(\d+))?<", html)
if m:
major = int(m.group(1))
minor = int(m.group(2))
patch = int(m.group(3)) if m.group(3) else 0
version_name = f"{major}.{minor}" if patch == 0 else f"{major}.{minor}.{patch}"
- # versionCode 规则:major×10000 + minor×100 + patch
- # 示例:v1.0→10000, v1.1→10100, v1.9→10900, v2.0→20000, v1.1.2→10102
- # 这样三段版本号也能正确递增,且不会与两段版本号冲突
+ # versionCode 规则:major×10000 + minor×100 + patch 保证覆盖安装递增
version_code = major * 10000 + minor * 100 + patch
print(f" Detected version: v{version_name} → versionCode={version_code}")
else:
@@ -46,7 +41,6 @@ else:
print(f"Patching Android Project for lang={LANG}, pkg={PKG_NAME}, version={version_name}...")
# ── 1. 图标文件 ──────────────────────────────────────────────────────────────
-# 将对应语言版本的 icon.png 复制到 Android drawable 资源目录
os.makedirs("android/app/src/main/res/drawable", exist_ok=True)
if os.path.exists(ICON_SRC):
shutil.copy(ICON_SRC, "android/app/src/main/res/drawable/icon.png")
@@ -59,20 +53,19 @@ manifest_path = "android/app/src/main/AndroidManifest.xml"
with open(manifest_path, "r", encoding="utf-8") as f:
manifest = f.read()
-# 替换默认图标引用为我们的 drawable/icon
+# 替换默认图标引用
manifest = manifest.replace("@mipmap/ic_launcher_round", "@drawable/icon")
manifest = manifest.replace("@mipmap/ic_launcher", "@drawable/icon")
manifest = manifest.replace("@drawable/icon_round", "@drawable/icon")
-# 添加 WAKE_LOCK 权限(屏保/常亮需要)
+# 添加 WAKE_LOCK 权限(屏保与视频常亮需要)
if "android.permission.WAKE_LOCK" not in manifest:
manifest = manifest.replace(
"",
' \n'
)
-# 注册 EmbyXDreamService(Android 系统屏保服务)
-# 修改规格:如需换 label 或 icon,修改下方 android:label / android:permission 即可
+# 注册系统屏保服务 EmbyXDreamService
service_block = """
@@ -247,7 +224,6 @@ with open(colors_path, "w", encoding="utf-8") as f:
print(" Created/Updated colors.xml")
# ── 8. 修改主题 (Themes/Styles) 适配 Google SplashScreen API ─────────────────
-# 增强鲁棒性:同时查找 themes.xml 和 styles.xml,处理多种可能的生成路径
target_files = [
"values/themes.xml",
"values-night/themes.xml",
@@ -262,25 +238,28 @@ for rel_path in target_files:
with open(full_path, "r", encoding="utf-8") as f:
content = f.read()
- # 使用更灵活的正则匹配 style 标签及其 parent
- # 兼容单引号/双引号/空格
- style_pattern = r'()'
+ m = re.search(style_block_pattern, content, flags=re.DOTALL)
+ if m:
+ start_tag = m.group(1)
+ inner_items = m.group(2)
- # 注入官方规范属性
- # 移除可能存在的旧 background 属性
- content = re.sub(r'- .*?
', '', content)
- content = re.sub(r'- .*?
', '', content)
- content = re.sub(r'- .*?
', '', content)
- content = re.sub(r'- .*?
', '', content)
+ start_tag = re.sub(r'parent="[^"]*"', 'parent="Theme.SplashScreen"', start_tag)
+
+ # 清理历史兼容属性,避免冲突
+ inner_items = re.sub(r'- .*?
', '', inner_items)
+ inner_items = re.sub(r'- .*?
', '', inner_items)
+ inner_items = re.sub(r'- .*?
', '', inner_items)
+ inner_items = re.sub(r'- .*?
', '', inner_items)
splash_items = """
- @color/black
- @drawable/icon
- @style/AppTheme.NoActionBar
"""
- content = content.replace('', f'{splash_items} ', 1)
+ new_block = f"{start_tag}{inner_items}{splash_items} "
+ content = content[:m.start()] + new_block + content[m.end():]
with open(full_path, "w", encoding="utf-8") as f:
f.write(content)
@@ -290,20 +269,17 @@ for rel_path in target_files:
if not splash_style_found:
print(" WARNING: AppTheme.NoActionBarLaunch style not found in any res files!")
-# ── 9. MainActivity 注入官方启动入口 ──────────────────────────────────────────
-# 确保在 super.onCreate 之前注入,且不重复注入
+# ── 9. MainActivity 注入启动页入口 ──────────────────────────────────────────
with open(main_activity_path, "r", encoding="utf-8") as f:
ma = f.read()
-# 确保导入语句存在
if "import androidx.core.splashscreen.SplashScreen;" not in ma:
ma = ma.replace("import android.os.Bundle;", "import android.os.Bundle;\nimport androidx.core.splashscreen.SplashScreen;")
if "SplashScreen.installSplashScreen(this)" not in ma:
- # 精准查找 super.onCreate 并在其上方插入
ma = ma.replace(
"super.onCreate(savedInstanceState);",
- "SplashScreen.installSplashScreen(this);\n super.onCreate(savedInstanceState);\n // 设置透明背景防止闪烁\n this.bridge.getWebView().setBackgroundColor(android.graphics.Color.BLACK);"
+ "SplashScreen.installSplashScreen(this);\n super.onCreate(savedInstanceState);\n // 设置透明底色防止切换回白屏闪烁\n this.bridge.getWebView().setBackgroundColor(android.graphics.Color.BLACK);"
)
with open(main_activity_path, "w", encoding="utf-8") as f: