using System.Collections.Generic; using Sirenix.OdinInspector; using Sirenix.OdinInspector.Editor; using UnityEditor; using UnityEditor.Build.Reporting; using UnityEngine; namespace Stary.Evo.Editor { public class BuildApkWindow : OdinEditorWindow { public static OdinEditorWindow window; [MenuItem("Evo/Dev/Apk打包工具", false, 4)] static void ShowWindows() { window = (BuildApkWindow)EditorWindow.GetWindow(typeof(BuildApkWindow)); window.maxSize = new Vector2(400, 500); window.Show(); } protected override void Initialize() { base.Initialize(); buildApkLocalEntity = new BuildApkEntity(() => { BuildAndroid(false); }, null); buildApkServerEntity = new BuildApkEntity(null, null); buildApkWatermarkEntity = new BuildApkEntity(() => { BuildAndroid(true); }, null); } [EnumToggleButtons, HideLabel] public DeviceType deviceType; [HideLabel] [Title("包裹列表", titleAlignment: TitleAlignments.Centered)] [ValueDropdown("GetBuildPackageNames")] public string selectedPackageNames; [BoxGroup("Build(清空打包缓存)", centerLabel: true, order: 1)] [Button("清空打包缓存")] void OnClearCache() { // 清理Library缓存目录 // 使用System.IO删除 // try { // System.IO.Directory.Delete(Application.dataPath + "/../Library/AssetImportState", true); // Debug.Log("成功删除AssetImportState"); // } catch (System.Exception e) { // Debug.LogError($"删除失败: {e.Message}"); // } // 使用System.IO删除 try { System.IO.Directory.Delete(Application.dataPath + "/../Library/BuildCache", true); Debug.Log("成功删除BuildCache"); } catch (System.Exception e) { Debug.LogError($"删除失败: {e.Message}"); } // 使用System.IO删除 try { System.IO.Directory.Delete(Application.dataPath + "/../Library/ScriptAssemblies", true); Debug.Log("成功删除ScriptAssemblies"); } catch (System.Exception e) { Debug.LogError($"删除失败: {e.Message}"); } AssetDatabase.Refresh(); EditorUtility.DisplayDialog("缓存清理", "已成功清除所有打包缓存文件", "确定"); } [BoxGroup("Build(普通包\\服务器本地包)", centerLabel: true, order: 2), HideLabel] public BuildApkEntity buildApkLocalEntity; [BoxGroup("Build(服务器热更包)", centerLabel: true, order: 3), HideLabel] public BuildApkEntity buildApkServerEntity; [BoxGroup("Build(水印包)", centerLabel: true, order: 4), HideLabel] public BuildApkEntity buildApkWatermarkEntity; public void BuildAndroid(bool isWatermark) { HotfixMainResDomain hotfixMainResDomain = Resources.Load("HotfixMainResDomain"); if (hotfixMainResDomain == null) { Debug.LogError("HotfixMainResDomain 资源在Resources下不存在,请检查!"); return; } ChangePlayerSchema.SetPlayerMode(PLayerMode.HOST_PLAYMODE); string packageName = ""; // 检测包名格式 if (!IsValidPackageName(selectedPackageNames)) { // 不是有效包名格式,添加前缀 com.xosmo. packageName = "com.xosmo." + selectedPackageNames; // 设置包名和项目名 PlayerSettings.productName = selectedPackageNames; PlayerSettings.applicationIdentifier = packageName; } else { // 分割包名字符串 string[] segments = selectedPackageNames.Split('.'); // 返回最后一个部分 packageName = segments[segments.Length - 1]; PlayerSettings.productName = packageName; PlayerSettings.applicationIdentifier = selectedPackageNames; } string[] scenelist = default; if (isWatermark) { scenelist = new[] { hotfixMainResDomain.projectInfo.loadingScenePath, $"Assets/Main/main_{deviceType.ToString()}.unity" }; PlayerSettings.productName += "_watermark"; PlayerSettings.applicationIdentifier += "_watermark"; Sprite xosmo = Resources.Load("logo"); PlayerSettings.virtualRealitySplashScreen = xosmo.texture; PlayerSettings.SplashScreen.showUnityLogo = false; PlayerSettings.SplashScreen.logos = new[] { PlayerSettings.SplashScreenLogo.Create(3f, xosmo), }; } else { scenelist = new[] { $"Assets/Main/main_{deviceType.ToString()}.unity" }; PlayerSettings.virtualRealitySplashScreen = null; PlayerSettings.SplashScreen.showUnityLogo = false; PlayerSettings.SplashScreen.logos = null; } // 配置构建选项 BuildPlayerOptions buildOptions = new BuildPlayerOptions { scenes = scenelist, locationPathName = $"Builds/Android/{PlayerSettings.productName}.apk", target = BuildTarget.Android, options = BuildOptions.None }; // 执行打包 var report = BuildPipeline.BuildPlayer(buildOptions); BuildSummary summary = report.summary; if (summary.result == BuildResult.Succeeded) { Debug.Log("Build succeeded: " + summary.totalSize + " bytes"); } if (summary.result == BuildResult.Failed) { Debug.LogError("Build failed"); } } public enum DeviceType { Xreal, Rokid } /// /// 检测当前所有包裹 /// /// private List GetBuildPackageNames() { List result = new List(); foreach (var name in CreatAssetWindow.GetCreatDomainAllName()) { result.Add(name); } if (selectedPackageNames.IsNullOrEmpty()) { if (result.Count > 0) { selectedPackageNames = result[0]; } else { selectedPackageNames = ""; } } return result; } /// /// 检测字符串是否是有效的包名格式 /// /// 要检测的字符串 /// 是否是有效的包名格式 private bool IsValidPackageName(string packageName) { if (string.IsNullOrEmpty(packageName)) return false; // 包名只能包含小写字母、数字和点 foreach (char c in packageName) { if (!char.IsLower(c) && !char.IsDigit(c) && c != '.') return false; } // 不能以点开头或结尾 if (packageName.StartsWith(".") || packageName.EndsWith(".")) return false; // 不能包含连续的点 if (packageName.Contains("..")) return false; // 至少包含一个点 if (!packageName.Contains(".")) return false; return true; } } }