Compare commits

2 Commits

Author SHA1 Message Date
f1084a5db9 release: 1.4.15 2026-06-10 21:52:43 +08:00
f0a21e33ec release: 1.4.14 2026-06-10 21:27:46 +08:00
10 changed files with 908 additions and 7 deletions

View File

@@ -1,3 +1,19 @@
# [1.4.15]
### 修复
* Release 默认仍关闭 `com.anythink.sdk:debugger-ui`,但不再把 `com.verbto.tools:util` 当作 DebugUI 附属库排除。
* `TopOn 配置` 页签新增独立的 `verbto util` 强制坐标配置,默认强制声明 `com.verbto.tools:util:1.1.3`;后续 Taku 修复后可取消勾选,交给宿主项目自动解析。
* Android Gradle 后处理在强制 util 时改写旧的 `com.verbto.tools:util:*` 声明,并只清理非目标版本的本地 util 产物。
# [1.4.14]
### 修复
* Release 默认不再通过 EDM4U 声明 `com.anythink.sdk:debugger-ui:+`,避免 `com.verbto.tools:util:1.0.6` 进入正式包触发 `anr_data.db` 降级崩溃。
* 新增 `TopOn 配置` 构建页签,可按构建配置启用 DebugUI关闭时构建后处理会从生成的 Gradle 工程剔除 `debugger-ui``verbto util`
* 启用 DebugUI 时同步声明 `com.verbto.tools:util:1.1.3` 作为诊断库兜底版本。
# [1.4.13]
### 修复

View File

@@ -0,0 +1,306 @@
#if UNITY_ANDROID
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor.Android;
using UnityEngine;
namespace Topon_Adapter.Editor
{
public sealed class ToponAndroidDebuggerDependencyPostProcessor : IPostGenerateGradleAndroidProject
{
private const string Tag = "[TopOn Build]";
private const string DebuggerDependency = "com.anythink.sdk:debugger-ui:+";
private const string DebuggerDependencyMarker = "com.anythink.sdk:debugger-ui";
private const string VerbtoDependencyMarker = "com.verbto.tools:util";
private const string DebuggerRepositoryUrl = "https://jfrog.anythinktech.com/artifactory/debugger";
private const string DepsStart = "// TopOn Debugger UI Dependencies Start";
private const string DepsEnd = "// TopOn Debugger UI Dependencies End";
private const string VerbtoDepsStart = "// TopOn Verbto Util Dependency Start";
private const string VerbtoDepsEnd = "// TopOn Verbto Util Dependency End";
private const string ReposStart = "// TopOn Debugger UI Repository Start";
private const string ReposEnd = "// TopOn Debugger UI Repository End";
public int callbackOrder => int.MaxValue;
public void OnPostGenerateGradleAndroidProject(string path)
{
var settings = ToponBuildSettingsStore.GetActiveForCurrentBuild();
try
{
ProcessGeneratedProject(path, settings);
}
finally
{
ToponBuildSettingsStore.ClearActiveBuildSettings();
}
}
public static void ProcessGeneratedProject(string path, ToponBuildSettings settings)
{
if (settings == null)
{
settings = ToponBuildSettingsStore.CreateDefault();
}
var gradleRoot = GetGradleRoot(path);
var gradleFiles = new[]
{
Path.Combine(path, "build.gradle"),
Path.Combine(gradleRoot, "launcher", "build.gradle"),
Path.Combine(gradleRoot, "build.gradle")
};
var forceVerbtoUtilVersion = settings.forceVerbtoUtilVersion;
var verbtoDependency = ToponBuildSettingsStore.GetVerbtoUtilDependency(settings);
foreach (var gradleFile in gradleFiles)
{
StripManagedDependenciesFromGradleFile(gradleFile, forceVerbtoUtilVersion);
}
StripManagedDependenciesFromGradleFile(Path.Combine(gradleRoot, "settings.gradle"), forceVerbtoUtilVersion);
if (settings.enableDebuggerUI || forceVerbtoUtilVersion)
{
InjectRepository(Path.Combine(gradleRoot, "settings.gradle"));
InjectRepository(Path.Combine(gradleRoot, "build.gradle"));
}
if (settings.enableDebuggerUI)
{
InjectDebuggerDependency(Path.Combine(path, "build.gradle"));
Debug.Log($"{Tag} DebugUI dependency enabled for this build.");
}
else
{
if (settings.stripResolvedDebuggerArtifacts)
{
RemoveGeneratedDebuggerArtifacts(gradleRoot);
}
Debug.Log($"{Tag} DebugUI dependency disabled for this build.");
}
if (forceVerbtoUtilVersion)
{
InjectVerbtoUtilDependency(Path.Combine(path, "build.gradle"), verbtoDependency);
RemoveGeneratedStaleVerbtoUtilArtifacts(gradleRoot, verbtoDependency);
Debug.Log($"{Tag} Verbto util dependency forced to {verbtoDependency}.");
}
else
{
Debug.Log($"{Tag} Verbto util dependency is not modified by TopOn build settings.");
}
}
private static string GetGradleRoot(string unityLibraryPath)
{
#if UNITY_2019_3_OR_NEWER
return Path.GetFullPath(Path.Combine(unityLibraryPath, ".."));
#else
return Path.GetFullPath(unityLibraryPath);
#endif
}
private static void StripManagedDependenciesFromGradleFile(string filePath, bool forceVerbtoUtilVersion)
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{
return;
}
var content = File.ReadAllText(filePath);
var original = content;
content = RemoveMarkedBlock(content, DepsStart, DepsEnd);
content = RemoveMarkedBlock(content, VerbtoDepsStart, VerbtoDepsEnd);
content = RemoveMarkedBlock(content, ReposStart, ReposEnd);
content = RemoveLinesContaining(content, DebuggerDependencyMarker);
if (forceVerbtoUtilVersion)
{
content = RemoveLinesContaining(content, VerbtoDependencyMarker);
}
if (!string.Equals(original, content, StringComparison.Ordinal))
{
File.WriteAllText(filePath, content);
}
}
private static void InjectDebuggerDependency(string buildGradlePath)
{
InjectDependencyBlock(buildGradlePath, DepsStart, DepsEnd, DebuggerDependency);
}
private static void InjectVerbtoUtilDependency(string buildGradlePath, string dependency)
{
InjectDependencyBlock(buildGradlePath, VerbtoDepsStart, VerbtoDepsEnd, dependency);
}
private static void InjectDependencyBlock(string buildGradlePath, string startMarker, string endMarker, string dependency)
{
if (!File.Exists(buildGradlePath))
{
Debug.LogWarning($"{Tag} build.gradle not found: {buildGradlePath}");
return;
}
if (string.IsNullOrWhiteSpace(dependency))
{
Debug.LogWarning($"{Tag} dependency is empty, skip injecting {startMarker}.");
return;
}
var content = File.ReadAllText(buildGradlePath);
var block = new StringBuilder();
block.AppendLine(startMarker);
block.AppendLine($" implementation '{dependency.Trim()}'");
block.AppendLine($" {endMarker}");
var pattern = new Regex(@"(dependencies\s*\{)");
if (!pattern.IsMatch(content))
{
Debug.LogWarning($"{Tag} dependencies block not found: {buildGradlePath}");
return;
}
content = pattern.Replace(content, match => match.Groups[1].Value + "\n " + block, 1);
File.WriteAllText(buildGradlePath, content);
}
private static void InjectRepository(string gradlePath)
{
if (!File.Exists(gradlePath))
{
return;
}
var content = File.ReadAllText(gradlePath);
if (content.Contains(DebuggerRepositoryUrl))
{
return;
}
var block = $"{ReposStart}\n maven {{ url '{DebuggerRepositoryUrl}' }}\n {ReposEnd}";
Regex pattern;
if (Path.GetFileName(gradlePath).Equals("settings.gradle", StringComparison.OrdinalIgnoreCase))
{
pattern = new Regex(@"(dependencyResolutionManagement\s*\{[\s\S]*?repositories\s*\{)");
}
else
{
block = $"{ReposStart}\n maven {{ url '{DebuggerRepositoryUrl}' }}\n {ReposEnd}";
pattern = new Regex(@"(repositories\s*\{)");
}
if (!pattern.IsMatch(content))
{
return;
}
content = pattern.Replace(content, match => match.Groups[1].Value + "\n " + block, 1);
File.WriteAllText(gradlePath, content);
}
private static void RemoveGeneratedDebuggerArtifacts(string gradleRoot)
{
if (string.IsNullOrWhiteSpace(gradleRoot) || !Directory.Exists(gradleRoot))
{
return;
}
var root = Path.GetFullPath(gradleRoot).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
foreach (var path in Directory.GetFiles(root, "*", SearchOption.AllDirectories))
{
if (!ToponBuildSettingsStore.IsDebuggerArtifactFileName(Path.GetFileName(path)))
{
continue;
}
var fullPath = Path.GetFullPath(path);
if (!fullPath.StartsWith(root, StringComparison.OrdinalIgnoreCase))
{
continue;
}
try
{
File.Delete(fullPath);
Debug.Log($"{Tag} Removed generated debugger artifact: {fullPath}");
}
catch (Exception exception)
{
Debug.LogWarning($"{Tag} Failed to remove generated debugger artifact: {exception.Message}");
}
}
}
private static void RemoveGeneratedStaleVerbtoUtilArtifacts(string gradleRoot, string expectedDependency)
{
if (string.IsNullOrWhiteSpace(gradleRoot) || !Directory.Exists(gradleRoot))
{
return;
}
var root = Path.GetFullPath(gradleRoot).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
foreach (var path in Directory.GetFiles(root, "*", SearchOption.AllDirectories))
{
var fileName = Path.GetFileName(path);
if (!ToponBuildSettingsStore.IsVerbtoUtilArtifactFileName(fileName) ||
ToponBuildSettingsStore.IsExpectedVerbtoUtilArtifactFileName(fileName, expectedDependency))
{
continue;
}
var fullPath = Path.GetFullPath(path);
if (!fullPath.StartsWith(root, StringComparison.OrdinalIgnoreCase))
{
continue;
}
try
{
File.Delete(fullPath);
Debug.Log($"{Tag} Removed stale verbto util artifact: {fullPath}");
}
catch (Exception exception)
{
Debug.LogWarning($"{Tag} Failed to remove stale verbto util artifact: {exception.Message}");
}
}
}
private static string RemoveMarkedBlock(string content, string startMarker, string endMarker)
{
var pattern = new Regex($@"\s*{Regex.Escape(startMarker)}[\s\S]*?{Regex.Escape(endMarker)}\s*");
return pattern.Replace(content, "\n");
}
private static string RemoveLinesContaining(string content, params string[] markers)
{
var lines = content.Replace("\r\n", "\n").Replace('\r', '\n').Split('\n');
var kept = new List<string>();
foreach (var line in lines)
{
var remove = false;
foreach (var marker in markers)
{
if (line.Contains(marker))
{
remove = true;
break;
}
}
if (!remove)
{
kept.Add(line);
}
}
return string.Join("\n", kept);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a10306d60f749a28af78c8c54738cd8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,389 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Topon_Adapter.Editor
{
[Serializable]
public sealed class ToponBuildSettings
{
public bool enableDebuggerUI = false;
public bool forceVerbtoUtilVersion = true;
public string verbtoUtilDependency = ToponBuildSettingsStore.DefaultVerbtoUtilDependency;
public bool stripResolvedDebuggerArtifacts = true;
}
internal static class ToponBuildSettingsStore
{
public const string DefaultVerbtoUtilDependency = "com.verbto.tools:util:1.1.3";
private const string ActiveBuildSessionKey = "Commercialization.Topon.ActiveBuildSettings";
private const string SettingsFileSuffix = "_topon_build_settings.json";
private const string BuildConfigsFolder = "BuildConfigs";
private const string DebuggerPackageMarker = "com.anythink.sdk:debugger-ui";
private const string VerbtoPackageMarker = "com.verbto.tools:util";
[Serializable]
private sealed class ActiveBuildSettings
{
public ToponBuildSettings settings;
public long utcTicks;
}
public static ToponBuildSettings CreateDefault()
{
return new ToponBuildSettings();
}
public static string GetVerbtoUtilDependency(ToponBuildSettings settings)
{
if (settings == null || string.IsNullOrWhiteSpace(settings.verbtoUtilDependency))
{
return DefaultVerbtoUtilDependency;
}
return settings.verbtoUtilDependency.Trim();
}
public static ToponBuildSettings LoadForProfileName(string profileName, string repositoryRoot)
{
var settings = CreateDefault();
var path = GetSettingsPath(profileName, repositoryRoot);
if (string.IsNullOrEmpty(path) || !File.Exists(path))
{
return settings;
}
try
{
JsonUtility.FromJsonOverwrite(File.ReadAllText(path), settings);
Normalize(settings);
}
catch (Exception exception)
{
Debug.LogWarning($"[TopOn Build] Failed to read build settings: {exception.Message}");
}
return settings;
}
public static void SaveForProfileName(string profileName, string repositoryRoot, ToponBuildSettings settings)
{
if (settings == null)
{
settings = CreateDefault();
}
else
{
Normalize(settings);
}
var path = GetSettingsPath(profileName, repositoryRoot);
if (string.IsNullOrEmpty(path))
{
return;
}
try
{
var directory = Path.GetDirectoryName(path);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
File.WriteAllText(path, JsonUtility.ToJson(settings, true));
}
catch (Exception exception)
{
Debug.LogWarning($"[TopOn Build] Failed to save build settings: {exception.Message}");
}
}
public static void SetActiveForCurrentBuild(ToponBuildSettings settings)
{
var activeSettings = new ActiveBuildSettings
{
settings = Clone(settings),
utcTicks = DateTime.UtcNow.Ticks
};
SessionState.SetString(ActiveBuildSessionKey, JsonUtility.ToJson(activeSettings));
}
public static ToponBuildSettings GetActiveForCurrentBuild()
{
var json = SessionState.GetString(ActiveBuildSessionKey, string.Empty);
if (string.IsNullOrWhiteSpace(json))
{
return CreateDefault();
}
try
{
var activeSettings = JsonUtility.FromJson<ActiveBuildSettings>(json);
if (activeSettings == null || activeSettings.settings == null)
{
return CreateDefault();
}
Normalize(activeSettings.settings);
var activatedAt = new DateTime(activeSettings.utcTicks, DateTimeKind.Utc);
if (DateTime.UtcNow - activatedAt > TimeSpan.FromHours(6))
{
ClearActiveBuildSettings();
return CreateDefault();
}
return Clone(activeSettings.settings);
}
catch (Exception exception)
{
Debug.LogWarning($"[TopOn Build] Failed to read active build settings: {exception.Message}");
return CreateDefault();
}
}
public static void ClearActiveBuildSettings()
{
SessionState.EraseString(ActiveBuildSessionKey);
}
public static bool HasStaleDebuggerResolverOutput(string repositoryRoot)
{
foreach (var path in GetResolverOutputPaths(repositoryRoot))
{
if (!File.Exists(path))
{
continue;
}
var content = File.ReadAllText(path);
if (content.Contains(DebuggerPackageMarker))
{
return true;
}
}
return false;
}
public static bool HasUnforcedVerbtoUtilOutput(string repositoryRoot, string expectedDependency)
{
expectedDependency = NormalizeDependency(expectedDependency);
foreach (var path in GetResolverOutputPaths(repositoryRoot))
{
if (!File.Exists(path))
{
continue;
}
var content = File.ReadAllText(path);
if (content.Contains(VerbtoPackageMarker) && !content.Contains(expectedDependency))
{
return true;
}
}
foreach (var path in FindResolvedVerbtoUtilArtifacts(repositoryRoot))
{
if (!IsExpectedVerbtoUtilArtifactFileName(Path.GetFileName(path), expectedDependency))
{
return true;
}
}
return false;
}
public static IReadOnlyList<string> FindResolvedDebuggerArtifacts(string repositoryRoot)
{
var result = new List<string>();
var root = ResolveRepositoryRoot(repositoryRoot);
if (string.IsNullOrEmpty(root))
{
return result;
}
var androidPluginPath = Path.Combine(root, "Assets", "Plugins", "Android");
if (!Directory.Exists(androidPluginPath))
{
return result;
}
foreach (var path in Directory.GetFiles(androidPluginPath, "*", SearchOption.AllDirectories))
{
if (IsDebuggerArtifactFileName(Path.GetFileName(path)))
{
result.Add(path);
}
}
return result;
}
public static IReadOnlyList<string> FindResolvedVerbtoUtilArtifacts(string repositoryRoot)
{
var result = new List<string>();
var root = ResolveRepositoryRoot(repositoryRoot);
if (string.IsNullOrEmpty(root))
{
return result;
}
var androidPluginPath = Path.Combine(root, "Assets", "Plugins", "Android");
if (!Directory.Exists(androidPluginPath))
{
return result;
}
foreach (var path in Directory.GetFiles(androidPluginPath, "*", SearchOption.AllDirectories))
{
if (IsVerbtoUtilArtifactFileName(Path.GetFileName(path)))
{
result.Add(path);
}
}
return result;
}
internal static bool IsDebuggerArtifactFileName(string fileName)
{
if (string.IsNullOrEmpty(fileName))
{
return false;
}
return fileName.StartsWith("com.anythink.sdk.debugger-ui-", StringComparison.OrdinalIgnoreCase);
}
internal static bool IsVerbtoUtilArtifactFileName(string fileName)
{
if (string.IsNullOrEmpty(fileName))
{
return false;
}
return fileName.StartsWith("com.verbto.tools.util-", StringComparison.OrdinalIgnoreCase);
}
internal static bool IsExpectedVerbtoUtilArtifactFileName(string fileName, string expectedDependency)
{
if (!IsVerbtoUtilArtifactFileName(fileName))
{
return false;
}
var version = GetVersionFromDependency(expectedDependency);
if (string.IsNullOrEmpty(version))
{
return false;
}
return fileName.StartsWith($"com.verbto.tools.util-{version}", StringComparison.OrdinalIgnoreCase);
}
private static ToponBuildSettings Clone(ToponBuildSettings settings)
{
if (settings == null)
{
return CreateDefault();
}
return new ToponBuildSettings
{
enableDebuggerUI = settings.enableDebuggerUI,
forceVerbtoUtilVersion = settings.forceVerbtoUtilVersion,
verbtoUtilDependency = GetVerbtoUtilDependency(settings),
stripResolvedDebuggerArtifacts = settings.stripResolvedDebuggerArtifacts
};
}
private static void Normalize(ToponBuildSettings settings)
{
if (settings == null)
{
return;
}
settings.verbtoUtilDependency = NormalizeDependency(settings.verbtoUtilDependency);
}
private static string NormalizeDependency(string dependency)
{
if (string.IsNullOrWhiteSpace(dependency))
{
return DefaultVerbtoUtilDependency;
}
return dependency.Trim();
}
private static string GetVersionFromDependency(string dependency)
{
dependency = NormalizeDependency(dependency);
var parts = dependency.Split(':');
return parts.Length >= 3 ? parts[parts.Length - 1] : string.Empty;
}
private static IEnumerable<string> GetResolverOutputPaths(string repositoryRoot)
{
var root = ResolveRepositoryRoot(repositoryRoot);
if (string.IsNullOrEmpty(root))
{
yield break;
}
yield return Path.Combine(root, "ProjectSettings", "AndroidResolverDependencies.xml");
yield return Path.Combine(root, "Assets", "Plugins", "Android", "mainTemplate.gradle");
yield return Path.Combine(root, "Assets", "Plugins", "Android", "mainTemplate.gradle.backup");
yield return Path.Combine(root, "Assets", "Plugins", "Android", "settingsTemplate.gradle");
}
private static string GetSettingsPath(string profileName, string repositoryRoot)
{
var root = ResolveRepositoryRoot(repositoryRoot);
if (string.IsNullOrEmpty(root))
{
return string.Empty;
}
return Path.Combine(root, BuildConfigsFolder, $"{SanitizeProfileName(profileName)}{SettingsFileSuffix}");
}
private static string ResolveRepositoryRoot(string repositoryRoot)
{
if (!string.IsNullOrWhiteSpace(repositoryRoot))
{
return Path.GetFullPath(repositoryRoot);
}
var dataPath = Application.dataPath;
var parent = Directory.GetParent(dataPath);
return parent == null ? string.Empty : parent.FullName;
}
private static string SanitizeProfileName(string profileName)
{
if (string.IsNullOrWhiteSpace(profileName))
{
return "default";
}
var invalidChars = Path.GetInvalidFileNameChars();
var chars = profileName.ToCharArray();
for (var i = 0; i < chars.Length; i++)
{
if (Array.IndexOf(invalidChars, chars[i]) >= 0)
{
chars[i] = '_';
}
}
return new string(chars);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 47b497e660b24e94b8e09d600f9c0fb8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,160 @@
using UnityEditor;
using UnityEngine;
namespace Topon_Adapter.Editor
{
[InitializeOnLoad]
internal static class ToponBuildWindowExtensionBootstrap
{
static ToponBuildWindowExtensionBootstrap()
{
BuildWindowExtensionRegistry.Register(new ToponBuildWindowExtension());
}
}
public sealed class ToponBuildWindowExtension : IBuildWindowExtension
{
public string Id => "com.commercialization.topon.build.settings";
public string DisplayName => "TopOn 配置";
public int Order => 80;
public void DrawSection(BuildWindowExtensionContext context)
{
var profile = context?.profile;
if (profile == null)
{
EditorGUILayout.HelpBox("当前没有构建配置。", MessageType.Info);
return;
}
var settings = ToponBuildSettingsStore.LoadForProfileName(profile.profileName, context.repositoryRoot);
EditorGUILayout.LabelField("TopOn Android 调试工具", EditorStyles.boldLabel);
EditorGUILayout.HelpBox(
"正式 release 默认关闭 DebugUI。verbto util 独立控制,默认强制指定到 1.1.3,避免回落到存在数据库降级风险的旧版本。",
MessageType.Info);
EditorGUI.BeginChangeCheck();
settings.enableDebuggerUI = EditorGUILayout.Toggle(
new GUIContent("启用 DebugUI 依赖", "仅用于开发/测试包;正式 release 应保持关闭。"),
settings.enableDebuggerUI);
settings.forceVerbtoUtilVersion = EditorGUILayout.Toggle(
new GUIContent("强制指定 verbto util", "无论 DebugUI 是否启用,都声明下方的 com.verbto.tools:util 坐标;取消勾选后交给 Taku/宿主项目自动处理。"),
settings.forceVerbtoUtilVersion);
using (new EditorGUI.DisabledScope(!settings.forceVerbtoUtilVersion))
{
settings.verbtoUtilDependency = EditorGUILayout.TextField(
new GUIContent("util 坐标", "默认 com.verbto.tools:util:1.1.3Taku 修复后可取消强制指定。"),
ToponBuildSettingsStore.GetVerbtoUtilDependency(settings));
}
settings.stripResolvedDebuggerArtifacts = EditorGUILayout.Toggle(
new GUIContent("禁用时剔除 DebugUI 旧产物", "关闭 DebugUI 时,从生成的 Gradle 工程中删除旧 Resolver 带入的 debugger-ui AAR不会把 verbto util 当作 DebugUI 一起剔除。"),
settings.stripResolvedDebuggerArtifacts);
if (EditorGUI.EndChangeCheck())
{
ToponBuildSettingsStore.SaveForProfileName(profile.profileName, context.repositoryRoot, settings);
}
EditorGUILayout.Space(6);
if (settings.enableDebuggerUI)
{
EditorGUILayout.HelpBox("当前配置会把 TopOn DebugUI 打进 Android 构建;请不要用于正式 release。", MessageType.Warning);
}
else
{
EditorGUILayout.HelpBox("当前配置不会打包 TopOn DebugUI。", MessageType.None);
}
if (settings.forceVerbtoUtilVersion)
{
EditorGUILayout.HelpBox($"当前会强制声明 {ToponBuildSettingsStore.GetVerbtoUtilDependency(settings)}。", MessageType.None);
}
else
{
EditorGUILayout.HelpBox("当前不会干预 verbto util 版本,由 Taku/宿主项目依赖解析决定。", MessageType.Info);
}
DrawResolverStatus(context);
}
public BuildWindowExtensionReport Preflight(BuildWindowExtensionContext context)
{
var profile = context?.profile;
if (profile == null)
{
return BuildWindowExtensionReport.Pass();
}
var settings = ToponBuildSettingsStore.LoadForProfileName(profile.profileName, context.repositoryRoot);
ToponBuildSettingsStore.SetActiveForCurrentBuild(settings);
var report = BuildWindowExtensionReport.Pass();
if (settings.enableDebuggerUI)
{
report.AddMessage("TopOn DebugUI 已启用。");
if (!profile.isDevelopment)
{
report.AddWarning("当前不是 Development Build请确认该配置不是正式 release。");
}
}
else
{
report.AddMessage("TopOn DebugUI 已关闭,构建产物不会打包 debugger-ui。");
}
if (!settings.enableDebuggerUI && ToponBuildSettingsStore.HasStaleDebuggerResolverOutput(context.repositoryRoot))
{
report.AddWarning("检测到旧 Resolver 输出仍包含 TopOn DebugUI本次构建会在生成 Gradle 后剔除,建议后续重新 Resolve。");
}
if (settings.forceVerbtoUtilVersion)
{
var dependency = ToponBuildSettingsStore.GetVerbtoUtilDependency(settings);
report.AddMessage($"TopOn 将强制声明 {dependency}。");
if (ToponBuildSettingsStore.HasUnforcedVerbtoUtilOutput(context.repositoryRoot, dependency))
{
report.AddWarning($"检测到旧 Resolver 输出或本地 AAR 可能不是 {dependency};本次构建会在生成 Gradle 后改写为强制版本。");
}
}
else
{
report.AddMessage("TopOn 不干预 verbto util 版本。");
}
return report;
}
public BuildWindowExtensionReport PostBuild(BuildWindowExtensionContext context)
{
return BuildWindowExtensionReport.Pass();
}
private static void DrawResolverStatus(BuildWindowExtensionContext context)
{
var profile = context?.profile;
var settings = profile == null
? ToponBuildSettingsStore.CreateDefault()
: ToponBuildSettingsStore.LoadForProfileName(profile.profileName, context.repositoryRoot);
var dependency = ToponBuildSettingsStore.GetVerbtoUtilDependency(settings);
var hasStaleDebuggerOutput = ToponBuildSettingsStore.HasStaleDebuggerResolverOutput(context.repositoryRoot);
var hasUnforcedUtilOutput = ToponBuildSettingsStore.HasUnforcedVerbtoUtilOutput(context.repositoryRoot, dependency);
var debuggerArtifacts = ToponBuildSettingsStore.FindResolvedDebuggerArtifacts(context.repositoryRoot);
var utilArtifacts = ToponBuildSettingsStore.FindResolvedVerbtoUtilArtifacts(context.repositoryRoot);
EditorGUILayout.Space(6);
EditorGUILayout.LabelField("本地依赖状态", EditorStyles.boldLabel);
EditorGUILayout.LabelField("旧 DebugUI 输出", hasStaleDebuggerOutput ? "检测到 debugger-ui" : "未检测到");
EditorGUILayout.LabelField("DebugUI AAR/JAR", debuggerArtifacts.Count == 0 ? "未检测到" : $"{debuggerArtifacts.Count} 个");
EditorGUILayout.LabelField("verbto util 强制", settings.forceVerbtoUtilVersion ? dependency : "自动/不干预");
EditorGUILayout.LabelField("verbto util 本地产物", utilArtifacts.Count == 0 ? "未检测到" : $"{utilArtifacts.Count} 个");
if (settings.forceVerbtoUtilVersion && hasUnforcedUtilOutput)
{
EditorGUILayout.HelpBox("检测到本地/Resolver 中存在非强制版本的 verbto utilAndroid Gradle 工程生成后会改写依赖,并清理旧版本本地产物。", MessageType.Warning);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59588e94a9074edba04bd828d233dd25
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,9 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<dependencies>
<androidPackages>
<repositories>
<repository>https://jfrog.anythinktech.com/artifactory/debugger</repository>
</repositories>
<androidPackage spec="com.anythink.sdk:debugger-ui:+"/>
<!-- Debugger UI is injected by Topon build settings only when explicitly enabled. -->
</androidPackages>
</dependencies>
</dependencies>

View File

@@ -5,7 +5,7 @@
"GUID:8a3d1447e0a3bdf4fa07035516da8b62",
"GUID:3198a86b02613024e960e3d04a9638cd",
"GUID:483a01338fa974b4498cd71261d6e8b9",
"GUID:87bccae0237fd4a41ac446d6636f95e0"
"GUID:24277cc3923ff5f49b48e1a274d4a02b"
],
"includePlatforms": [
"Editor"

View File

@@ -2,7 +2,7 @@
"name": "com.commercialization.topon",
"displayName": "Commercialization.topon",
"description": "基于topon的广告sdk封装依赖基础商业化模块",
"version": "1.4.13",
"version": "1.4.15",
"unity": "2021.1",
"license": "MIT",
"repository": {