You've already forked Commercialization.tapadn
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8132027785 | |||
| 4089560471 | |||
| 286799142b | |||
| 1b595f25e1 | |||
| 18af360571 | |||
| 8dc806c1eb | |||
| 96364aab18 |
51
CHANGELOG.md
51
CHANGELOG.md
@@ -1,3 +1,54 @@
|
||||
# [1.0.8]
|
||||
|
||||
### 修复
|
||||
|
||||
* 修复 Editor 广告位诊断在编译期触发 `CS0165` 未赋值变量错误的问题。
|
||||
|
||||
# [1.0.7]
|
||||
|
||||
### 修复
|
||||
|
||||
* 接入 `CC-Framework.Commercialization` 的 Editor 诊断接口,Unity Editor 模拟点击广告时也会输出 TapADN 当前解析出的广告位 ID。
|
||||
|
||||
# [1.0.6]
|
||||
|
||||
### 修复
|
||||
|
||||
* 兼容 `CommonKeyValues` 中直接使用业务场景名作为 key、SpaceId 作为 value 的激励视频广告位配置,避免只识别 `tapadn.rewarded_scene_slot.<scene_id>` 时回退到默认激励广告位。
|
||||
* 激励视频进入场景、加载和播放请求会输出当前解析到的 SpaceId 及来源,便于 Editor Console 和样例调试面板确认实际使用的广告位。
|
||||
|
||||
# [1.0.5]
|
||||
|
||||
### 调整
|
||||
|
||||
* Android native 聚合 SDK AAR 升级到 `4.2.7.3`。
|
||||
* Android Pangle 依赖升级到 `7.6.1.2`,GDT 依赖升级到 `4.690.1560`,改由 Gradle 后处理注入 Maven 依赖。
|
||||
* 移除旧本地 Pangle/GDT AAR,避免与 Maven 依赖重复类。
|
||||
|
||||
### 文档
|
||||
|
||||
* 新增 `SDK_MAINTENANCE.md`,记录官方源码改动清单、封装层职责、SDK 升级步骤和发布流程。
|
||||
|
||||
# [1.0.4]
|
||||
|
||||
### 新增
|
||||
|
||||
* 激励视频支持按游戏场景映射不同 TapADN SpaceId,并在未配置或配置非法时回退默认激励广告位。
|
||||
* 手动加载模式下激励视频缓存按 SpaceId 隔离,避免不同场景广告位串用 ready 缓存。
|
||||
* 激励视频缓存默认 10 分钟未消费自动销毁,可通过 `tapadn.rewarded_cache_max_age_seconds` 覆盖。
|
||||
|
||||
### 调整
|
||||
|
||||
* 智能预加载归因缓存增加 SpaceId 维度,避免多广告位场景下 ready/归因状态混用。
|
||||
|
||||
# [1.0.3]
|
||||
|
||||
### 修复
|
||||
|
||||
* iOS 导出后自动修复 `UnityFramework` target 的广告 SDK `FRAMEWORK_SEARCH_PATHS` / `HEADER_SEARCH_PATHS`,覆盖 Dirichlet、CSJ、GDT、DRA、GDTMobSDK、Tquic、BUAdSDK 的真实 xcframework slice。
|
||||
* iOS 导出后清理 CocoaPods `Pods-UnityFramework*.xcconfig` 中的 `XCFrameworkIntermediates` 搜索路径,避免 Xcode 真机 Play 时出现 framework not found 或 search path not found。
|
||||
* 保持签名配置由业务工程负责,广告模块不写入 Team、provisioning profile 或 code signing 设置。
|
||||
|
||||
# [1.0.1]
|
||||
|
||||
### 调整
|
||||
|
||||
15
DirichletMediation/Editor/Dirichlet.Mediation.Editor.asmdef
Normal file
15
DirichletMediation/Editor/Dirichlet.Mediation.Editor.asmdef
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Dirichlet.Mediation.Editor",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ffd2503194414b5e8b8e687a6a70a19f
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -23,6 +23,8 @@ namespace Dirichlet.Mediation.Editor
|
||||
private const string DIRICHLET_DEPS_END = "// Dirichlet Mediation Dependencies End";
|
||||
private const string DIRICHLET_REPOS_START = "// Dirichlet Mediation Repositories Start";
|
||||
private const string DIRICHLET_REPOS_END = "// Dirichlet Mediation Repositories End";
|
||||
private const string PangleSdkVersion = "7.6.1.2";
|
||||
private const string GdtSdkVersion = "4.690.1560";
|
||||
|
||||
public int callbackOrder => 100; // Run after EDM4U (which uses lower values)
|
||||
|
||||
@@ -149,32 +151,24 @@ namespace Dirichlet.Mediation.Editor
|
||||
var depsBlock = new StringBuilder();
|
||||
depsBlock.AppendLine(DIRICHLET_DEPS_START);
|
||||
|
||||
// Core Mediation AAR
|
||||
depsBlock.AppendLine(" implementation(name: 'DirichletAD_Mediation_4.2.5.0', ext: 'aar')");
|
||||
|
||||
// CSJ (穿山甲) Adapter and SDK
|
||||
if (enableCsj)
|
||||
{
|
||||
depsBlock.AppendLine(" implementation(name: 'DirichletAD_CSJ_Adapter_4.2.5.0', ext: 'aar')");
|
||||
depsBlock.AppendLine(" implementation(name: 'open_ad_sdk_7.4.2.2', ext: 'aar')");
|
||||
}
|
||||
|
||||
// GDT (广点通) Adapter and SDK
|
||||
if (enableGdt)
|
||||
{
|
||||
depsBlock.AppendLine(" implementation(name: 'DirichletAD_GDT_Adapter_4.2.5.0', ext: 'aar')");
|
||||
depsBlock.AppendLine(" implementation(name: 'GDTSDK.unionNormal.4.671.1541', ext: 'aar')");
|
||||
}
|
||||
|
||||
// IQY (爱奇艺) Adapter and SDK
|
||||
// Local AAR files are imported by Unity's PluginImporter from Assets/Plugins/Android.
|
||||
// Do not declare them here again, otherwise exported Gradle projects can get duplicate classes.
|
||||
if (enableIqy)
|
||||
{
|
||||
depsBlock.AppendLine(" implementation(name: 'DirichletAD_IQY_Adapter_4.2.5.0', ext: 'aar')");
|
||||
depsBlock.AppendLine(" implementation(name: 'iadsdk-release-2.3.102.110', ext: 'aar')");
|
||||
depsBlock.AppendLine(" implementation 'com.android.support.constraint:constraint-layout:1.1.3'");
|
||||
}
|
||||
|
||||
// Maven dependencies (required for SDK functionality)
|
||||
if (enableCsj)
|
||||
{
|
||||
depsBlock.AppendLine($" implementation('com.pangle.cn:ads-sdk-pro:{PangleSdkVersion}') {{");
|
||||
depsBlock.AppendLine(" exclude group: 'com.android.support'");
|
||||
depsBlock.AppendLine(" }");
|
||||
}
|
||||
if (enableGdt)
|
||||
{
|
||||
depsBlock.AppendLine($" implementation 'com.qq.e.union:union:{GdtSdkVersion}'");
|
||||
}
|
||||
depsBlock.AppendLine(" implementation 'com.android.support:recyclerview-v7:28.0.0'");
|
||||
depsBlock.AppendLine(" implementation 'com.github.bumptech.glide:glide:4.9.0'");
|
||||
depsBlock.AppendLine(" implementation 'com.android.support:support-v4:28.0.0'");
|
||||
|
||||
@@ -36,6 +36,9 @@ namespace Dirichlet.Mediation.Editor
|
||||
private const string ENV_ATT_DESCRIPTION = "DIRICHLET_IOS_ATT_DESCRIPTION";
|
||||
private const string PrefKeyIOSSDKVersion = "Dirichlet.iOS.SDKVersion";
|
||||
private const string PrefKeyATTDescription = "Dirichlet.iOS.TrackingUsageDescription";
|
||||
private const string IOSDeviceSlice = "ios-arm64";
|
||||
private const string TquicIOSDeviceSlice = "ios-arm64_armv7";
|
||||
private static readonly string[] GDTDynamicFrameworkNames = { "GDTMobSDK.framework", "Tquic.framework" };
|
||||
|
||||
/// <summary>
|
||||
/// 解析出的 target 信息
|
||||
@@ -78,8 +81,8 @@ namespace Dirichlet.Mediation.Editor
|
||||
// 4. Run pod install
|
||||
RunPodInstall(pathToBuiltProject);
|
||||
|
||||
// 5. Embed GDT dynamic frameworks into app target (must run after pod install)
|
||||
EmbedGDTDynamicFrameworks(pathToBuiltProject, targetInfo);
|
||||
// 5. Fix ad SDK framework/header search paths and embed GDT dynamic frameworks (must run after pod install)
|
||||
FixAdSDKIOSFrameworkConfiguration(pathToBuiltProject, targetInfo);
|
||||
|
||||
Debug.Log("[DirichletMediation] iOS post-process completed successfully.");
|
||||
}
|
||||
@@ -517,20 +520,16 @@ namespace Dirichlet.Mediation.Editor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GDTMobSDK 提供的是预编译动态库(GDTMobSDK.framework, Tquic.framework),
|
||||
/// 必须 embed 到 app bundle 中才能在运行时加载。
|
||||
/// 由于所有 pods 都在 Framework target 上,CocoaPods 不会自动 embed 到 app target,
|
||||
/// 需要在 pod install 之后手动处理。
|
||||
/// UnityFramework 链接阶段需要显式搜索广告 SDK xcframework 内部的真机 slice,
|
||||
/// 否则 Xcode 可能报 ld: framework 'GDTMobSDK' not found 或 XCFrameworkIntermediates 搜索路径缺失。
|
||||
/// 同时 GDTMobSDK 提供的是预编译动态库(GDTMobSDK.framework, Tquic.framework),
|
||||
/// 必须 embed 到 app bundle 中才能在运行时加载。由于所有 pods 都在 Framework target 上,
|
||||
/// CocoaPods 不会自动 embed 到 app target,需要在 pod install 之后手动处理。
|
||||
/// 依赖 UnityEditor.iOS.Xcode.Extensions 中的 AddFileToEmbedFrameworks 扩展方法。
|
||||
/// </summary>
|
||||
private static void EmbedGDTDynamicFrameworks(string projectPath, TargetInfo targetInfo)
|
||||
private static void FixAdSDKIOSFrameworkConfiguration(string projectPath, TargetInfo targetInfo)
|
||||
{
|
||||
var enableGdt = EditorPrefs.GetBool("Dirichlet.iOS.EnableGDT", true);
|
||||
if (!enableGdt)
|
||||
{
|
||||
Debug.Log("[DirichletMediation] GDT adapter disabled, skipping dynamic framework embedding");
|
||||
return;
|
||||
}
|
||||
|
||||
var xcodeProjectName = DetectXcodeProjectName(projectPath);
|
||||
var projectFilePath = Path.Combine(projectPath, $"{xcodeProjectName}.xcodeproj/project.pbxproj");
|
||||
@@ -543,12 +542,19 @@ namespace Dirichlet.Mediation.Editor
|
||||
mainTargetGuid = pbxProject.TargetGuidByName(targetInfo.AppTargetName);
|
||||
}
|
||||
|
||||
// GDTMobSDK 的动态框架列表
|
||||
var dynamicFrameworkNames = new[] { "GDTMobSDK.framework", "Tquic.framework" };
|
||||
var targetGuid = ResolveUnityFrameworkTargetGuid(pbxProject, targetInfo);
|
||||
var frameworkSearchPaths = GetAdSDKFrameworkSearchPaths();
|
||||
var headerSearchPaths = GetAdSDKHeaderSearchPaths(frameworkSearchPaths);
|
||||
|
||||
var searchPathsAdded = AddAdSDKSearchPaths(pbxProject, targetGuid, frameworkSearchPaths, headerSearchPaths);
|
||||
PatchPodsXCConfigSearchPaths(projectPath, targetInfo, frameworkSearchPaths, headerSearchPaths);
|
||||
|
||||
var podsDir = Path.Combine(projectPath, "Pods");
|
||||
var embedded = 0;
|
||||
|
||||
foreach (var frameworkName in dynamicFrameworkNames)
|
||||
if (enableGdt)
|
||||
{
|
||||
foreach (var frameworkName in GDTDynamicFrameworkNames)
|
||||
{
|
||||
var frameworkPath = FindDynamicFramework(podsDir, frameworkName);
|
||||
if (string.IsNullOrEmpty(frameworkPath))
|
||||
@@ -566,12 +572,251 @@ namespace Dirichlet.Mediation.Editor
|
||||
embedded++;
|
||||
Debug.Log($"[DirichletMediation] Embedded dynamic framework: {frameworkName}");
|
||||
}
|
||||
|
||||
if (embedded > 0)
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("[DirichletMediation] GDT adapter disabled, skipping dynamic framework embedding");
|
||||
}
|
||||
|
||||
pbxProject.WriteToFile(projectFilePath);
|
||||
if (searchPathsAdded)
|
||||
{
|
||||
Debug.Log($"[DirichletMediation] Added ad SDK framework/header search paths to {targetInfo.FrameworkTargetName}");
|
||||
}
|
||||
Debug.Log($"[DirichletMediation] Embedded {embedded} GDT dynamic frameworks into {targetInfo.AppTargetName}");
|
||||
}
|
||||
|
||||
private static string ResolveUnityFrameworkTargetGuid(PBXProject pbxProject, TargetInfo targetInfo)
|
||||
{
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
var targetGuid = pbxProject.GetUnityFrameworkTargetGuid();
|
||||
#else
|
||||
var targetGuid = targetInfo.FrameworkTargetGuid;
|
||||
#endif
|
||||
if (string.IsNullOrEmpty(targetGuid))
|
||||
{
|
||||
targetGuid = targetInfo.FrameworkTargetGuid;
|
||||
}
|
||||
if (string.IsNullOrEmpty(targetGuid))
|
||||
{
|
||||
targetGuid = pbxProject.TargetGuidByName(targetInfo.FrameworkTargetName);
|
||||
}
|
||||
|
||||
return targetGuid;
|
||||
}
|
||||
|
||||
private static bool AddAdSDKSearchPaths(PBXProject pbxProject, string targetGuid, string[] frameworkSearchPaths, string[] headerSearchPaths)
|
||||
{
|
||||
if (string.IsNullOrEmpty(targetGuid))
|
||||
{
|
||||
Debug.LogWarning("[DirichletMediation] UnityFramework target GUID is empty, skipping ad SDK search paths");
|
||||
return false;
|
||||
}
|
||||
|
||||
pbxProject.AddBuildProperty(targetGuid, "FRAMEWORK_SEARCH_PATHS", "$(inherited)");
|
||||
foreach (var searchPath in frameworkSearchPaths)
|
||||
{
|
||||
pbxProject.AddBuildProperty(targetGuid, "FRAMEWORK_SEARCH_PATHS", searchPath);
|
||||
}
|
||||
|
||||
pbxProject.AddBuildProperty(targetGuid, "HEADER_SEARCH_PATHS", "$(inherited)");
|
||||
foreach (var searchPath in headerSearchPaths)
|
||||
{
|
||||
pbxProject.AddBuildProperty(targetGuid, "HEADER_SEARCH_PATHS", searchPath);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void PatchPodsXCConfigSearchPaths(
|
||||
string projectPath,
|
||||
TargetInfo targetInfo,
|
||||
string[] frameworkSearchPaths,
|
||||
string[] headerSearchPaths)
|
||||
{
|
||||
var targetSupportRoot = Path.Combine(projectPath, "Pods", "Target Support Files");
|
||||
if (!Directory.Exists(targetSupportRoot))
|
||||
{
|
||||
Debug.LogWarning("[DirichletMediation] CocoaPods target support files not found, skipping xcconfig search path patch");
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPrefix = "Pods-" + targetInfo.FrameworkTargetName;
|
||||
var xcconfigFiles = Directory.GetFiles(targetSupportRoot, "*.xcconfig", SearchOption.AllDirectories)
|
||||
.Where(path => Path.GetFileNameWithoutExtension(path).StartsWith(targetPrefix, System.StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
|
||||
if (xcconfigFiles.Length == 0)
|
||||
{
|
||||
Debug.LogWarning($"[DirichletMediation] No CocoaPods xcconfig found for {targetInfo.FrameworkTargetName}, skipping search path patch");
|
||||
return;
|
||||
}
|
||||
|
||||
var patched = 0;
|
||||
foreach (var xcconfigPath in xcconfigFiles)
|
||||
{
|
||||
var lines = File.ReadAllLines(xcconfigPath).ToList();
|
||||
var changed = UpsertXCConfigBuildSetting(lines, "FRAMEWORK_SEARCH_PATHS", frameworkSearchPaths);
|
||||
changed |= UpsertXCConfigBuildSetting(lines, "HEADER_SEARCH_PATHS", headerSearchPaths);
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
File.WriteAllLines(xcconfigPath, lines);
|
||||
patched++;
|
||||
}
|
||||
|
||||
Debug.Log($"[DirichletMediation] Patched {patched} CocoaPods xcconfig search path file(s) for {targetInfo.FrameworkTargetName}");
|
||||
}
|
||||
|
||||
private static bool UpsertXCConfigBuildSetting(System.Collections.Generic.List<string> lines, string propertyName, string[] searchPaths)
|
||||
{
|
||||
var insertIndex = -1;
|
||||
var originalLines = new System.Collections.Generic.List<string>();
|
||||
var tokens = new System.Collections.Generic.List<string>();
|
||||
|
||||
for (var i = lines.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!IsXCConfigBuildSettingLine(lines[i], propertyName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
insertIndex = i;
|
||||
originalLines.Add(lines[i]);
|
||||
CollectXCConfigBuildSettingTokens(lines[i], tokens);
|
||||
lines.RemoveAt(i);
|
||||
}
|
||||
|
||||
if (!ContainsXCConfigToken(tokens, "$(inherited)"))
|
||||
{
|
||||
tokens.Insert(0, "$(inherited)");
|
||||
}
|
||||
|
||||
foreach (var searchPath in searchPaths)
|
||||
{
|
||||
AddXCConfigTokenIfMissing(tokens, searchPath);
|
||||
}
|
||||
|
||||
var newLine = $"{propertyName} = {string.Join(" ", tokens)}";
|
||||
|
||||
if (insertIndex < 0)
|
||||
{
|
||||
lines.Add(newLine);
|
||||
return true;
|
||||
}
|
||||
|
||||
lines.Insert(insertIndex, newLine);
|
||||
return originalLines.Count != 1 || originalLines[0] != newLine;
|
||||
}
|
||||
|
||||
private static void CollectXCConfigBuildSettingTokens(string line, System.Collections.Generic.List<string> tokens)
|
||||
{
|
||||
var separatorIndex = line.IndexOf('=');
|
||||
if (separatorIndex < 0 || separatorIndex >= line.Length - 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var value = line.Substring(separatorIndex + 1).Trim();
|
||||
var lineTokens = value.Split(new[] { ' ', '\t' }, System.StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var token in lineTokens)
|
||||
{
|
||||
if (token.IndexOf("XCFrameworkIntermediates", System.StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AddXCConfigTokenIfMissing(tokens, token);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ContainsXCConfigToken(System.Collections.Generic.List<string> tokens, string value)
|
||||
{
|
||||
var normalizedValue = NormalizeXCConfigToken(value);
|
||||
return tokens.Any(token => NormalizeXCConfigToken(token) == normalizedValue);
|
||||
}
|
||||
|
||||
private static void AddXCConfigTokenIfMissing(System.Collections.Generic.List<string> tokens, string value)
|
||||
{
|
||||
if (!ContainsXCConfigToken(tokens, value))
|
||||
{
|
||||
tokens.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static string NormalizeXCConfigToken(string token)
|
||||
{
|
||||
return (token ?? string.Empty).Trim().Trim('"');
|
||||
}
|
||||
|
||||
private static bool IsXCConfigBuildSettingLine(string line, string propertyName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var trimmed = line.TrimStart();
|
||||
return trimmed.StartsWith(propertyName + " =", System.StringComparison.Ordinal)
|
||||
|| trimmed.StartsWith(propertyName + "=", System.StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static string[] GetAdSDKFrameworkSearchPaths()
|
||||
{
|
||||
var sdkVersion = ResolveIOSSDKVersion();
|
||||
var enableCsj = EditorPrefs.GetBool("Dirichlet.iOS.EnableCSJ", true);
|
||||
var enableGdt = EditorPrefs.GetBool("Dirichlet.iOS.EnableGDT", true);
|
||||
var paths = new System.Collections.Generic.List<string>
|
||||
{
|
||||
VersionedDirichletFrameworkSearchPath("DirichletAdSDK", sdkVersion),
|
||||
VersionedDirichletFrameworkSearchPath("DirichletCoreSDK", sdkVersion),
|
||||
VersionedDirichletFrameworkSearchPath("DirichletMediationSDK", sdkVersion),
|
||||
VersionedDirichletFrameworkSearchPath("DirichletMediationAdapterDRA", sdkVersion)
|
||||
};
|
||||
|
||||
if (enableCsj)
|
||||
{
|
||||
paths.Add(VersionedDirichletFrameworkSearchPath("DirichletMediationAdapterCSJ", sdkVersion));
|
||||
paths.Add("$(PODS_ROOT)/Ads-CN/SDK/BUAdSDK.xcframework/" + IOSDeviceSlice);
|
||||
}
|
||||
|
||||
if (enableGdt)
|
||||
{
|
||||
paths.Add(VersionedDirichletFrameworkSearchPath("DirichletMediationAdapterGDT", sdkVersion));
|
||||
paths.Add("$(PODS_ROOT)/GDTMobSDK/GDTFramework/GDTMobSDK.xcframework/" + IOSDeviceSlice);
|
||||
paths.Add("$(PODS_ROOT)/GDTMobSDK/GDTFramework/Tquic.xcframework/" + TquicIOSDeviceSlice);
|
||||
}
|
||||
|
||||
return paths.ToArray();
|
||||
}
|
||||
|
||||
private static string[] GetAdSDKHeaderSearchPaths(string[] frameworkSearchPaths)
|
||||
{
|
||||
return frameworkSearchPaths
|
||||
.Select(ToFrameworkHeaderSearchPath)
|
||||
.Where(path => !string.IsNullOrEmpty(path))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static string VersionedDirichletFrameworkSearchPath(string frameworkName, string sdkVersion)
|
||||
{
|
||||
return $"$(PODS_ROOT)/{frameworkName}/{frameworkName}-{sdkVersion}/{frameworkName}.xcframework/{IOSDeviceSlice}";
|
||||
}
|
||||
|
||||
private static string ToFrameworkHeaderSearchPath(string frameworkSearchPath)
|
||||
{
|
||||
var parts = frameworkSearchPath.Split(new[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries);
|
||||
var xcframeworkPart = parts.LastOrDefault(part => part.EndsWith(".xcframework", System.StringComparison.OrdinalIgnoreCase));
|
||||
if (string.IsNullOrEmpty(xcframeworkPart))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var frameworkName = xcframeworkPart.Substring(0, xcframeworkPart.Length - ".xcframework".Length);
|
||||
return $"{frameworkSearchPath}/{frameworkName}.framework/Headers";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,33 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90b3b17e0788494398662e729c344ee2
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
Binary file not shown.
@@ -1,33 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 930136242e574a2b89110e6a25e49065
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
115
SDK_MAINTENANCE.md
Normal file
115
SDK_MAINTENANCE.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# TapADN SDK 封装维护说明
|
||||
|
||||
本文记录 `Commercialization.tapadn` 对官方 Dirichlet/TapADN 聚合 SDK 的封装、改动和升级注意事项。维护或升级 SDK 时先读本文,再改文件。
|
||||
|
||||
## 当前 SDK 版本
|
||||
|
||||
官方链接:
|
||||
|
||||
* 资源下载页:https://ssp.dirichlet.cn/docs/resource-download/
|
||||
* 聚合 Unity 接入文档:https://ssp.dirichlet.cn/docs/dirichlet-mediation-sdk/dirichlet-mediation-sdk-guide-unity/
|
||||
* 聚合 Android 接入文档:https://ssp.dirichlet.cn/docs/dirichlet-mediation-sdk/dirichlet-mediation-sdk-guide-android/
|
||||
|
||||
| 范围 | 当前版本 | 来源 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| Unity 聚合 SDK | 4.2.5.0 | 官方 `dirichlet_mediation_unity_4.2.5.0.unitypackage` | 官方资源页当前仍只提供 Unity 4.2.5.0。 |
|
||||
| Android 聚合 native AAR | 4.2.7.3 | 官方 `dirichlet_ad_mediation_4.2.7.3.zip` | 已单独升级 Android native 侧。 |
|
||||
| Android Pangle | 7.6.1.2 | 官方 Android 聚合接入文档 | 通过 Gradle 后处理注入 Maven 依赖。 |
|
||||
| Android GDT | 4.690.1560 | 官方 Android 聚合接入文档 | 通过 Gradle 后处理注入 Maven 依赖。 |
|
||||
| iOS 聚合 SDK Pod | 4.2.0.1 | 官方 iOS 聚合版本 | 默认值在 `DirichletMediationIOSPostProcessor`,可用环境变量覆盖。 |
|
||||
|
||||
## 模块结构
|
||||
|
||||
| 路径 | 归属 | 维护说明 |
|
||||
| --- | --- | --- |
|
||||
| `Assets/DirichletMediation` | 官方 Unity SDK 基础层 | 不再视为纯官方源码,部分文件已有本地改动。 |
|
||||
| `Assets/Plugins/Android/DirichletMediation` | 官方 Android Unity bridge + native AAR | Java bridge 当前与官方 Unity 包一致;AAR 已升级到 Android native 4.2.7.3。 |
|
||||
| `Assets/Plugins/Android/libs` | Android 本地依赖 | 保留 `iadsdk-release-2.3.102.110.aar`;Pangle/GDT 不再放本地 AAR,改由 Maven 注入。 |
|
||||
| `Assets/Tapadn_Adapter` | 本模块封装层 | 对接 `CC-Framework.Commercialization`,不要让业务层直接调用官方 SDK。 |
|
||||
| `Assets/Samples~` | 可选调试样例 | 不是官方 sample,是本模块验证 `ADManager` 流程的样例。 |
|
||||
|
||||
## 官方源码改动清单
|
||||
|
||||
以下文件来自官方 Unity SDK,但本仓库已经修改过。升级官方 Unity SDK 时不能直接覆盖,必须三方合并:
|
||||
|
||||
| 文件 | 本地改动目的 |
|
||||
| --- | --- |
|
||||
| `Assets/DirichletMediation/Runtime/DirichletAdTypes.cs` | 补齐 Unity 侧 ad handle、auto-ad fallback、事件会话保活、`IsValid` / `Destroy` 包装等桥接行为。 |
|
||||
| `Assets/DirichletMediation/Runtime/DirichletMediationSdk.cs` | 增强 Android/iOS/noop bridge、Unity 线程派发、iOS load/init callback receiver 和平台兼容逻辑。 |
|
||||
| `Assets/DirichletMediation/Editor/DirichletGradlePostProcessor.cs` | 改为适配 Unity 导出的 Gradle 工程,注入仓库、support/glide/okhttp、Pangle/GDT Maven 依赖,避免本地 AAR 重复类。 |
|
||||
| `Assets/DirichletMediation/Editor/DirichletMediationIOSPostProcessor.cs` | 自动生成 Podfile,处理 UnityFramework target、framework/header search paths、SKAdNetwork、ATT、GDT 动态 framework 嵌入和 CocoaPods 异常兜底。 |
|
||||
|
||||
以下官方文件当前与官方 Unity 4.2.5.0 包一致,升级时可优先直接替换后验证:
|
||||
|
||||
| 文件 | 说明 |
|
||||
| --- | --- |
|
||||
| `Assets/DirichletMediation/Editor/DirichletMediationDependencies.xml` | EDM4U 依赖声明。 |
|
||||
| `Assets/Plugins/Android/DirichletMediation/src/main/java/com/dirichlet/unity/DirichletUnityBridge.java` | Android Java bridge。 |
|
||||
| `Assets/Plugins/Android/AndroidManifest.xml` | 官方基础 Manifest。 |
|
||||
| `Assets/Plugins/Android/proguard-user.txt` | 当前为空文件。 |
|
||||
|
||||
## 封装层做了什么
|
||||
|
||||
`Tapadn_Adapter` 的目标是让业务项目只面对 `ADManager` / `ADConfig` / `AD_Type`:
|
||||
|
||||
1. `TapadnAdController` 从 `ADConfig` 和 `CommonKeyValues` 解析媒体 ID、MediaKey、广告位、渠道、debug、权限、预加载和展示超时配置。
|
||||
2. `TapadnCommercialization` 提供创建 controller、初始化 `ADManager`、创建默认 `ADConfig`、批量写入激励场景广告位映射的便捷入口。
|
||||
3. `TapadnAdRequestFactory` 统一构建 `DirichletAdRequest`,保证 SpaceId 是正整数,并注入 UserId、奖励名、奖励数量、展示尺寸。
|
||||
4. `TapadnAwardVideoPlayer` 对接激励视频。手动 load/show 模式下,按 SpaceId 隔离缓存;展示关闭、展示失败、`IsValid == false`、或默认 600 秒未消费都会销毁缓存。
|
||||
5. `TapadnInteractionPlayer` 对接插屏;`TapadnSplashPlayer` 对接开屏。两者保持单默认广告位语义。
|
||||
6. `TapadnSmartLoadOrchestrator` 维护场景学习数据和智能预加载归因。当前是保守策略:默认不开启;开启后先观察用户点击广告的概率,达到阈值才自动预加载。
|
||||
|
||||
## 场景广告位规则
|
||||
|
||||
激励视频支持游戏场景映射不同 SpaceId:
|
||||
|
||||
| 配置 key | 示例 |
|
||||
| --- | --- |
|
||||
| `tapadn.rewarded_scene_slot.<scene_id>` | `tapadn.rewarded_scene_slot.level_clear = 200101` |
|
||||
| `tapadn.rewarded_scene_slots` | `level_clear=200101,daily_bonus=200102` |
|
||||
| `tapadn.rewarded_scene_slots_json` | `{ "Mappings": [ { "Scene": "level_clear", "SlotId": "200101" } ] }` |
|
||||
|
||||
回退规则:
|
||||
|
||||
1. 未传场景、场景为空、场景未配置、配置 SpaceId 非法时,使用 `BaseAwardAdKeyValue.value`。
|
||||
2. 如果两个场景配置到同一个 SpaceId,它们共享同一个广告位缓存。
|
||||
3. 如果 A 场景 SpaceId 已加载但没展示,用户去 B 场景展示 B SpaceId,A 缓存不会被 B 消费;A 会等回到 A 时复用,或超时/失效后销毁。
|
||||
|
||||
## Android 升级步骤
|
||||
|
||||
1. 查官方资源页和聚合 Android 发布记录,确认最新 Android 聚合版本、Pangle 版本、GDT 版本。
|
||||
2. 下载 `dirichlet_ad_mediation_<version>.zip`,校验官方 MD5。
|
||||
3. 替换 `Assets/Plugins/Android/DirichletMediation/libs/DirichletAD_*_<version>.aar`。
|
||||
4. 检查官方 Android 接入文档中的 Maven 依赖,更新 `DirichletGradlePostProcessor` 里的 `PangleSdkVersion`、`GdtSdkVersion`。
|
||||
5. 不要同时保留 Pangle/GDT 本地 AAR 和 Maven 依赖,否则容易出现 duplicate classes。当前策略是 Pangle/GDT 走 Maven。
|
||||
6. 搜索旧版本号,更新 `GLOBAL_DESIGN.md`、`README.md`、`CHANGELOG.md` 和 `Assets/package.json`。
|
||||
7. 至少执行 `dotnet build Commercialization.tapadn.sln --no-restore` 和 `git diff --check`。
|
||||
8. Android 真机构建仍需在消费项目里跑项目自带构建流程验证 Manifest merge、Gradle dependency resolution 和广告展示回调。
|
||||
|
||||
## Unity SDK 升级步骤
|
||||
|
||||
1. 下载官方新的 `dirichlet_mediation_unity_<version>.unitypackage` 并校验 MD5。
|
||||
2. 解包到临时目录,对比 `Assets/DirichletMediation` 和 `Assets/Plugins/Android`。
|
||||
3. 对“官方源码改动清单”里的 4 个文件做三方合并,不允许直接覆盖。
|
||||
4. 官方 sample 不进入默认包;如需要保留调试能力,继续放到 `Samples~`。
|
||||
5. 检查 Android Java bridge API 是否和当前 C# bridge 匹配,重点是 load/show/destroy/isValid/auto-ad callback。
|
||||
6. 检查 iOS Pod 名称和版本是否变化,同步 `DirichletMediationIOSPostProcessor` 的默认版本和 search path 规则。
|
||||
7. 重新验证 Android/iOS editor compile;真机展示验证至少覆盖初始化、激励 load/show/close/reward、插屏、开屏、无填充失败。
|
||||
|
||||
## 发布步骤
|
||||
|
||||
包根是 `Assets/package.json`,消费者应使用:
|
||||
|
||||
```json
|
||||
"com.commercialization.tapadn": "http://private.lightyears.ltd:18650/foldcc/Commercialization.tapadn.git?path=/Assets#<version>"
|
||||
```
|
||||
|
||||
发布命令:
|
||||
|
||||
```bash
|
||||
git subtree split --prefix=Assets --branch upm
|
||||
git tag <version>
|
||||
git push origin master upm <version>
|
||||
```
|
||||
|
||||
注意:当前版本 tag 打在完整仓库 `master` 上,因此消费者必须带 `?path=/Assets`。
|
||||
7
SDK_MAINTENANCE.md.meta
Normal file
7
SDK_MAINTENANCE.md.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcf571baef764df0aa6789990d47c36a
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -162,6 +162,7 @@ public sealed class TapadnIAAAdDebugSampleGui : MonoBehaviour
|
||||
GUILayout.Label($"Last EventLog: {_lastEventLog}", _textStyle);
|
||||
GUILayout.Label($"Last SDK Version: {DisplayValue(TapadnAdController.LastSdkVersion)}", _textStyle);
|
||||
GUILayout.Label($"Last Init Error: {DisplayValue(TapadnAdController.LastInitError)}", _textStyle);
|
||||
GUILayout.Label($"Rewarded Selected SpaceId: {GetResolvedRewardedSlotForDisplay(rewardedScenario)}", _textStyle);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -250,6 +251,7 @@ public sealed class TapadnIAAAdDebugSampleGui : MonoBehaviour
|
||||
|
||||
if (EnsureInitialized(label))
|
||||
{
|
||||
LogRewardedResolvedSlot(adType, scenario, "Enter scenario");
|
||||
ADManager.Instance.EnterAdScenario(adType, scenario);
|
||||
AppendLog($"Enter scenario requested. type={adType}, scenario={scenario}");
|
||||
}
|
||||
@@ -278,6 +280,7 @@ public sealed class TapadnIAAAdDebugSampleGui : MonoBehaviour
|
||||
|
||||
if (EnsureInitialized(label))
|
||||
{
|
||||
LogRewardedResolvedSlot(adType, scenario, "AsyncPlayAD");
|
||||
ADManager.Instance.AsyncPlayAD(adType, scenario, result =>
|
||||
{
|
||||
AppendLog($"{adType} callback: {result}");
|
||||
@@ -424,6 +427,30 @@ public sealed class TapadnIAAAdDebugSampleGui : MonoBehaviour
|
||||
}
|
||||
|
||||
AppendLog($"Options => mediaId={options.MediaId}, channel={options.Channel}, sub={options.SubChannel}, debug={options.Debug}, rewardAuto={options.RewardedAutoLoad}, interAuto={options.InterstitialAutoLoad}, splashAuto={options.SplashAutoLoad}");
|
||||
AppendLog($"Rewarded selected slot => {GetResolvedRewardedSlotForDisplay(rewardedScenario)}, configuredSceneSlots={options.RewardedSceneSlotIds?.Count ?? 0}");
|
||||
}
|
||||
|
||||
private void LogRewardedResolvedSlot(AD_Type adType, string scenario, string actionName)
|
||||
{
|
||||
if (adType != AD_Type.AwardVideo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AppendLog($"{actionName} rewarded slot => {GetResolvedRewardedSlotForDisplay(scenario)}");
|
||||
}
|
||||
|
||||
private string GetResolvedRewardedSlotForDisplay(string scenario)
|
||||
{
|
||||
var defaultSlotId = adConfig?.BaseAwardAdKeyValue?.value;
|
||||
var options = TapadnAdController.CurrentOptions;
|
||||
if (options == null)
|
||||
{
|
||||
return $"{DisplayValue(defaultSlotId)} (source=default, scenario={DisplayValue(scenario)})";
|
||||
}
|
||||
|
||||
var slotId = options.ResolveRewardedSlotId(defaultSlotId, scenario, out var mapped);
|
||||
return $"{DisplayValue(slotId)} (source={(mapped ? "scene" : "default")}, scenario={DisplayValue(scenario)})";
|
||||
}
|
||||
|
||||
private void OnRewardedBefore(string placementId, string scenario)
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<dependencies>
|
||||
<androidPackages>
|
||||
<androidPackage spec="com.tencent.mm.opensdk:wechat-sdk-android:6.8.34">
|
||||
<repositories>
|
||||
<repository>https://maven.aliyun.com/repository/public</repository>
|
||||
<repository>https://repo.maven.apache.org/maven2</repository>
|
||||
</repositories>
|
||||
</androidPackage>
|
||||
</androidPackages>
|
||||
<!-- WeChat OpenSDK is shipped as a local AAR under Assets/Plugins/Android. -->
|
||||
</dependencies>
|
||||
|
||||
@@ -3,7 +3,7 @@ using Dirichlet.Mediation;
|
||||
using Runtime.ADAggregator;
|
||||
using UnityEngine;
|
||||
|
||||
public sealed class TapadnAdController : IAdController
|
||||
public sealed class TapadnAdController : IAdController, IAdEditorDiagnostics
|
||||
{
|
||||
public static TapadnControllerOptions CurrentOptions { get; private set; }
|
||||
public static string LastSdkVersion { get; private set; }
|
||||
@@ -73,4 +73,41 @@ public sealed class TapadnAdController : IAdController
|
||||
{
|
||||
_maskAction?.Invoke(isOpen);
|
||||
}
|
||||
|
||||
public void LogEditorAdPlacement(ADConfig adConfig, AD_Type adType, string adScene, string action, object[] args)
|
||||
{
|
||||
var options = TapadnControllerOptions.Resolve(adConfig, args);
|
||||
var normalizedScene = string.IsNullOrWhiteSpace(adScene) ? "__default__" : adScene.Trim();
|
||||
var slotSource = "default";
|
||||
var slotId = ResolveEditorSlotId(adConfig, options, adType, normalizedScene, out slotSource);
|
||||
Debug.Log($"[TapADN] Editor ad {action}. type={adType}, scene={normalizedScene}, slot={DisplayEditorValue(slotId)}, source={slotSource}");
|
||||
}
|
||||
|
||||
private static string ResolveEditorSlotId(ADConfig adConfig, TapadnControllerOptions options, AD_Type adType, string adScene, out string slotSource)
|
||||
{
|
||||
slotSource = "default";
|
||||
switch (adType)
|
||||
{
|
||||
case AD_Type.AwardVideo:
|
||||
var defaultRewardedSlotId = adConfig?.BaseAwardAdKeyValue?.value;
|
||||
var mapped = false;
|
||||
var rewardedSlotId = options == null
|
||||
? defaultRewardedSlotId
|
||||
: options.ResolveRewardedSlotId(defaultRewardedSlotId, adScene, out mapped);
|
||||
slotSource = mapped ? "scene" : "default";
|
||||
return rewardedSlotId;
|
||||
case AD_Type.Interaction:
|
||||
return adConfig?.BaseInteractionAdKeyValue?.value;
|
||||
case AD_Type.Splash:
|
||||
return adConfig?.BaseSplashAdKeyValue?.value;
|
||||
default:
|
||||
slotSource = "unsupported";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string DisplayEditorValue(string value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value) ? "<empty>" : value.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dirichlet.Mediation;
|
||||
using Runtime.ADAggregator;
|
||||
using UnityEngine;
|
||||
@@ -7,8 +8,11 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
{
|
||||
private const float RewardCloseSettleDelaySeconds = 0.25f;
|
||||
|
||||
private readonly Dictionary<string, RewardedSlotCache> _slotCaches = new Dictionary<string, RewardedSlotCache>(StringComparer.Ordinal);
|
||||
|
||||
private DirichletAdNative _adNative;
|
||||
private DirichletRewardVideoAd _loadedAd;
|
||||
private string _defaultSlotId;
|
||||
private string _activeSlotId;
|
||||
private bool _rewardVerified;
|
||||
private bool _rewardVerifyReceived;
|
||||
private bool _closePendingRewardVerify;
|
||||
@@ -22,30 +26,47 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
|
||||
public override void OnInit()
|
||||
{
|
||||
_defaultSlotId = Key;
|
||||
_adNative = DirichletAdManager.CreateAdNative();
|
||||
}
|
||||
|
||||
public override bool IsReadly()
|
||||
{
|
||||
var slotId = ResolveCurrentSlotId();
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
return TapadnAdRequestFactory.TryParseSlotId(Key, out _);
|
||||
return TapadnAdRequestFactory.TryParseSlotId(slotId, out _);
|
||||
}
|
||||
|
||||
if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid)
|
||||
var cache = GetCache(slotId);
|
||||
if (IsCacheReady(cache))
|
||||
{
|
||||
curState = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cache != null && cache.Loading)
|
||||
{
|
||||
curState = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cache != null)
|
||||
{
|
||||
RemoveCache(slotId);
|
||||
}
|
||||
|
||||
curState = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void LoadAD()
|
||||
{
|
||||
if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _))
|
||||
var slotId = ResolveCurrentSlotId(out var mapped);
|
||||
Debug.Log($"[TapADN] Rewarded load requested. scene={NormalizeScenario(AdScene)}, slot={slotId}, source={GetSlotSource(mapped)}, auto={UseAutoLoad()}");
|
||||
if (!TapadnAdRequestFactory.TryParseSlotId(slotId, out _))
|
||||
{
|
||||
Debug.LogError($"[TapADN] Invalid rewarded slot id: {Key}");
|
||||
Debug.LogError($"[TapADN] Invalid rewarded slot id: {slotId}");
|
||||
curState = 0;
|
||||
return;
|
||||
}
|
||||
@@ -55,7 +76,7 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
curState = 2;
|
||||
try
|
||||
{
|
||||
_adNative.PreLoad(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), 3);
|
||||
_adNative.PreLoad(TapadnAdRequestFactory.BuildRewarded(slotId, TapadnAdController.CurrentOptions), 3);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -64,33 +85,37 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
return;
|
||||
}
|
||||
|
||||
if (curState == 1 || IsReadly())
|
||||
var cache = GetCache(slotId);
|
||||
if (cache != null && (cache.Loading || IsCacheReady(cache)))
|
||||
{
|
||||
curState = cache.Loading ? 1 : 2;
|
||||
return;
|
||||
}
|
||||
|
||||
cache = new RewardedSlotCache { Loading = true };
|
||||
_slotCaches[slotId] = cache;
|
||||
curState = 1;
|
||||
TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.AwardVideo, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.AwardVideo, AdScene, slotId);
|
||||
_adNative.LoadRewardVideoAd(
|
||||
TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions),
|
||||
TapadnAdRequestFactory.BuildRewarded(slotId, TapadnAdController.CurrentOptions),
|
||||
ad =>
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, true);
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = ad;
|
||||
_loadedAd.Shown += OnManualShown;
|
||||
_loadedAd.Clicked += OnManualClicked;
|
||||
_loadedAd.ShowFailed += OnManualShowFailed;
|
||||
_loadedAd.RewardVerified += OnManualRewardVerify;
|
||||
_loadedAd.Closed += OnManualClosed;
|
||||
curState = 2;
|
||||
Debug.Log($"[TapADN] Rewarded loaded. slot={Key}");
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, true, slotId);
|
||||
DestroyCachedAd(cache);
|
||||
cache.Ad = ad;
|
||||
cache.Loading = false;
|
||||
cache.LoadedUnix = GetNowUnixSeconds();
|
||||
RegisterManualEvents(slotId, cache.Ad);
|
||||
ScheduleCacheExpiration(slotId, cache);
|
||||
curState = string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal) ? 2 : curState;
|
||||
Debug.Log($"[TapADN] Rewarded loaded. scene={NormalizeScenario(AdScene)}, slot={slotId}");
|
||||
},
|
||||
error =>
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, false);
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Rewarded load failed. code={error.Code}, message={error.Message}");
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, false, slotId);
|
||||
RemoveCache(slotId);
|
||||
curState = string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal) ? 0 : curState;
|
||||
Debug.LogError($"[TapADN] Rewarded load failed. slot={slotId}, code={error.Code}, message={error.Message}");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -104,16 +129,21 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
_showSettled = false;
|
||||
_rewardCloseSettleHandler?.Kill();
|
||||
_rewardCloseSettleHandler = null;
|
||||
_activeSlotId = ResolveCurrentSlotId(out var mapped);
|
||||
Key = _activeSlotId;
|
||||
curState = 0;
|
||||
Debug.Log($"[TapADN] Rewarded show requested. scene={NormalizeScenario(AdScene)}, slot={_activeSlotId}, source={GetSlotSource(mapped)}, auto={UseAutoLoad()}");
|
||||
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
_adNative.ShowRewardVideoAutoAd(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), this);
|
||||
_adNative.ShowRewardVideoAutoAd(TapadnAdRequestFactory.BuildRewarded(_activeSlotId, TapadnAdController.CurrentOptions), this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loadedAd == null || !_loadedAd.Show())
|
||||
var cache = GetCache(_activeSlotId);
|
||||
if (!IsCacheReady(cache) || cache.Ad == null || !cache.Ad.Show())
|
||||
{
|
||||
RemoveCache(_activeSlotId);
|
||||
OnError(new DirichletError("show_failed", "ShowRewardVideoAd returned false"));
|
||||
return;
|
||||
}
|
||||
@@ -130,14 +160,14 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
_rewardCloseSettleHandler?.Kill();
|
||||
_rewardCloseSettleHandler = null;
|
||||
curState = 0;
|
||||
TapadnSmartLoadOrchestrator.OnShowError(AD_Type.AwardVideo, AdScene);
|
||||
Debug.LogError($"[TapADN] Rewarded show failed. code={error?.Code}, message={error?.Message}");
|
||||
TapadnSmartLoadOrchestrator.OnShowError(AD_Type.AwardVideo, AdScene, _activeSlotId);
|
||||
Debug.LogError($"[TapADN] Rewarded show failed. slot={_activeSlotId}, code={error?.Code}, message={error?.Message}");
|
||||
adListener.OnShowError();
|
||||
}
|
||||
|
||||
public void OnAdShow()
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.AwardVideo, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.AwardVideo, AdScene, _activeSlotId);
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
@@ -175,12 +205,41 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
|
||||
public override void OnPlayRequestStarted()
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.AwardVideo, AdScene, !UseAutoLoad() && IsReadly());
|
||||
var slotId = ResolveCurrentSlotId(out var mapped);
|
||||
Key = slotId;
|
||||
Debug.Log($"[TapADN] Rewarded play request. scene={NormalizeScenario(AdScene)}, slot={slotId}, source={GetSlotSource(mapped)}, auto={UseAutoLoad()}");
|
||||
TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.AwardVideo, AdScene, !UseAutoLoad() && IsReadly(), slotId);
|
||||
}
|
||||
|
||||
public override void EnterAdScenario(string scenario)
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.AwardVideo, scenario, Key);
|
||||
AdScene = NormalizeScenario(scenario);
|
||||
var slotId = ResolveCurrentSlotId(out var mapped);
|
||||
Key = slotId;
|
||||
Debug.Log($"[TapADN] Rewarded enter scene. scene={AdScene}, slot={slotId}, source={GetSlotSource(mapped)}");
|
||||
TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.AwardVideo, AdScene, slotId);
|
||||
}
|
||||
|
||||
private string ResolveCurrentSlotId()
|
||||
{
|
||||
return ResolveCurrentSlotId(out _);
|
||||
}
|
||||
|
||||
private string ResolveCurrentSlotId(out bool mapped)
|
||||
{
|
||||
if (TapadnAdController.CurrentOptions == null)
|
||||
{
|
||||
mapped = false;
|
||||
return string.IsNullOrWhiteSpace(_defaultSlotId) ? _defaultSlotId : _defaultSlotId.Trim();
|
||||
}
|
||||
|
||||
var slotId = TapadnAdController.CurrentOptions.ResolveRewardedSlotId(_defaultSlotId, AdScene, out mapped);
|
||||
return string.IsNullOrWhiteSpace(slotId) ? _defaultSlotId : slotId.Trim();
|
||||
}
|
||||
|
||||
private static string GetSlotSource(bool mapped)
|
||||
{
|
||||
return mapped ? "scene" : "default";
|
||||
}
|
||||
|
||||
private bool UseAutoLoad()
|
||||
@@ -188,8 +247,66 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
return TapadnAdController.CurrentOptions?.RewardedAutoLoad ?? true;
|
||||
}
|
||||
|
||||
private void OnManualShown()
|
||||
private RewardedSlotCache GetCache(string slotId)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(slotId) && _slotCaches.TryGetValue(slotId, out var cache) ? cache : null;
|
||||
}
|
||||
|
||||
private bool IsCacheReady(RewardedSlotCache cache)
|
||||
{
|
||||
if (cache == null || cache.Loading || cache.Ad == null || !cache.Ad.IsLoaded || !cache.Ad.IsValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var maxAgeSeconds = TapadnAdController.CurrentOptions?.RewardedCacheMaxAgeSeconds ?? 0;
|
||||
return maxAgeSeconds <= 0 || GetNowUnixSeconds() - cache.LoadedUnix <= maxAgeSeconds;
|
||||
}
|
||||
|
||||
private void RegisterManualEvents(string slotId, DirichletRewardVideoAd ad)
|
||||
{
|
||||
if (ad == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ad.Shown += () => OnManualShown(slotId);
|
||||
ad.Clicked += OnManualClicked;
|
||||
ad.ShowFailed += error => OnManualShowFailed(slotId, error);
|
||||
ad.RewardVerified += OnManualRewardVerify;
|
||||
ad.Closed += () => OnManualClosed(slotId);
|
||||
}
|
||||
|
||||
private void ScheduleCacheExpiration(string slotId, RewardedSlotCache cache)
|
||||
{
|
||||
cache.ExpireHandler?.Kill();
|
||||
cache.ExpireHandler = null;
|
||||
|
||||
var maxAgeSeconds = TapadnAdController.CurrentOptions?.RewardedCacheMaxAgeSeconds ?? 600;
|
||||
if (maxAgeSeconds <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cache.ExpireHandler = ADManager.Instance.CreateTimer(maxAgeSeconds, () =>
|
||||
{
|
||||
if (!ReferenceEquals(GetCache(slotId), cache))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[TapADN] Rewarded cache expired. slot={slotId}, maxAgeSeconds={maxAgeSeconds}");
|
||||
RemoveCache(slotId);
|
||||
if (string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal))
|
||||
{
|
||||
curState = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void OnManualShown(string slotId)
|
||||
{
|
||||
_activeSlotId = slotId;
|
||||
OnAdShow();
|
||||
}
|
||||
|
||||
@@ -197,8 +314,9 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
{
|
||||
}
|
||||
|
||||
private void OnManualShowFailed(DirichletError error)
|
||||
private void OnManualShowFailed(string slotId, DirichletError error)
|
||||
{
|
||||
RemoveCache(slotId);
|
||||
OnError(error);
|
||||
}
|
||||
|
||||
@@ -207,13 +325,49 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
OnRewardVerify(args);
|
||||
}
|
||||
|
||||
private void OnManualClosed()
|
||||
private void OnManualClosed(string slotId)
|
||||
{
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = null;
|
||||
RemoveCache(slotId);
|
||||
OnAdClose();
|
||||
}
|
||||
|
||||
private void RemoveCache(string slotId)
|
||||
{
|
||||
var cache = GetCache(slotId);
|
||||
if (cache == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DestroyCachedAd(cache);
|
||||
_slotCaches.Remove(slotId);
|
||||
}
|
||||
|
||||
private static void DestroyCachedAd(RewardedSlotCache cache)
|
||||
{
|
||||
if (cache?.Ad == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
cache.ExpireHandler?.Kill();
|
||||
cache.ExpireHandler = null;
|
||||
cache.Ad.Destroy();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogWarning($"[TapADN] Rewarded Destroy failed: {exception.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
cache.Ad = null;
|
||||
cache.Loading = false;
|
||||
cache.LoadedUnix = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void CompleteRewardedClose()
|
||||
{
|
||||
if (_showSettled)
|
||||
@@ -228,4 +382,22 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
|
||||
adListener.OnRewardVerify(_rewardVerified, TapadnAdController.CurrentOptions?.RewardAmount ?? 1, TapadnAdController.CurrentOptions?.RewardName ?? string.Empty);
|
||||
adListener.OnAdClose();
|
||||
}
|
||||
|
||||
private static string NormalizeScenario(string scenario)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim();
|
||||
}
|
||||
|
||||
private static long GetNowUnixSeconds()
|
||||
{
|
||||
return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
|
||||
}
|
||||
|
||||
private sealed class RewardedSlotCache
|
||||
{
|
||||
public DirichletRewardVideoAd Ad;
|
||||
public bool Loading;
|
||||
public long LoadedUnix;
|
||||
public AdTimeHandler ExpireHandler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Runtime.ADAggregator;
|
||||
|
||||
public static class TapadnCommercialization
|
||||
@@ -31,4 +32,31 @@ public static class TapadnCommercialization
|
||||
config.BaseSplashAdKeyValue = new AdKeyValue { key = "splash", value = splashSlotId };
|
||||
return config;
|
||||
}
|
||||
|
||||
public static void SetRewardedSceneSlots(ADConfig config, IDictionary<string, string> sceneSlotIds)
|
||||
{
|
||||
if (config == null || sceneSlotIds == null || sceneSlotIds.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.CommonKeyValues == null)
|
||||
{
|
||||
config.CommonKeyValues = new List<AdKeyValue>();
|
||||
}
|
||||
|
||||
foreach (var entry in sceneSlotIds)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.Key) || string.IsNullOrWhiteSpace(entry.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
config.CommonKeyValues.Add(new AdKeyValue
|
||||
{
|
||||
key = TapadnControllerOptions.RewardedSceneSlotPrefix + entry.Key.Trim(),
|
||||
value = entry.Value.Trim()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ using UnityEngine;
|
||||
|
||||
public sealed class TapadnControllerOptions
|
||||
{
|
||||
private const string TapadnKeyPrefix = "tapadn.";
|
||||
|
||||
public const string MediaNameKey = "tapadn.media_name";
|
||||
public const string MediaIdKey = "tapadn.media_id";
|
||||
public const string MediaKeyKey = "tapadn.media_key";
|
||||
@@ -27,6 +29,10 @@ public sealed class TapadnControllerOptions
|
||||
public const string RewardedMaxLoadAttemptsKey = "tapadn.rewarded_max_load_attempts";
|
||||
public const string RewardedLoadRetryDelayMsKey = "tapadn.rewarded_load_retry_delay_ms";
|
||||
public const string RewardedShowTimeoutMsKey = "tapadn.rewarded_show_timeout_ms";
|
||||
public const string RewardedSceneSlotPrefix = "tapadn.rewarded_scene_slot.";
|
||||
public const string RewardedSceneSlotsKey = "tapadn.rewarded_scene_slots";
|
||||
public const string RewardedSceneSlotsJsonKey = "tapadn.rewarded_scene_slots_json";
|
||||
public const string RewardedCacheMaxAgeSecondsKey = "tapadn.rewarded_cache_max_age_seconds";
|
||||
public const string RewardNameKey = "tapadn.reward_name";
|
||||
public const string RewardAmountKey = "tapadn.reward_amount";
|
||||
public const string InterstitialAutoLoadKey = "tapadn.interstitial_auto_load";
|
||||
@@ -64,6 +70,8 @@ public sealed class TapadnControllerOptions
|
||||
public int RewardedMaxLoadAttempts { get; set; } = 1;
|
||||
public int RewardedLoadRetryDelayMs { get; set; } = 500;
|
||||
public int RewardedShowTimeoutMs { get; set; } = 20000;
|
||||
public int RewardedCacheMaxAgeSeconds { get; set; } = 600;
|
||||
public Dictionary<string, string> RewardedSceneSlotIds { get; private set; } = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
public string RewardName { get; set; } = "reward";
|
||||
public int RewardAmount { get; set; } = 1;
|
||||
public bool InterstitialAutoLoad { get; set; } = false;
|
||||
@@ -205,6 +213,11 @@ public sealed class TapadnControllerOptions
|
||||
RewardedMaxLoadAttempts = incoming.RewardedMaxLoadAttempts;
|
||||
RewardedLoadRetryDelayMs = incoming.RewardedLoadRetryDelayMs;
|
||||
RewardedShowTimeoutMs = incoming.RewardedShowTimeoutMs;
|
||||
RewardedCacheMaxAgeSeconds = incoming.RewardedCacheMaxAgeSeconds;
|
||||
if (incoming.RewardedSceneSlotIds != null && incoming.RewardedSceneSlotIds.Count > 0)
|
||||
{
|
||||
RewardedSceneSlotIds = CloneSceneSlotMap(incoming.RewardedSceneSlotIds);
|
||||
}
|
||||
RewardName = incoming.RewardName ?? RewardName;
|
||||
RewardAmount = incoming.RewardAmount;
|
||||
InterstitialAutoLoad = incoming.InterstitialAutoLoad;
|
||||
@@ -266,6 +279,8 @@ public sealed class TapadnControllerOptions
|
||||
RewardedMaxLoadAttempts = GetInt(map, RewardedMaxLoadAttemptsKey) ?? RewardedMaxLoadAttempts;
|
||||
RewardedLoadRetryDelayMs = GetInt(map, RewardedLoadRetryDelayMsKey) ?? RewardedLoadRetryDelayMs;
|
||||
RewardedShowTimeoutMs = GetInt(map, RewardedShowTimeoutMsKey) ?? RewardedShowTimeoutMs;
|
||||
RewardedCacheMaxAgeSeconds = Math.Max(0, GetInt(map, RewardedCacheMaxAgeSecondsKey) ?? RewardedCacheMaxAgeSeconds);
|
||||
ApplyRewardedSceneSlots(map);
|
||||
RewardName = GetString(map, RewardNameKey) ?? RewardName;
|
||||
RewardAmount = GetInt(map, RewardAmountKey) ?? RewardAmount;
|
||||
InterstitialAutoLoad = GetBool(map, InterstitialAutoLoadKey) ?? InterstitialAutoLoad;
|
||||
@@ -286,6 +301,162 @@ public sealed class TapadnControllerOptions
|
||||
ExpressHeight = GetInt(map, ExpressHeightKey) ?? ExpressHeight;
|
||||
}
|
||||
|
||||
public string ResolveRewardedSlotId(string defaultSlotId, string scenario)
|
||||
{
|
||||
return ResolveRewardedSlotId(defaultSlotId, scenario, out _);
|
||||
}
|
||||
|
||||
public string ResolveRewardedSlotId(string defaultSlotId, string scenario, out bool mapped)
|
||||
{
|
||||
var normalizedScenario = NormalizeScenario(scenario);
|
||||
if (RewardedSceneSlotIds != null &&
|
||||
RewardedSceneSlotIds.TryGetValue(normalizedScenario, out var mappedSlotId) &&
|
||||
TapadnAdRequestFactory.TryParseSlotId(mappedSlotId, out _))
|
||||
{
|
||||
mapped = true;
|
||||
return mappedSlotId;
|
||||
}
|
||||
|
||||
mapped = false;
|
||||
return defaultSlotId;
|
||||
}
|
||||
|
||||
private void ApplyRewardedSceneSlots(IDictionary<string, string> map)
|
||||
{
|
||||
ApplyLegacyRewardedSceneSlots(map);
|
||||
|
||||
foreach (var entry in map)
|
||||
{
|
||||
if (entry.Key == null || !entry.Key.StartsWith(RewardedSceneSlotPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var scene = entry.Key.Substring(RewardedSceneSlotPrefix.Length);
|
||||
AddRewardedSceneSlot(scene, entry.Value);
|
||||
}
|
||||
|
||||
ParseSceneSlotPairs(GetString(map, RewardedSceneSlotsKey), AddRewardedSceneSlot);
|
||||
ParseSceneSlotJson(GetString(map, RewardedSceneSlotsJsonKey), AddRewardedSceneSlot);
|
||||
}
|
||||
|
||||
private void ApplyLegacyRewardedSceneSlots(IDictionary<string, string> map)
|
||||
{
|
||||
foreach (var entry in map)
|
||||
{
|
||||
if (!IsLegacyRewardedSceneSlotEntry(entry.Key, entry.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AddRewardedSceneSlot(entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRewardedSceneSlot(string scene, string slotId)
|
||||
{
|
||||
scene = NormalizeScenario(scene);
|
||||
if (string.IsNullOrWhiteSpace(slotId) || !TapadnAdRequestFactory.TryParseSlotId(slotId.Trim(), out _))
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"[TapADN] Ignore invalid rewarded scene slot. scene={scene}, slot={slotId}");
|
||||
return;
|
||||
}
|
||||
|
||||
RewardedSceneSlotIds[scene] = slotId.Trim();
|
||||
}
|
||||
|
||||
private static bool IsLegacyRewardedSceneSlotEntry(string key, string value)
|
||||
{
|
||||
var normalizedKey = key?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(normalizedKey) ||
|
||||
string.IsNullOrWhiteSpace(value) ||
|
||||
normalizedKey.StartsWith(TapadnKeyPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (normalizedKey.ToLowerInvariant())
|
||||
{
|
||||
case "media_id":
|
||||
case "media_name":
|
||||
case "media_key":
|
||||
case "channel":
|
||||
case "sub_channel":
|
||||
case "debug":
|
||||
return false;
|
||||
}
|
||||
|
||||
return TapadnAdRequestFactory.TryParseSlotId(value.Trim(), out _);
|
||||
}
|
||||
|
||||
private static void ParseSceneSlotPairs(string value, Action<string, string> add)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value) || add == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pairs = value.Split(new[] { ',', ';', '\n', '\r', '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var pair in pairs)
|
||||
{
|
||||
var separatorIndex = pair.IndexOf('=');
|
||||
if (separatorIndex < 0)
|
||||
{
|
||||
separatorIndex = pair.IndexOf(':');
|
||||
}
|
||||
|
||||
if (separatorIndex <= 0 || separatorIndex >= pair.Length - 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
add(pair.Substring(0, separatorIndex), pair.Substring(separatorIndex + 1));
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseSceneSlotJson(string json, Action<string, string> add)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json) || add == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var parsed = JsonUtility.FromJson<TapadnSceneSlotMapConfig>(json);
|
||||
if (parsed?.Mappings == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var mapping in parsed.Mappings)
|
||||
{
|
||||
if (mapping == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
add(mapping.Scene, mapping.SlotId);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"[TapADN] Parse rewarded scene slot JSON failed: {exception.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> CloneSceneSlotMap(Dictionary<string, string> source)
|
||||
{
|
||||
return source == null
|
||||
? new Dictionary<string, string>(StringComparer.Ordinal)
|
||||
: new Dictionary<string, string>(source, StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
private static string NormalizeScenario(string scenario)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim();
|
||||
}
|
||||
|
||||
private static string GetString(IDictionary<string, string> map, params string[] keys)
|
||||
{
|
||||
foreach (var key in keys)
|
||||
@@ -383,4 +554,17 @@ public sealed class TapadnControllerOptions
|
||||
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private sealed class TapadnSceneSlotMapConfig
|
||||
{
|
||||
public List<TapadnSceneSlotMapping> Mappings;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private sealed class TapadnSceneSlotMapping
|
||||
{
|
||||
public string Scene;
|
||||
public string SlotId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,12 +56,12 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu
|
||||
}
|
||||
|
||||
curState = 1;
|
||||
TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.Interaction, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.Interaction, AdScene, Key);
|
||||
_adNative.LoadInterstitialAd(
|
||||
TapadnAdRequestFactory.BuildInterstitial(Key, TapadnAdController.CurrentOptions),
|
||||
ad =>
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Interaction, AdScene, true);
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Interaction, AdScene, true, Key);
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = ad;
|
||||
_loadedAd.Shown += OnManualShown;
|
||||
@@ -73,7 +73,7 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu
|
||||
},
|
||||
error =>
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Interaction, AdScene, false);
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Interaction, AdScene, false, Key);
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Interstitial load failed. code={error.Code}, message={error.Message}");
|
||||
});
|
||||
@@ -106,7 +106,7 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu
|
||||
}
|
||||
|
||||
_showSettled = true;
|
||||
TapadnSmartLoadOrchestrator.OnShowError(AD_Type.Interaction, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnShowError(AD_Type.Interaction, AdScene, Key);
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Interstitial show failed. code={error?.Code}, message={error?.Message}");
|
||||
adListener.OnShowError();
|
||||
@@ -114,7 +114,7 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu
|
||||
|
||||
public void OnAdShow()
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Interaction, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Interaction, AdScene, Key);
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
@@ -136,12 +136,13 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu
|
||||
|
||||
public override void OnPlayRequestStarted()
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.Interaction, AdScene, !UseAutoLoad() && IsReadly());
|
||||
TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.Interaction, AdScene, !UseAutoLoad() && IsReadly(), Key);
|
||||
}
|
||||
|
||||
public override void EnterAdScenario(string scenario)
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.Interaction, scenario, Key);
|
||||
AdScene = string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim();
|
||||
TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.Interaction, AdScene, Key);
|
||||
}
|
||||
|
||||
private bool UseAutoLoad()
|
||||
@@ -151,7 +152,7 @@ public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAu
|
||||
|
||||
private void OnManualShown()
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Interaction, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Interaction, AdScene, Key);
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public static class TapadnSmartLoadOrchestrator
|
||||
private static TapadnSmartLoadConfig _runtimeConfig;
|
||||
private static Dictionary<string, TapadnSmartLoadSceneState> _states = new Dictionary<string, TapadnSmartLoadSceneState>(StringComparer.Ordinal);
|
||||
private static Dictionary<string, TapadnSmartLoadPolicyItem> _policies = new Dictionary<string, TapadnSmartLoadPolicyItem>(StringComparer.Ordinal);
|
||||
private static Dictionary<int, TapadnSmartLoadCacheState> _cacheStates = new Dictionary<int, TapadnSmartLoadCacheState>();
|
||||
private static Dictionary<string, TapadnSmartLoadCacheState> _cacheStates = new Dictionary<string, TapadnSmartLoadCacheState>(StringComparer.Ordinal);
|
||||
private static bool _initialized;
|
||||
private static bool _enabled;
|
||||
|
||||
@@ -116,7 +116,7 @@ public static class TapadnSmartLoadOrchestrator
|
||||
_enabled = options?.SmartPreloadEnabled ?? false;
|
||||
_initialized = true;
|
||||
_states = new Dictionary<string, TapadnSmartLoadSceneState>(StringComparer.Ordinal);
|
||||
_cacheStates = new Dictionary<int, TapadnSmartLoadCacheState>();
|
||||
_cacheStates = new Dictionary<string, TapadnSmartLoadCacheState>(StringComparer.Ordinal);
|
||||
LoadStates();
|
||||
EnsureDefaultPolicies(_runtimeConfig);
|
||||
}
|
||||
@@ -135,10 +135,10 @@ public static class TapadnSmartLoadOrchestrator
|
||||
record.ShowRequestCount = Math.Max(0, record.ShowRequestCount);
|
||||
SaveStates();
|
||||
|
||||
TryPreload(adType, normalizedScenario);
|
||||
TryPreload(adType, normalizedScenario, _slotId);
|
||||
}
|
||||
|
||||
public static void OnPlayRequestStarted(AD_Type adType, string scenario, bool cacheReadyAtRequest)
|
||||
public static void OnPlayRequestStarted(AD_Type adType, string scenario, bool cacheReadyAtRequest, string slotId = null)
|
||||
{
|
||||
if (!_initialized || !_enabled)
|
||||
{
|
||||
@@ -152,49 +152,49 @@ public static class TapadnSmartLoadOrchestrator
|
||||
record.LastUpdatedUnix = GetNowUnixSeconds();
|
||||
if (cacheReadyAtRequest)
|
||||
{
|
||||
MarkImmediateHit(adType, normalizedScenario);
|
||||
MarkImmediateHit(adType, normalizedScenario, slotId);
|
||||
}
|
||||
else
|
||||
{
|
||||
MarkCacheExpiredIfStale(adType);
|
||||
MarkCacheExpiredIfStale(adType, slotId);
|
||||
}
|
||||
|
||||
SaveStates();
|
||||
}
|
||||
|
||||
public static void OnLoadRequested(AD_Type adType, string scenario)
|
||||
public static void OnLoadRequested(AD_Type adType, string scenario, string slotId = null)
|
||||
{
|
||||
if (!_initialized || !_enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PrepareSmartLoadRequest(adType, scenario);
|
||||
PrepareSmartLoadRequest(adType, scenario, slotId);
|
||||
}
|
||||
|
||||
public static void OnLoadStarted(AD_Type adType, string scenario)
|
||||
public static void OnLoadStarted(AD_Type adType, string scenario, string slotId = null)
|
||||
{
|
||||
if (!_initialized || !_enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BeginLoadRequest(adType, scenario);
|
||||
BeginLoadRequest(adType, scenario, slotId);
|
||||
SaveStates();
|
||||
}
|
||||
|
||||
public static void OnLoadResult(AD_Type adType, string scenario, bool success)
|
||||
public static void OnLoadResult(AD_Type adType, string scenario, bool success, string slotId = null)
|
||||
{
|
||||
if (!_initialized || !_enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CompleteLoadRequest(adType, scenario, success);
|
||||
CompleteLoadRequest(adType, scenario, success, slotId);
|
||||
SaveStates();
|
||||
}
|
||||
|
||||
public static void OnShowStart(AD_Type adType, string scenario)
|
||||
public static void OnShowStart(AD_Type adType, string scenario, string slotId = null)
|
||||
{
|
||||
if (!_initialized || !_enabled)
|
||||
{
|
||||
@@ -204,11 +204,11 @@ public static class TapadnSmartLoadOrchestrator
|
||||
var record = GetOrCreateState(adType, NormalizeScenario(scenario));
|
||||
record.ShowStartCount = Math.Max(0, record.ShowStartCount) + 1;
|
||||
record.LastUpdatedUnix = GetNowUnixSeconds();
|
||||
MarkCacheConsumed(adType, scenario);
|
||||
MarkCacheConsumed(adType, scenario, slotId);
|
||||
SaveStates();
|
||||
}
|
||||
|
||||
public static void OnShowError(AD_Type adType, string scenario)
|
||||
public static void OnShowError(AD_Type adType, string scenario, string slotId = null)
|
||||
{
|
||||
if (!_initialized || !_enabled)
|
||||
{
|
||||
@@ -218,11 +218,11 @@ public static class TapadnSmartLoadOrchestrator
|
||||
var record = GetOrCreateState(adType, NormalizeScenario(scenario));
|
||||
record.ShowFailureCount = Math.Max(0, record.ShowFailureCount) + 1;
|
||||
record.LastUpdatedUnix = GetNowUnixSeconds();
|
||||
MarkCacheShowFailed(adType, scenario);
|
||||
MarkCacheShowFailed(adType, scenario, slotId);
|
||||
SaveStates();
|
||||
}
|
||||
|
||||
private static void TryPreload(AD_Type adType, string scenario)
|
||||
private static void TryPreload(AD_Type adType, string scenario, string slotId)
|
||||
{
|
||||
if (!_initialized || !_enabled)
|
||||
{
|
||||
@@ -257,11 +257,11 @@ public static class TapadnSmartLoadOrchestrator
|
||||
return;
|
||||
}
|
||||
|
||||
MarkCacheExpiredIfStale(adType);
|
||||
OnLoadRequested(adType, scenario);
|
||||
MarkCacheExpiredIfStale(adType, slotId);
|
||||
OnLoadRequested(adType, scenario, slotId);
|
||||
ADManager.Instance.LoadAD(adType);
|
||||
var smartLoadStarted = HasPendingSmartLoadForScene(adType, scenario);
|
||||
ClearPreparedLoadIfNotStarted(adType);
|
||||
var smartLoadStarted = HasPendingSmartLoadForScene(adType, scenario, slotId);
|
||||
ClearPreparedLoadIfNotStarted(adType, slotId);
|
||||
if (!smartLoadStarted)
|
||||
{
|
||||
return;
|
||||
@@ -302,9 +302,9 @@ public static class TapadnSmartLoadOrchestrator
|
||||
return Mathf.Lerp(policy.BaseProbability, observedRate, trust);
|
||||
}
|
||||
|
||||
private static void PrepareSmartLoadRequest(AD_Type adType, string scenario)
|
||||
private static void PrepareSmartLoadRequest(AD_Type adType, string scenario, string slotId)
|
||||
{
|
||||
var state = GetOrCreateCacheState(adType);
|
||||
var state = GetOrCreateCacheState(adType, slotId);
|
||||
if (state.PendingSmartLoad)
|
||||
{
|
||||
return;
|
||||
@@ -316,9 +316,9 @@ public static class TapadnSmartLoadOrchestrator
|
||||
state.PreparedRequestUnix = GetNowUnixSeconds();
|
||||
}
|
||||
|
||||
private static void BeginLoadRequest(AD_Type adType, string scenario)
|
||||
private static void BeginLoadRequest(AD_Type adType, string scenario, string slotId)
|
||||
{
|
||||
var state = GetOrCreateCacheState(adType);
|
||||
var state = GetOrCreateCacheState(adType, slotId);
|
||||
var now = GetNowUnixSeconds();
|
||||
if (state.PreparedSmartLoad)
|
||||
{
|
||||
@@ -346,9 +346,9 @@ public static class TapadnSmartLoadOrchestrator
|
||||
state.PreparedRequestUnix = 0;
|
||||
}
|
||||
|
||||
private static void ClearPreparedLoadIfNotStarted(AD_Type adType)
|
||||
private static void ClearPreparedLoadIfNotStarted(AD_Type adType, string slotId)
|
||||
{
|
||||
var state = GetOrCreateCacheState(adType);
|
||||
var state = GetOrCreateCacheState(adType, slotId);
|
||||
if (state.PendingSmartLoad)
|
||||
{
|
||||
return;
|
||||
@@ -360,16 +360,16 @@ public static class TapadnSmartLoadOrchestrator
|
||||
state.PreparedRequestUnix = 0;
|
||||
}
|
||||
|
||||
private static bool HasPendingSmartLoadForScene(AD_Type adType, string scenario)
|
||||
private static bool HasPendingSmartLoadForScene(AD_Type adType, string scenario, string slotId)
|
||||
{
|
||||
var state = GetOrCreateCacheState(adType);
|
||||
var state = GetOrCreateCacheState(adType, slotId);
|
||||
return state.PendingSmartLoad &&
|
||||
string.Equals(NormalizeScenario(state.PendingOriginScene), NormalizeScenario(scenario), StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static void CompleteLoadRequest(AD_Type adType, string scenario, bool success)
|
||||
private static void CompleteLoadRequest(AD_Type adType, string scenario, bool success, string slotId)
|
||||
{
|
||||
var cacheState = GetOrCreateCacheState(adType);
|
||||
var cacheState = GetOrCreateCacheState(adType, slotId);
|
||||
var normalizedScenario = NormalizeScenario(scenario);
|
||||
var originScene = cacheState.PendingSmartLoad ? NormalizeScenario(cacheState.PendingOriginScene) : normalizedScenario;
|
||||
var originRecord = GetOrCreateState(adType, originScene);
|
||||
@@ -408,23 +408,23 @@ public static class TapadnSmartLoadOrchestrator
|
||||
cacheState.PendingRequestUnix = 0;
|
||||
}
|
||||
|
||||
private static void MarkImmediateHit(AD_Type adType, string scenario)
|
||||
private static void MarkImmediateHit(AD_Type adType, string scenario, string slotId)
|
||||
{
|
||||
var consumedScene = NormalizeScenario(scenario);
|
||||
var currentSceneRecord = GetOrCreateState(adType, consumedScene);
|
||||
currentSceneRecord.ImmediateHitCount = Math.Max(0, currentSceneRecord.ImmediateHitCount) + 1;
|
||||
currentSceneRecord.LastUpdatedUnix = GetNowUnixSeconds();
|
||||
|
||||
var cacheState = GetOrCreateCacheState(adType);
|
||||
var cacheState = GetOrCreateCacheState(adType, slotId);
|
||||
if (!cacheState.HasReadyCache)
|
||||
{
|
||||
currentSceneRecord.UnattributedCacheHitCount = Math.Max(0, currentSceneRecord.UnattributedCacheHitCount) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void MarkCacheConsumed(AD_Type adType, string scenario)
|
||||
private static void MarkCacheConsumed(AD_Type adType, string scenario, string slotId)
|
||||
{
|
||||
var cacheState = GetOrCreateCacheState(adType);
|
||||
var cacheState = GetOrCreateCacheState(adType, slotId);
|
||||
if (!cacheState.HasReadyCache || cacheState.Consumed)
|
||||
{
|
||||
return;
|
||||
@@ -458,9 +458,9 @@ public static class TapadnSmartLoadOrchestrator
|
||||
ClearReadyCache(cacheState);
|
||||
}
|
||||
|
||||
private static void MarkCacheShowFailed(AD_Type adType, string scenario)
|
||||
private static void MarkCacheShowFailed(AD_Type adType, string scenario, string slotId)
|
||||
{
|
||||
var cacheState = GetOrCreateCacheState(adType);
|
||||
var cacheState = GetOrCreateCacheState(adType, slotId);
|
||||
if (!cacheState.HasReadyCache)
|
||||
{
|
||||
return;
|
||||
@@ -479,9 +479,9 @@ public static class TapadnSmartLoadOrchestrator
|
||||
ClearReadyCache(cacheState);
|
||||
}
|
||||
|
||||
private static void MarkCacheExpiredIfStale(AD_Type adType)
|
||||
private static void MarkCacheExpiredIfStale(AD_Type adType, string slotId)
|
||||
{
|
||||
var cacheState = GetOrCreateCacheState(adType);
|
||||
var cacheState = GetOrCreateCacheState(adType, slotId);
|
||||
if (!cacheState.HasReadyCache)
|
||||
{
|
||||
return;
|
||||
@@ -502,9 +502,9 @@ public static class TapadnSmartLoadOrchestrator
|
||||
ClearReadyCache(cacheState);
|
||||
}
|
||||
|
||||
private static TapadnSmartLoadCacheState GetOrCreateCacheState(AD_Type adType)
|
||||
private static TapadnSmartLoadCacheState GetOrCreateCacheState(AD_Type adType, string slotId)
|
||||
{
|
||||
var key = (int)adType;
|
||||
var key = ComposeCacheKey(adType, slotId);
|
||||
if (_cacheStates.TryGetValue(key, out var state) && state != null)
|
||||
{
|
||||
return state;
|
||||
@@ -879,6 +879,16 @@ public static class TapadnSmartLoadOrchestrator
|
||||
return ((int)adType) + "|" + NormalizeScenario(scenario);
|
||||
}
|
||||
|
||||
private static string ComposeCacheKey(AD_Type adType, string slotId)
|
||||
{
|
||||
return ((int)adType) + "|" + NormalizeSlotId(slotId);
|
||||
}
|
||||
|
||||
private static string NormalizeSlotId(string slotId)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(slotId) ? "__default_slot__" : slotId.Trim();
|
||||
}
|
||||
|
||||
private static string NormalizeScenario(string scenario)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(scenario))
|
||||
|
||||
@@ -56,12 +56,12 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene
|
||||
}
|
||||
|
||||
curState = 1;
|
||||
TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.Splash, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.Splash, AdScene, Key);
|
||||
_adNative.LoadSplashAd(
|
||||
TapadnAdRequestFactory.BuildSplash(Key, TapadnAdController.CurrentOptions),
|
||||
ad =>
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Splash, AdScene, true);
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Splash, AdScene, true, Key);
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = ad;
|
||||
_loadedAd.Shown += OnManualShown;
|
||||
@@ -73,7 +73,7 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene
|
||||
},
|
||||
error =>
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Splash, AdScene, false);
|
||||
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.Splash, AdScene, false, Key);
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Splash load failed. code={error.Code}, message={error.Message}");
|
||||
});
|
||||
@@ -106,7 +106,7 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene
|
||||
}
|
||||
|
||||
_showSettled = true;
|
||||
TapadnSmartLoadOrchestrator.OnShowError(AD_Type.Splash, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnShowError(AD_Type.Splash, AdScene, Key);
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Splash show failed. code={error?.Code}, message={error?.Message}");
|
||||
adListener.OnShowError();
|
||||
@@ -114,7 +114,7 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene
|
||||
|
||||
public void OnAdShow()
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Splash, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Splash, AdScene, Key);
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
@@ -136,12 +136,13 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene
|
||||
|
||||
public override void OnPlayRequestStarted()
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.Splash, AdScene, !UseAutoLoad() && IsReadly());
|
||||
TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.Splash, AdScene, !UseAutoLoad() && IsReadly(), Key);
|
||||
}
|
||||
|
||||
public override void EnterAdScenario(string scenario)
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.Splash, scenario, Key);
|
||||
AdScene = string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim();
|
||||
TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.Splash, AdScene, Key);
|
||||
}
|
||||
|
||||
private bool UseAutoLoad()
|
||||
@@ -151,7 +152,7 @@ public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListene
|
||||
|
||||
private void OnManualShown()
|
||||
{
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Splash, AdScene);
|
||||
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.Splash, AdScene, Key);
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "com.commercialization.tapadn",
|
||||
"displayName": "Commercialization.tapadn",
|
||||
"description": "TapADN / Dirichlet mediation implementation for CC-Framework.Commercialization.",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.8",
|
||||
"unity": "2022.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -15,7 +15,7 @@
|
||||
"url": "https://gitee.com/foldcc"
|
||||
},
|
||||
"dependencies": {
|
||||
"com.foldcc.cc-framework.commercialization": "http://private.lightyears.ltd:18650/foldcc/CC-Framework.Commercialization.git#1.0.15"
|
||||
"com.foldcc.cc-framework.commercialization": "http://private.lightyears.ltd:18650/foldcc/CC-Framework.Commercialization.git#1.0.16"
|
||||
},
|
||||
"samples": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user