# Commercialization.topon 维护规范 ## 1. 仓库定位 本仓库是 `Topon` 平台商业化实现层的 Unity 源码工程,不是业务项目。 它承担两类职责: 1. 作为 `com.commercialization.topon` 的源码发布仓库。 2. 作为本地联调和验证工程,用来测试该实现层与商业化抽象层的组合效果。 当前设计是: - `com.foldcc.cc-framework.commercialization` 提供抽象层。 - `com.commercialization.topon` 提供 `Topon/AnyThink` 的具体实现层。 - 业务项目通过 `商业化抽象层 + 平台实现层` 的组合快速接入广告能力。 ## 2. 发布规范 ### 2.1 发布源 真正发布到 UPM 的内容只有 `Assets` 子树。 - 包定义文件:`Assets/package.json` - 发布脚本:`Update Upm.bat` 发布脚本做的事情: 1. 从 `Assets` 子树切出 `upm` 分支。 2. 强推 `upm` 分支。 3. 按 `Assets/package.json` 里的 `version` 创建 tag。 也就是说: - 根目录的 `Packages`、`ProjectSettings`、`Library` 都不是包内容。 - 维护包时,必须把所有真正要发布的代码和资源都放在 `Assets` 下。 ### 2.2 版本约定 - 包版本号以 `Assets/package.json` 为准。 - 业务项目引用的也是 `Assets/package.json` 对应 tag。 - 本地工程里的 `Packages/manifest.json` 只用于当前源码工程联调,不参与发布。 - 当前发布版本: - `com.commercialization.topon`:`1.4.9` - `com.foldcc.cc-framework.commercialization`:`1.0.14` ### 2.3 发布前检查 发布前至少确认以下事项: 1. `Assets/package.json` 的版本号已更新。 2. `Assets/package.json` 里的核心依赖版本与本地验证环境一致。 3. 所有本次升级需要发布的内容都在 `Assets` 下。 4. `Update Upm.bat` 执行前,工作区已整理干净。 5. Android 业务项目的 `minSdkVersion` 已不低于 `24`。 ## 3. 目录职责 ### 3.1 `Assets/Topon_Adapter` 本目录是平台具体实现层,负责把抽象广告接口绑定到 Topon。 - `Runtime/Scripts` - `ToponAdController.cs`:实现 `IAdController` - `AwardVideoPlayer.cs`:激励视频实现 - `InteractionPlayer.cs`:插屏实现 - `ADListenerAggregator.cs`:新版 SDK 回调桥接 - `Editor` - `AD_BuildAndroidProcess.cs`:Android 导出后处理 - `WXDependencies.xml`:微信 Android 依赖 - `ToponTestDependencies.xml`:调试依赖 - `alex_tt_file_path.xml` / `anythink_bk_tt_file_path.xml`:文件路径配置 ### 3.2 `Assets/AnyThinkPlugin` 本目录是官方 AnyThink Unity 插件及其二次适配层。 - `AnyThinkAds` - 官方运行时 API、平台桥、AAR、iOS 桥代码 - `Script/IntegrationManager` - SDK 管理器 - 本地安装状态记录 - 版本下载和热修复 - `Script/Editor` - Android/iOS 构建期后处理 ### 3.3 `Assets/Plugins/Android` 本目录保存额外 Android 资源和补充模块。 - `gromoreRes.androidlib`:额外 Android 资源载体 - 多个 `*.DISABLED` 模板文件:当前不作为主流程依赖,保留给手工切换或历史兼容 ### 3.4 `Assets/ExternalDependencyManager` EDM4U 依赖解析器,负责消费 `Dependencies.xml` 并拉取 Android/iOS 依赖。 ## 4. 运行时架构 运行时链路如下: `业务项目 -> 商业化抽象层 -> Topon_Adapter -> AnyThink 官方 SDK -> Android/iOS 原生桥` 职责划分如下: - 抽象层 - `ADManager`:统一初始化、异步播放、超时、遮罩、事件流 - `IAdController`:平台实现层入口 - `ADPlayer`:广告位抽象 - `AsyncAdPlayer`:广告加载与播放调度器 - Topon 实现层 - `ToponAdController`:初始化 Topon SDK,创建各广告位 Player - `AwardVideoPlayer` / `InteractionPlayer`:广告位具体实现 - 官方 SDK - `ATSDKAPI`:统一 SDK 能力入口 - `ATAdsClientFactory`:按平台创建实际 Client - `Platform/Android` 和 `Platform/iOS`:桥接到原生层 当前已明确实现的广告类型: - `AwardVideo` - `Interaction` 当前保留但未落地完整实现的类型: - `Splash` ## 5. 升级 SDK 时不能丢的本地改造 这是本仓库最重要的部分。升级官方 SDK 时,不能直接全量覆盖,否则会把包管理能力和构建补丁一起冲掉。 ### 5.1 动态路径读取规范 本仓库已经把关键文件路径从固定 `Assets/...` 改为动态定位。 必须保留以下思路: 1. 通过 `AssetDatabase.FindAssets` 找到脚本自身位置。 2. 基于脚本位置反推插件根目录。 3. 所有插件配置、资源、构建拷贝都从动态根目录计算。 当前核心实现点: - `ATConfig.RootPath` - `ATConfig.GetScriptsPath(...)` - `ATPostProcessBuildAndroid.GetScriptsPath(...)` - `AD_BuildAndroidProcess.GetScriptsPath(...)` 这样做的目的: - 不依赖固定 `Assets/AnyThinkPlugin/...` 绝对相对路径。 - 为后续包管理器接入保留空间。 - 允许实现层以非侵入方式挂接到其他项目。 结论: - 后续升级 AnyThink SDK 时,不允许重新引入硬编码 `Assets/...` 路径作为主逻辑。 - 如果官方新版本新增了读取配置文件、复制模板文件、写本地状态文件的逻辑,必须按当前动态定位方式重新改造。 ### 5.2 本地安装状态与配置落盘 本仓库通过 `ATConfig` 在插件目录下维护本地状态: - `plugin_setting_data.json` - `plugin_hot_fix_data.json` - 各 network 的 `network_data.json` 这些文件用于: - 记录当前国家区服选择 - 记录 Android/iOS 已安装 core 版本 - 记录各 mediation network 当前安装版本 - 记录 AdMob app id - 记录 AndroidX 选择 - 记录热修复版本 升级时不要删除这套机制。 ### 5.3 新版回调桥接规范 `Topon_Adapter` 里新增了 `ADListenerAggregator`,作用是把新版 event 风格回调重新桥接回旧 listener 逻辑。 背景: - 老代码依赖 `listener` 风格回调。 - 新版 SDK 已不再适合直接 `client.setListener(this)`。 因此: - `AwardVideoPlayer` 必须通过 `ADListenerAggregator.BindAwardVideoListener(...)` 绑定。 - `InteractionPlayer` 必须通过 `ADListenerAggregator.BindInterstitialAdListener(...)` 绑定。 - 奖励视频链路的旧 listener 回调必须继续完整桥接到 Unity 主线程,不能直接在 SDK 子线程里触发业务逻辑。 如果升级后官方再次调整回调模型,优先延续这层桥接,不要直接把抽象层改成强耦合官方回调。 ### 5.4 `ToponAdController` 配置入口规范 `ToponAdController` 现在支持两类初始化输入: 1. 兼容旧参数: - `args[0]`:`channel` - `args[1]`:`debug` 2. 推荐新参数: - 通过 `ADConfig.CommonKeyValues` - 或额外传入 `ToponControllerOptions` - 或额外传入 `IDictionary` 当前已支持的配置 key: - `topon.channel` - `topon.sub_channel` - `topon.debug` - `topon.debugger_key` - `topon.auto_open_debugger_ui` - `topon.sdk_area` - `topon.longitude` - `topon.latitude` - `topon.exclude_bundle_ids` - `topon.rewarded_exclude_ad_source_ids` - `topon.query_area_on_init` - `topon.custom_map.` - `topon.rewarded_custom_data.` - `topon.rewarded_auto_load` - `topon.rewarded_prewarm_on_init` - `topon.rewarded_max_load_attempts` - `topon.rewarded_load_retry_delay_ms` - `topon.interstitial_auto_load` - `topon.interstitial_prewarm_on_init` - `topon.interstitial_max_load_attempts` - `topon.interstitial_load_retry_delay_ms` - `topon.local_strategy_asset_path` 说明: - `topon.debug=true` 现在只打开 SDK 调试日志。 - 官方 DebugUI 默认不再自动弹出,如需使用,手动调用或在样例面板点击 `Open DebugUI`。 - `topon.exclude_bundle_ids` - 用于全局排除指定广告主 bundle id - `topon.rewarded_exclude_ad_source_ids` - 用于当前激励视频广告位排除指定广告源 - `topon.query_area_on_init` - 初始化后主动查询 SDK 当前区域 - 结果会回写到 `ToponAdController.LastDetectedArea` - `topon.custom_map.` - 对应 `ATSDKAPI.initCustomMap(...)` - 注意先设置 custom map,再设置 channel/sub_channel - `topon.rewarded_custom_data.` - 对应 `ATSDKAPI.setCustomDataForPlacementID(...)` - 当前默认应用到激励视频广告位 维护约束: - 当前 IAA 业务主链路以激励视频为主,新功能配置优先围绕 `AwardVideo` 广告位设计。 - 如果后续要补插屏、开屏、原生等广告位的同类配置,优先扩展 `ToponControllerOptions`,不要把 SDK 细节直接散落到业务层。 ### 5.5 `AnyThinkSDKEditor` 编辑器开关规范 `AnyThinkPlugin/Script/IntegrationManager/Editor` 这套“SDK Manager / 远端版本检查 / hotfix 检查 / 远端 unitypackage 导入”能力,当前应视为维护工具,而不是业务项目默认能力。 当前约定: - 只有在定义了 `AnyThinkSDKEditor` 宏时,才允许显示 `AnyThink` 菜单并启用联网检查。 - 未定义 `AnyThinkSDKEditor` 时: - 不显示 `AnyThink/SDK Manager` - 不执行 SDK 版本拉取 - 不执行 hotfix 检查 - 不执行远端 unitypackage 下载与导入 这样做的目的: - 避免业务项目通过包管理接入后,仍然保留官方集成管理器的远端更新入口。 - 降低编辑器侧供应链风险。 - 把 SDK 升级动作收敛到维护工程,而不是下游接入工程。 ## 6. Android 构建期自定义规范 Android 的构建后处理分为两层: 1. `Topon_Adapter` 平台专项后处理 2. `AnyThinkPlugin` 通用 SDK 后处理 ### 6.1 `Topon_Adapter/Editor/AD_BuildAndroidProcess.cs` 主要职责: - 将 `alex_tt_file_path.xml` 和 `anythink_bk_tt_file_path.xml` 复制到导出的 Gradle 工程 - 将 `UnityPlayerActivity` 的 `launchMode` 改为 `singleTop` - 在 `manifest` 中增加微信 `queries/package` - 重建 `.wxapi.WXEntryActivity` - 注入 `com.bytedance.sdk.openadsdk.TTFileProvider` - 在 `launcher` application 节点设置 - `android:allowBackup="false"` - `tools:replace="android:allowBackup"` 升级时这些点必须逐项核对。 ### 6.2 `AnyThinkPlugin/Script/Editor/ATPostProcessBuildAndroid.cs` 主要职责: - 处理 `gradle.properties` - `android.useAndroidX` - `android.enableJetifier` - `android.enableDexingArtifactTransform=false` - 按 AdMob 是否安装,动态补 `com.google.android.gms.ads.APPLICATION_ID` - 中国区时补 `android:networkSecurityConfig` - 增加 `org.apache.http.legacy` - 调用 `ATProcessBuildGradleAndroid.processBuildGradle(path)` ### 6.3 `AnyThinkPlugin/Script/Editor/ATProcessBuildGradleAndroid.cs` 当前生效职责: - 海外模式下注入 `packagingOptions` - `merge 'META-INF/com.android.tools/proguard/coroutines.pro'` - `exclude 'META-INF/*.kotlin_module'` 当前文件里还有历史保留逻辑: - `handleNetworkResMerge(...)` - `callGradleTask(...)` 其中存在旧的固定路径残留,不是当前主流程依赖。若后续重新启用,必须先改造成动态路径。 ### 6.4 Android 依赖补充 除了官方插件自带依赖,本仓库还额外声明了: - 微信依赖:`WXDependencies.xml` - Topon 调试依赖:`ToponTestDependencies.xml` 升级后如果官方依赖结构变化,需要同步确认这些补充依赖是否仍然必要。 ## 7. iOS 构建期自定义规范 `AnyThinkPlugin/Script/Editor/ATPostProcessBuildiOS.cs` 负责 iOS 导出后的补丁。 当前关键职责: - 嵌入特定动态 framework - 添加 bundle 资源 - 关闭 bitcode - 开启 Objective-C exceptions - 按 AdMob 是否安装补充 iOS 侧 Google app id 升级 iOS SDK 时,至少要检查: 1. 需要 embed 的 framework 路径是否变化。 2. 需要附带的 bundle 是否变化。 3. plist 补丁是否仍然适用。 ## 8. 升级官方 SDK 的推荐流程 建议按以下顺序执行,不要直接整目录替换后发布。 ### 8.1 准备阶段 1. 记录当前包版本和 core 依赖版本。 2. 备份当前 `Assets/AnyThinkPlugin` 和 `Assets/Topon_Adapter`。 3. 确认本次升级目标是 - 仅升级官方 SDK - 还是同时升级商业化 core 抽象层接口 ### 8.2 合并阶段 1. 先更新官方运行时目录 - `Assets/AnyThinkPlugin/AnyThinkAds` 2. 再检查编辑器目录 - `Assets/AnyThinkPlugin/Script/IntegrationManager` - `Assets/AnyThinkPlugin/Script/Editor` 3. 最后回填本仓库本地改造 - 动态路径改造 - listener 桥接 - Android/iOS 构建补丁 - `Topon_Adapter` 运行时绑定 不建议做法: - 直接拿官方新版覆盖整个 `Assets/AnyThinkPlugin` - 直接覆盖 `Topon_Adapter` - 在没核对构建脚本的情况下直接发布 tag ### 8.3 验证阶段 升级后至少验证以下内容: 1. Unity 工程可编译。 2. `Topon_Adapter` 仍能正确引用 core 抽象层。 3. 激励视频和插屏能正常加载、展示、回调。 4. Android 导出工程中: - `WXEntryActivity` 存在 - `TTFileProvider` 存在 - `queries/com.tencent.mm` 存在 - `allowBackup=false` 生效 - `networkSecurityConfig` 在中国区按预期生效 - `packagingOptions` 注入正常 5. iOS 导出工程中: - framework embed 正常 - bundle 正常 - plist 补丁正常 6. EDM4U 依赖解析后无明显冲突。 ### 8.4 发布阶段 1. 更新 `Assets/package.json` 版本。 2. 必要时同步更新 `Assets/package.json` 中的 core 依赖版本。 3. 本地工程验证无误后执行 `Update Upm.bat`。 4. 在业务项目按 tag 验证最终接入结果。 ## 9. 当前已识别的维护注意项 ### 9.1 版本声明可能漂移 当前仓库内存在两处 core 版本信息: - `Assets/package.json` - `Packages/manifest.json` 前者决定发布包依赖,后者仅影响当前源码工程联调。 升级或发版时,要确认二者是否需要同步,不要出现“发布出去的依赖版本”和“本地验证时的依赖版本”长期漂移。 ### 9.2 不要依赖根目录工程文件 根目录这些文件只是 Unity 本地工程产物: - `*.csproj` - `*.sln` - `Library` - `Temp` 包发布和业务项目接入都不应依赖它们。 ### 9.3 当前实现范围 本仓库当前本质上是: - `Topon` 平台广告实现层 - 面向 `商业化抽象层` 的适配包 不是: - 通用业务 Demo - 完整多平台商业化总仓 - 所有广告位都已完全实现的全量样板 ## 10. 一句话原则 后续升级 Topon/AnyThink SDK 时,优先保护这四件事: 1. `Assets` 子树可独立发布为 UPM 包。 2. 动态路径定位不能回退成固定 `Assets/...` 读取。 3. `Topon_Adapter` 对 core 抽象层的接口契约不能被官方 SDK 反向污染。 4. Android/iOS 构建期补丁必须逐项保留并重新验证。