2026-06-04 17:16:17 +08:00
|
|
|
|
# Commercialization.tapadn
|
|
|
|
|
|
|
|
|
|
|
|
`Commercialization.tapadn` 是 TapADN / Dirichlet 聚合广告平台在 `CC-Framework.Commercialization` 抽象层上的实现包。
|
|
|
|
|
|
|
|
|
|
|
|
## 接入定位
|
|
|
|
|
|
|
|
|
|
|
|
业务项目只需要同时引入:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
2026-06-12 16:17:36 +08:00
|
|
|
|
"com.foldcc.cc-framework.commercialization": "http://private.lightyears.ltd:18650/foldcc/CC-Framework.Commercialization.git#1.0.15",
|
2026-06-17 15:52:26 +08:00
|
|
|
|
"com.commercialization.tapadn": "http://private.lightyears.ltd:18650/foldcc/Commercialization.tapadn.git?path=/Assets#1.0.5"
|
2026-06-04 17:16:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
项目层继续面向 `ADManager`、`ADConfig`、`AD_Type` 工作,不直接依赖 TapADN SDK API。
|
|
|
|
|
|
|
|
|
|
|
|
## 初始化方式
|
|
|
|
|
|
|
|
|
|
|
|
推荐让本模块创建 controller 并初始化广告管理器:
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
var config = TapadnCommercialization.CreateConfig(
|
|
|
|
|
|
mediaId: "100000",
|
|
|
|
|
|
mediaKey: "media-key",
|
|
|
|
|
|
mediaName: "GameName",
|
|
|
|
|
|
rewardSlotId: "200000",
|
|
|
|
|
|
interstitialSlotId: "200001",
|
|
|
|
|
|
splashSlotId: "200002");
|
|
|
|
|
|
|
|
|
|
|
|
TapadnCommercialization.InitADManager(
|
|
|
|
|
|
onCallback: () => Debug.Log("AD ready"),
|
|
|
|
|
|
userId: userId,
|
|
|
|
|
|
adConfig: config);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
如项目已有 `ADConfig` 资产,也可以直接调用:
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
ADManager.Instance.Init(callback, userId, adConfig, new TapadnAdController());
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`ADConfig` 字段约定:
|
|
|
|
|
|
|
|
|
|
|
|
* `Id`: TapADN MediaId。
|
|
|
|
|
|
* `Key`: TapADN MediaKey。
|
|
|
|
|
|
* `Key2`: MediaName。
|
|
|
|
|
|
* `BaseAwardAdKeyValue.value`: 激励视频广告位 SpaceId。
|
|
|
|
|
|
* `BaseInteractionAdKeyValue.value`: 插屏广告位 SpaceId。
|
|
|
|
|
|
* `BaseSplashAdKeyValue.value`: 开屏广告位 SpaceId。
|
|
|
|
|
|
|
|
|
|
|
|
## 配置 key
|
|
|
|
|
|
|
|
|
|
|
|
可通过 `ADConfig.CommonKeyValues` 或 `InitADManager(..., args)` 中传入 `IDictionary` 覆盖:
|
|
|
|
|
|
|
|
|
|
|
|
* `tapadn.media_id`
|
|
|
|
|
|
* `tapadn.media_key`
|
|
|
|
|
|
* `tapadn.media_name`
|
|
|
|
|
|
* `tapadn.channel`
|
|
|
|
|
|
* `tapadn.sub_channel`
|
|
|
|
|
|
* `tapadn.debug`
|
|
|
|
|
|
* `tapadn.tap_client_id`
|
|
|
|
|
|
* `tapadn.shake_enabled`
|
|
|
|
|
|
* `tapadn.custom_config_json`
|
|
|
|
|
|
* `tapadn.data_json`
|
|
|
|
|
|
* `tapadn.atags`
|
|
|
|
|
|
* `tapadn.allow_idfa_access`
|
|
|
|
|
|
* `tapadn.request_permission_on_init`
|
|
|
|
|
|
* `tapadn.reward_name`
|
|
|
|
|
|
* `tapadn.reward_amount`
|
|
|
|
|
|
* `tapadn.rewarded_auto_load`
|
|
|
|
|
|
* `tapadn.rewarded_prewarm_on_init`
|
|
|
|
|
|
* `tapadn.rewarded_max_load_attempts`
|
|
|
|
|
|
* `tapadn.rewarded_load_retry_delay_ms`
|
|
|
|
|
|
* `tapadn.rewarded_show_timeout_ms`
|
2026-06-17 15:40:25 +08:00
|
|
|
|
* `tapadn.rewarded_scene_slot.<scene_id>`(激励视频场景广告位映射,值为对应 SpaceId)
|
|
|
|
|
|
* `tapadn.rewarded_scene_slots`(激励视频场景广告位批量映射,格式 `scene_a=10001,scene_b=10002`)
|
|
|
|
|
|
* `tapadn.rewarded_scene_slots_json`(激励视频场景广告位 JSON,格式见下方)
|
|
|
|
|
|
* `tapadn.rewarded_cache_max_age_seconds`(可选本地缓存年龄上限;默认 `600` 秒,设为 `0` 表示只使用 SDK `IsValid` 判断)
|
2026-06-04 17:16:17 +08:00
|
|
|
|
* `tapadn.interstitial_auto_load`
|
|
|
|
|
|
* `tapadn.interstitial_prewarm_on_init`
|
|
|
|
|
|
* `tapadn.interstitial_max_load_attempts`
|
|
|
|
|
|
* `tapadn.interstitial_load_retry_delay_ms`
|
|
|
|
|
|
* `tapadn.interstitial_show_timeout_ms`
|
|
|
|
|
|
* `tapadn.splash_auto_load`
|
|
|
|
|
|
* `tapadn.splash_prewarm_on_init`
|
|
|
|
|
|
* `tapadn.splash_max_load_attempts`
|
|
|
|
|
|
* `tapadn.splash_load_retry_delay_ms`
|
|
|
|
|
|
* `tapadn.splash_show_timeout_ms`
|
2026-06-05 21:44:35 +08:00
|
|
|
|
* `tapadn.smart_preload_enabled`(开启智能预加载策略)
|
|
|
|
|
|
* `tapadn.smart_preload_config_json`(智能预加载静态配置 JSON)
|
|
|
|
|
|
* `tapadn.smart_preload_config_asset_path`(预加载策略资源表路径,默认 `TapadnSmartLoadPolicy_Default`)
|
|
|
|
|
|
* `tapadn.smart_preload_remote_json`(远端覆盖配置 JSON,按场景覆盖静态配置)
|
2026-06-04 17:16:17 +08:00
|
|
|
|
* `tapadn.express_width`
|
|
|
|
|
|
* `tapadn.express_height`
|
|
|
|
|
|
|
2026-06-05 21:44:35 +08:00
|
|
|
|
默认激励、插屏、开屏都使用手动 load/show;如无特殊策略验证需求,不建议开启 auto-ad。若要做 auto-ad AB 测试,再将对应 `*_auto_load` 设为 `true`。
|
|
|
|
|
|
|
2026-06-17 15:40:25 +08:00
|
|
|
|
### 激励视频场景广告位
|
|
|
|
|
|
|
|
|
|
|
|
激励视频支持按游戏场景路由不同 TapADN SpaceId。项目层继续调用 `ADManager.EnterAdScenario(AD_Type.AwardVideo, sceneId)` 和 `ADManager.AsyncPlayAD(AD_Type.AwardVideo, sceneId, callback)`;TapADN adapter 会按 `sceneId` 查表:
|
|
|
|
|
|
|
2026-06-17 18:15:02 +08:00
|
|
|
|
* 命中 `tapadn.rewarded_scene_slot.<scene_id>`、批量配置,或 `CommonKeyValues` 中 `scene_id=SpaceId` 的兼容配置时,使用该场景 SpaceId。
|
2026-06-17 15:40:25 +08:00
|
|
|
|
* 未传场景、场景为空、场景未配置、配置的 SpaceId 非法时,回退到 `BaseAwardAdKeyValue.value` 默认激励视频广告位。
|
|
|
|
|
|
* 手动 load/show 模式下,缓存按 SpaceId 隔离;A 场景加载的激励视频不会被 B 场景误认为 ready。
|
2026-06-17 18:15:02 +08:00
|
|
|
|
* Editor/样例调试时,进入场景、加载和播放请求会在 Console 输出当前解析到的 SpaceId 及来源,格式类似 `slot=200101, source=scene`。
|
2026-06-17 15:40:25 +08:00
|
|
|
|
|
|
|
|
|
|
单项配置示例:
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
adConfig.CommonKeyValues.Add(new AdKeyValue
|
|
|
|
|
|
{
|
|
|
|
|
|
key = "tapadn.rewarded_scene_slot.level_clear",
|
|
|
|
|
|
value = "200101"
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-17 18:15:02 +08:00
|
|
|
|
兼容已有业务配置示例:
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
adConfig.CommonKeyValues.Add(new AdKeyValue
|
|
|
|
|
|
{
|
|
|
|
|
|
key = "PlantUnlock",
|
|
|
|
|
|
value = "200101"
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-17 15:40:25 +08:00
|
|
|
|
批量字符串配置示例:
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
adConfig.CommonKeyValues.Add(new AdKeyValue
|
|
|
|
|
|
{
|
|
|
|
|
|
key = "tapadn.rewarded_scene_slots",
|
|
|
|
|
|
value = "level_clear=200101,daily_bonus=200102"
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
JSON 配置示例:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"Mappings": [
|
|
|
|
|
|
{ "Scene": "level_clear", "SlotId": "200101" },
|
|
|
|
|
|
{ "Scene": "daily_bonus", "SlotId": "200102" }
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
生命周期策略按官方文档保持保守:
|
|
|
|
|
|
|
|
|
|
|
|
* `DirichletAdNative` 仍由每个 TapADN player 统一持有,不在每个场景重复创建。
|
|
|
|
|
|
* 手动加载返回的 `DirichletRewardVideoAd` 按 SpaceId 缓存;展示关闭、展示失败、SDK `IsValid == false` 或超过 `tapadn.rewarded_cache_max_age_seconds` 后销毁。
|
|
|
|
|
|
* 官方文档没有给出固定过期秒数;本模块默认 10 分钟未消费主动销毁,同时每次 ready/show 前仍调用 SDK `IsValid`。
|
|
|
|
|
|
* Android auto-ad 仍交给官方 `ShowRewardVideoAutoAd` / `PreLoad` 的 native 缓存管理;iOS/Editor fallback 仍是 load 成功后立即 show,不承诺 native 缓存语义。
|
|
|
|
|
|
|
2026-06-05 21:44:35 +08:00
|
|
|
|
### 智能预加载(实验)
|
|
|
|
|
|
|
|
|
|
|
|
默认会按“场景进入次数 + 场景播放请求次数”维护一个小样本统计:
|
|
|
|
|
|
|
|
|
|
|
|
* 进入场景时记录 `EnterCount`
|
|
|
|
|
|
* `AsyncPlayAD` 执行前调用的 `OnPlayRequestStarted` 记录 `PlayRequestCount`
|
|
|
|
|
|
* 按置信加权算法推算场景播放概率,达到阈值后触发 `ADManager.LoadAD` 预加载
|
|
|
|
|
|
* 预加载归因按“全局广告类型缓存”记录:触发场景记录 `preload_request/success/fail`,实际播放场景记录 `show/immediate/smart_cache_hit`
|
|
|
|
|
|
* 当 A 场景触发的全局缓存在 B 场景展示时,A 会记录 `smart_preload_consumed_other_scene`,B 会记录 `smart_cache_cross_scene_hit`
|
|
|
|
|
|
|
|
|
|
|
|
配置 JSON 示例(可通过 `CommonKeyValues` 下发):
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"GlobalDefault": {
|
|
|
|
|
|
"AdType": -1,
|
|
|
|
|
|
"Scene": "__default__",
|
|
|
|
|
|
"BaseProbability": 0.08,
|
|
|
|
|
|
"PreloadThreshold": 0.75,
|
|
|
|
|
|
"CooldownSeconds": 120,
|
|
|
|
|
|
"MinSamplesForConfidence": 8,
|
|
|
|
|
|
"DecayHalfLifeHours": 72
|
|
|
|
|
|
},
|
|
|
|
|
|
"ScenePolicies": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"AdType": 0,
|
|
|
|
|
|
"Scene": "reward_debug",
|
|
|
|
|
|
"BaseProbability": 0.6,
|
|
|
|
|
|
"PreloadThreshold": 0.5,
|
|
|
|
|
|
"CooldownSeconds": 60,
|
|
|
|
|
|
"MinSamplesForConfidence": 4,
|
|
|
|
|
|
"DecayHalfLifeHours": 48
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
说明:
|
|
|
|
|
|
* `AdType` 使用 `AD_Type` 枚举值:`0=AwardVideo`, `1=Splash`, `2=Interaction`
|
|
|
|
|
|
* `Scene` 用于和 `ADManager.EnterAdScenario` 的场景名对齐;场景未命中时回退到对应广告位的默认场景配置。
|
|
|
|
|
|
* `ExportSnapshotCsv()` 会额外导出 `immediate_hit`、`smart_cache_hit`、`smart_preload_consumed`、`smart_preload_expired` 等列,用于区分“哪个场景触发预加载”和“哪个场景最终消费缓存”。
|
2026-06-04 17:16:17 +08:00
|
|
|
|
|
|
|
|
|
|
## Android 构建
|
|
|
|
|
|
|
|
|
|
|
|
包内包含官方 `DirichletMediation` SDK、Android AAR、iOS bridge、EDM4U 依赖声明和构建后处理。
|
|
|
|
|
|
|
2026-06-17 15:52:26 +08:00
|
|
|
|
维护和升级说明见 `SDK_MAINTENANCE.md`,其中记录了官方源码改动清单、Android/iOS/Unity SDK 升级步骤和发布流程。
|
|
|
|
|
|
|
2026-06-04 17:16:17 +08:00
|
|
|
|
构建后处理会自动补齐:
|
|
|
|
|
|
|
|
|
|
|
|
* TapADN 所需权限。
|
|
|
|
|
|
* TapADN `TapADFileProvider` 与 `tapad_ad_file_path.xml`。
|
|
|
|
|
|
* 微信 OpenSDK `WXEntryActivity`、`queries`、本地 `wechat-sdk-android-6.8.34.aar`。
|
2026-06-17 15:52:26 +08:00
|
|
|
|
* Pangle `com.pangle.cn:ads-sdk-pro:7.6.1.2` 和 GDT `com.qq.e.union:union:4.690.1560` Maven 依赖。
|
2026-06-04 17:16:17 +08:00
|
|
|
|
* `android.useAndroidX=true` 与 `android.enableJetifier=true`。
|
|
|
|
|
|
|
|
|
|
|
|
包内不默认暴露可视化编辑面板;调试样例通过 `Samples~` 作为可选导入内容。
|
2026-06-05 21:44:35 +08:00
|
|
|
|
|
2026-06-12 16:05:13 +08:00
|
|
|
|
## iOS 构建
|
|
|
|
|
|
|
|
|
|
|
|
iOS 侧通过 `DirichletMediationIOSPostProcessor` 在 Unity 导出 Xcode 工程后自动处理:
|
|
|
|
|
|
|
|
|
|
|
|
* 生成 `Podfile`,默认接入 `DirichletMediationSDK`、`DirichletMediationAdapterDRA`、`DirichletMediationAdapterCSJ`、`DirichletMediationAdapterGDT` 的 iOS `4.2.0.1` Pod。
|
|
|
|
|
|
* 将 Pods 放到 Unity Framework target,避免 adapter 被 strip 后运行时找不到类。
|
|
|
|
|
|
* 补齐 `SKAdNetworkItems`、`NSUserTrackingUsageDescription`、`AppTrackingTransparency.framework`、`AdSupport.framework`。
|
|
|
|
|
|
* 执行 `pod install`;若构建机没有 CocoaPods,会在日志里给出手动执行路径。
|
|
|
|
|
|
* 将 GDT 的动态 framework 嵌入 App target。
|
|
|
|
|
|
|
|
|
|
|
|
可选覆盖:
|
|
|
|
|
|
|
|
|
|
|
|
* `DIRICHLET_IOS_SDK_VERSION` 或 `EditorPrefs("Dirichlet.iOS.SDKVersion")`:临时切换 iOS Pod 版本。
|
|
|
|
|
|
* `DIRICHLET_IOS_ATT_DESCRIPTION` 或 `EditorPrefs("Dirichlet.iOS.TrackingUsageDescription")`:替换 ATT 弹窗文案。
|
|
|
|
|
|
* `DIRICHLET_UNITY_FRAMEWORK_TARGET` / `DIRICHLET_UNITY_APP_TARGET`:极端自定义 Xcode target 名称时手动指定。
|
|
|
|
|
|
|
|
|
|
|
|
iOS 的 auto-ad 原生接口仍按官方口径视为 Android 能力;本模块在 iOS 上对激励、插屏、开屏做了“load 成功后立即 show”的兼容 fallback,不承诺 native 缓存语义。正式联调仍需要用 TapADN iOS 媒体账号和 iOS 广告位做真机验证,重点看初始化、ATT、三类广告 load/show/close/reward 回调,以及无填充/未 ready 的失败收口。
|
|
|
|
|
|
|
2026-06-05 21:44:35 +08:00
|
|
|
|
## 智能预加载敏感度验收(默认次留 35%)
|
|
|
|
|
|
|
|
|
|
|
|
本模块包含一套本地仿真脚本,用于模拟 IAA 场景下不同 `PreloadThreshold` 与 `CooldownSeconds` 的收益差异,输出完整 CSV 与变化曲线。
|
|
|
|
|
|
|
|
|
|
|
|
默认次留基线设置为 `35%`(你可以改保留率列表),默认模型参数位于 `Assets/Tapadn_Adapter/Runtime/Resources/TapadnSmartLoadPolicy_Default.json`。
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python Tools/SmartLoadSensitivity/smartload_sensitivity_simulation.py --users 5000 --out-dir Tools/SmartLoadSensitivity/output
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
输出文件(可复现):
|
|
|
|
|
|
|
|
|
|
|
|
* `Tools/SmartLoadSensitivity/output/smartload_sensitivity_summary.csv`
|
|
|
|
|
|
* `Tools/SmartLoadSensitivity/output/smartload_retention_rank.csv`
|
|
|
|
|
|
* `Tools/SmartLoadSensitivity/output/TapADN_智能预加载_敏感度验收报告.md`
|
|
|
|
|
|
* `Tools/SmartLoadSensitivity/output/*.png`(热力图和曲线)
|
|
|
|
|
|
|
|
|
|
|
|
重点图示(`TapADN_智能预加载_敏感度验收报告.md` 中已自动嵌入):
|
|
|
|
|
|
|
|
|
|
|
|
* `heatmap_immediate_r_0.35.png`(次留 35% 下的即时命中率)
|
|
|
|
|
|
* `heatmap_wait_ms_r_0.35.png`(次留 35% 下的平均等待时延)
|
|
|
|
|
|
* `heatmap_waste_ratio_r_0.35.png`(次留 35% 下的 waste 率)
|
|
|
|
|
|
* `line_immediate_vs_retention.png`(留存与即时命中率关系)
|
|
|
|
|
|
* `line_wait_vs_retention.png`(留存与等待时延关系)
|
|
|
|
|
|
|
|
|
|
|
|
你也可以直接查看部分曲线对比:
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|