You've already forked Commercialization.tapadn
Implement TapADN commercialization module
This commit is contained in:
8
Tapadn_Adapter/Editor.meta
Normal file
8
Tapadn_Adapter/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95121de0d8184f92a4184be55ea40e5b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
285
Tapadn_Adapter/Editor/TapadnBuildAndroidProcess.cs
Normal file
285
Tapadn_Adapter/Editor/TapadnBuildAndroidProcess.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
#if UNITY_ANDROID
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Android;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Tapadn_Adapter.Editor
|
||||
{
|
||||
public sealed class TapadnBuildAndroidProcess : IPostGenerateGradleAndroidProject
|
||||
{
|
||||
private static readonly XNamespace AndroidNamespace = "http://schemas.android.com/apk/res/android";
|
||||
private static readonly XNamespace ToolsNamespace = "http://schemas.android.com/tools";
|
||||
|
||||
public int callbackOrder => 180;
|
||||
|
||||
public void OnPostGenerateGradleAndroidProject(string path)
|
||||
{
|
||||
ProcessGradleProperties(path);
|
||||
ProcessAndroidManifest(path);
|
||||
}
|
||||
|
||||
public static void ProcessAndroidManifest(string path)
|
||||
{
|
||||
var unityManifestPath = Path.Combine(path, "src/main/AndroidManifest.xml");
|
||||
var launcherManifestPath = Path.Combine(path, "../launcher/src/main/AndroidManifest.xml");
|
||||
var providerTargetManifestPath = File.Exists(launcherManifestPath) ? launcherManifestPath : unityManifestPath;
|
||||
|
||||
if (!File.Exists(unityManifestPath))
|
||||
{
|
||||
Debug.LogWarning($"[TapADN] AndroidManifest.xml is missing: {unityManifestPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
var unityManifest = XDocument.Load(unityManifestPath);
|
||||
EnsureManifestPatch(unityManifest, true, false);
|
||||
unityManifest.Save(unityManifestPath);
|
||||
|
||||
if (File.Exists(providerTargetManifestPath))
|
||||
{
|
||||
var providerManifest = XDocument.Load(providerTargetManifestPath);
|
||||
EnsureManifestPatch(providerManifest, false, true);
|
||||
providerManifest.Save(providerTargetManifestPath);
|
||||
}
|
||||
|
||||
var resXmlPath = Path.Combine(path, "src/main/res/xml");
|
||||
Directory.CreateDirectory(resXmlPath);
|
||||
var sourceXmlPath = GetEditorAssetPath("tapad_ad_file_path.xml");
|
||||
if (!string.IsNullOrEmpty(sourceXmlPath) && File.Exists(sourceXmlPath))
|
||||
{
|
||||
File.Copy(sourceXmlPath, Path.Combine(resXmlPath, "tapad_ad_file_path.xml"), true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureManifestPatch(XDocument manifest, bool includeWechatActivity, bool includeTapadProvider)
|
||||
{
|
||||
var manifestElement = manifest.Element("manifest");
|
||||
if (manifestElement == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureNamespace(manifestElement, "tools", ToolsNamespace.NamespaceName);
|
||||
|
||||
EnsurePermission(manifestElement, "android.permission.INTERNET");
|
||||
EnsurePermission(manifestElement, "android.permission.ACCESS_NETWORK_STATE");
|
||||
EnsurePermission(manifestElement, "android.permission.READ_PHONE_STATE");
|
||||
EnsurePermission(manifestElement, "android.permission.QUERY_ALL_PACKAGES");
|
||||
EnsurePermission(manifestElement, "android.permission.REQUEST_INSTALL_PACKAGES");
|
||||
EnsurePermission(manifestElement, "android.permission.BLUETOOTH");
|
||||
EnsurePermission(manifestElement, "android.permission.BLUETOOTH_CONNECT");
|
||||
EnsurePermission(manifestElement, "android.permission.ACCESS_FINE_LOCATION");
|
||||
EnsurePermission(manifestElement, "android.permission.ACCESS_COARSE_LOCATION");
|
||||
EnsurePermission(manifestElement, "android.permission.POST_NOTIFICATIONS");
|
||||
EnsureWechatQueries(manifestElement);
|
||||
|
||||
var applicationElement = manifestElement.Element("application");
|
||||
if (applicationElement == null)
|
||||
{
|
||||
applicationElement = new XElement("application");
|
||||
manifestElement.Add(applicationElement);
|
||||
}
|
||||
|
||||
SetUnityActivitySingleTop(applicationElement);
|
||||
|
||||
if (includeWechatActivity)
|
||||
{
|
||||
EnsureWechatEntryActivity(applicationElement);
|
||||
}
|
||||
|
||||
if (includeTapadProvider)
|
||||
{
|
||||
EnsureTapadFileProvider(applicationElement);
|
||||
SetOrAddAttribute(applicationElement, AndroidNamespace + "allowBackup", "false");
|
||||
MergeToolsReplaceAttribute(applicationElement, "android:allowBackup");
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsurePermission(XElement manifestElement, string permissionName)
|
||||
{
|
||||
var exists = manifestElement.Elements("uses-permission")
|
||||
.Any(element => element.Attribute(AndroidNamespace + "name")?.Value == permissionName);
|
||||
if (exists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var permission = new XElement("uses-permission");
|
||||
permission.Add(new XAttribute(AndroidNamespace + "name", permissionName));
|
||||
if (permissionName == "android.permission.BLUETOOTH_CONNECT" ||
|
||||
permissionName == "android.permission.POST_NOTIFICATIONS")
|
||||
{
|
||||
permission.Add(new XAttribute(ToolsNamespace + "targetApi", permissionName.EndsWith("CONNECT") ? "s" : "33"));
|
||||
}
|
||||
|
||||
manifestElement.Add(permission);
|
||||
}
|
||||
|
||||
private static void EnsureWechatQueries(XElement manifestElement)
|
||||
{
|
||||
var queries = manifestElement.Elements("queries").FirstOrDefault();
|
||||
if (queries == null)
|
||||
{
|
||||
queries = new XElement("queries");
|
||||
manifestElement.Add(queries);
|
||||
}
|
||||
|
||||
var exists = queries.Elements("package")
|
||||
.Any(element => element.Attribute(AndroidNamespace + "name")?.Value == "com.tencent.mm");
|
||||
if (!exists)
|
||||
{
|
||||
var packageElement = new XElement("package");
|
||||
packageElement.Add(new XAttribute(AndroidNamespace + "name", "com.tencent.mm"));
|
||||
queries.Add(packageElement);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureWechatEntryActivity(XElement applicationElement)
|
||||
{
|
||||
RemoveElementsByAndroidName(applicationElement, "activity", ".wxapi.WXEntryActivity");
|
||||
|
||||
var activity = new XElement("activity");
|
||||
activity.Add(new XAttribute(AndroidNamespace + "name", ".wxapi.WXEntryActivity"));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "label", "@string/app_name"));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "theme", "@android:style/Theme.Translucent.NoTitleBar"));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "exported", "true"));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "taskAffinity", Application.identifier));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "launchMode", "singleTop"));
|
||||
applicationElement.Add(activity);
|
||||
}
|
||||
|
||||
private static void EnsureTapadFileProvider(XElement applicationElement)
|
||||
{
|
||||
RemoveElementsByAndroidName(applicationElement, "provider", "com.tapsdk.tapad.internal.TapADFileProvider");
|
||||
|
||||
var provider = new XElement("provider");
|
||||
provider.Add(new XAttribute(AndroidNamespace + "name", "com.tapsdk.tapad.internal.TapADFileProvider"));
|
||||
provider.Add(new XAttribute(AndroidNamespace + "authorities", "${applicationId}.com.tds.ad.fileprovider"));
|
||||
provider.Add(new XAttribute(AndroidNamespace + "exported", "false"));
|
||||
provider.Add(new XAttribute(AndroidNamespace + "grantUriPermissions", "true"));
|
||||
provider.Add(new XAttribute(ToolsNamespace + "replace", "android:authorities"));
|
||||
|
||||
var metadata = new XElement("meta-data");
|
||||
metadata.Add(new XAttribute(AndroidNamespace + "name", "android.support.FILE_PROVIDER_PATHS"));
|
||||
metadata.Add(new XAttribute(AndroidNamespace + "resource", "@xml/tapad_ad_file_path"));
|
||||
provider.Add(metadata);
|
||||
|
||||
applicationElement.Add(provider);
|
||||
}
|
||||
|
||||
private static void SetUnityActivitySingleTop(XElement applicationElement)
|
||||
{
|
||||
foreach (var activity in applicationElement.Elements("activity"))
|
||||
{
|
||||
var name = activity.Attribute(AndroidNamespace + "name")?.Value;
|
||||
if (name == "com.unity3d.player.UnityPlayerActivity")
|
||||
{
|
||||
SetOrAddAttribute(activity, AndroidNamespace + "launchMode", "singleTop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RemoveElementsByAndroidName(XElement parent, string localName, string androidName)
|
||||
{
|
||||
parent.Elements(localName)
|
||||
.Where(element => element.Attribute(AndroidNamespace + "name")?.Value == androidName)
|
||||
.ToList()
|
||||
.ForEach(element => element.Remove());
|
||||
}
|
||||
|
||||
private static void ProcessGradleProperties(string path)
|
||||
{
|
||||
var root = Directory.GetParent(path)?.FullName;
|
||||
if (string.IsNullOrEmpty(root))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var gradlePropertiesPath = Path.Combine(root, "gradle.properties");
|
||||
var lines = File.Exists(gradlePropertiesPath)
|
||||
? File.ReadAllLines(gradlePropertiesPath).ToList()
|
||||
: new List<string>();
|
||||
|
||||
UpsertProperty(lines, "android.useAndroidX", "true");
|
||||
UpsertProperty(lines, "android.enableJetifier", "true");
|
||||
|
||||
File.WriteAllText(gradlePropertiesPath, string.Join("\n", lines) + "\n");
|
||||
}
|
||||
|
||||
private static void UpsertProperty(List<string> lines, string key, string value)
|
||||
{
|
||||
var prefix = key + "=";
|
||||
var index = lines.FindIndex(line => line.TrimStart().StartsWith(prefix));
|
||||
if (index >= 0)
|
||||
{
|
||||
lines[index] = prefix + value;
|
||||
return;
|
||||
}
|
||||
|
||||
lines.Add(prefix + value);
|
||||
}
|
||||
|
||||
private static void SetOrAddAttribute(XElement element, XName attributeName, string value)
|
||||
{
|
||||
var attribute = element.Attribute(attributeName);
|
||||
if (attribute == null)
|
||||
{
|
||||
element.Add(new XAttribute(attributeName, value));
|
||||
return;
|
||||
}
|
||||
|
||||
attribute.SetValue(value);
|
||||
}
|
||||
|
||||
private static void MergeToolsReplaceAttribute(XElement element, params string[] replaceValues)
|
||||
{
|
||||
var replaceAttributeName = ToolsNamespace + "replace";
|
||||
var mergedValues = new List<string>();
|
||||
var currentValue = element.Attribute(replaceAttributeName)?.Value;
|
||||
if (!string.IsNullOrWhiteSpace(currentValue))
|
||||
{
|
||||
mergedValues.AddRange(currentValue.Split(',')
|
||||
.Select(value => value.Trim())
|
||||
.Where(value => !string.IsNullOrWhiteSpace(value)));
|
||||
}
|
||||
|
||||
foreach (var replaceValue in replaceValues)
|
||||
{
|
||||
if (!mergedValues.Contains(replaceValue))
|
||||
{
|
||||
mergedValues.Add(replaceValue);
|
||||
}
|
||||
}
|
||||
|
||||
element.SetAttributeValue(replaceAttributeName, string.Join(",", mergedValues));
|
||||
}
|
||||
|
||||
private static void EnsureNamespace(XElement element, string prefix, string namespaceName)
|
||||
{
|
||||
var namespaceAttributeName = XNamespace.Xmlns + prefix;
|
||||
if (element.Attribute(namespaceAttributeName) == null)
|
||||
{
|
||||
element.Add(new XAttribute(namespaceAttributeName, namespaceName));
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetEditorAssetPath(string fileName)
|
||||
{
|
||||
var guids = AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(fileName));
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (Path.GetFileName(path) == fileName)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Tapadn_Adapter/Editor/TapadnBuildAndroidProcess.cs.meta
Normal file
11
Tapadn_Adapter/Editor/TapadnBuildAndroidProcess.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ab0342739d64cabbf5360a6f49250a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
15
Tapadn_Adapter/Editor/Tapadn_Adapter.Editor.asmdef
Normal file
15
Tapadn_Adapter/Editor/Tapadn_Adapter.Editor.asmdef
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Tapadn_Adapter.Editor",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Tapadn_Adapter/Editor/Tapadn_Adapter.Editor.asmdef.meta
Normal file
7
Tapadn_Adapter/Editor/Tapadn_Adapter.Editor.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d92d8c493204ca298403fceb36f5a71
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
11
Tapadn_Adapter/Editor/WXDependencies.xml
Normal file
11
Tapadn_Adapter/Editor/WXDependencies.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?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>
|
||||
</dependencies>
|
||||
7
Tapadn_Adapter/Editor/WXDependencies.xml.meta
Normal file
7
Tapadn_Adapter/Editor/WXDependencies.xml.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea7cb8d4cc2e4dce8859500b44a86028
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
7
Tapadn_Adapter/Editor/tapad_ad_file_path.xml
Normal file
7
Tapadn_Adapter/Editor/tapad_ad_file_path.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<external-path name="external" path="." />
|
||||
<external-files-path name="external_files" path="." />
|
||||
<files-path name="files" path="." />
|
||||
<cache-path name="cache" path="." />
|
||||
</paths>
|
||||
7
Tapadn_Adapter/Editor/tapad_ad_file_path.xml.meta
Normal file
7
Tapadn_Adapter/Editor/tapad_ad_file_path.xml.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcb4be7a15dd43aaa4862ab35f8b309b
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Tapadn_Adapter/Runtime.meta
Normal file
8
Tapadn_Adapter/Runtime.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9c09f845d424a529010aa7f15b05e9c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Tapadn_Adapter/Runtime/Scripts.meta
Normal file
8
Tapadn_Adapter/Runtime/Scripts.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a07b2d839f4748b0b52bd5bcb950f111
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
75
Tapadn_Adapter/Runtime/Scripts/TapadnAdController.cs
Normal file
75
Tapadn_Adapter/Runtime/Scripts/TapadnAdController.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using Dirichlet.Mediation;
|
||||
using Runtime.ADAggregator;
|
||||
using UnityEngine;
|
||||
|
||||
public sealed class TapadnAdController : IAdController
|
||||
{
|
||||
public static TapadnControllerOptions CurrentOptions { get; private set; }
|
||||
public static string LastSdkVersion { get; private set; }
|
||||
public static string LastInitError { get; private set; }
|
||||
|
||||
private Action<bool> _maskAction;
|
||||
private Action<string, string> _logEventAction;
|
||||
private ADConfig _adConfig;
|
||||
private TapadnControllerOptions _options;
|
||||
|
||||
public void Init(ADConfig adConfig, object[] args)
|
||||
{
|
||||
_adConfig = adConfig;
|
||||
_options = TapadnControllerOptions.Resolve(adConfig, args);
|
||||
CurrentOptions = _options;
|
||||
|
||||
var sdkConfig = _options.BuildSdkConfig();
|
||||
DirichletSdk.Init(
|
||||
sdkConfig,
|
||||
result =>
|
||||
{
|
||||
LastInitError = null;
|
||||
LastSdkVersion = DirichletSdk.GetVersion();
|
||||
EventLog("tapadn_init", "success", result?.Message);
|
||||
Debug.Log($"[TapADN] Init success. version={LastSdkVersion}, message={result?.Message}");
|
||||
if (_options.RequestPermissionOnInit)
|
||||
{
|
||||
DirichletSdk.RequestPermissionIfNecessary();
|
||||
}
|
||||
},
|
||||
error =>
|
||||
{
|
||||
LastInitError = $"{error?.Code}:{error?.Message}";
|
||||
EventLog("tapadn_init_error", error?.Code ?? "unknown", error?.Message);
|
||||
Debug.LogError($"[TapADN] Init failed. code={error?.Code}, message={error?.Message}");
|
||||
});
|
||||
}
|
||||
|
||||
public void SetListener(Action<bool> adMaskAction, Action<string, string> logEventAction)
|
||||
{
|
||||
_maskAction = adMaskAction;
|
||||
_logEventAction = logEventAction;
|
||||
}
|
||||
|
||||
public ADPlayer CreateAdPlayer(AD_Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case AD_Type.AwardVideo:
|
||||
return new TapadnAwardVideoPlayer().Init(_adConfig?.BaseAwardAdKeyValue?.value);
|
||||
case AD_Type.Interaction:
|
||||
return new TapadnInteractionPlayer().Init(_adConfig?.BaseInteractionAdKeyValue?.value);
|
||||
case AD_Type.Splash:
|
||||
return new TapadnSplashPlayer().Init(_adConfig?.BaseSplashAdKeyValue?.value);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void EventLog(string eventTable, string eventValue, string eventMessage = null)
|
||||
{
|
||||
_logEventAction?.Invoke(eventTable, eventValue);
|
||||
}
|
||||
|
||||
public void SetMask(bool isOpen)
|
||||
{
|
||||
_maskAction?.Invoke(isOpen);
|
||||
}
|
||||
}
|
||||
11
Tapadn_Adapter/Runtime/Scripts/TapadnAdController.cs.meta
Normal file
11
Tapadn_Adapter/Runtime/Scripts/TapadnAdController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a08780bf18a349b58a35e2dfb79d0743
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
55
Tapadn_Adapter/Runtime/Scripts/TapadnAdRequestFactory.cs
Normal file
55
Tapadn_Adapter/Runtime/Scripts/TapadnAdRequestFactory.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using Dirichlet.Mediation;
|
||||
using Runtime.ADAggregator;
|
||||
using UnityEngine;
|
||||
|
||||
internal static class TapadnAdRequestFactory
|
||||
{
|
||||
public static bool TryParseSlotId(string slotId, out long parsed)
|
||||
{
|
||||
return long.TryParse(slotId, out parsed) && parsed > 0;
|
||||
}
|
||||
|
||||
public static DirichletAdRequest BuildRewarded(string slotId, TapadnControllerOptions options)
|
||||
{
|
||||
var builder = CreateBaseBuilder(slotId)
|
||||
.WithUserId(ADManager.Instance.UserId)
|
||||
.WithRewardName(options?.RewardName ?? "reward")
|
||||
.WithRewardAmount(options?.RewardAmount ?? 1);
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
public static DirichletAdRequest BuildInterstitial(string slotId, TapadnControllerOptions options)
|
||||
{
|
||||
return ApplyExpressSize(CreateBaseBuilder(slotId), options).Build();
|
||||
}
|
||||
|
||||
public static DirichletAdRequest BuildSplash(string slotId, TapadnControllerOptions options)
|
||||
{
|
||||
var builder = CreateBaseBuilder(slotId);
|
||||
var width = options?.ExpressWidth ?? Screen.width;
|
||||
var height = options?.ExpressHeight ?? Screen.height;
|
||||
return builder.WithExpressViewSize(width, height).Build();
|
||||
}
|
||||
|
||||
private static DirichletAdRequest.Builder CreateBaseBuilder(string slotId)
|
||||
{
|
||||
if (!TryParseSlotId(slotId, out var parsed))
|
||||
{
|
||||
throw new ArgumentException($"TapADN slot id must be a positive integer. Current value: {slotId}", nameof(slotId));
|
||||
}
|
||||
|
||||
return new DirichletAdRequest.Builder().WithSpaceId(parsed);
|
||||
}
|
||||
|
||||
private static DirichletAdRequest.Builder ApplyExpressSize(DirichletAdRequest.Builder builder, TapadnControllerOptions options)
|
||||
{
|
||||
if (options?.ExpressWidth != null || options?.ExpressHeight != null)
|
||||
{
|
||||
builder.WithExpressViewSize(options?.ExpressWidth ?? Screen.width, options?.ExpressHeight ?? Screen.height);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01ac342b5e1c49cf87b649eddcd34f7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
159
Tapadn_Adapter/Runtime/Scripts/TapadnAwardVideoPlayer.cs
Normal file
159
Tapadn_Adapter/Runtime/Scripts/TapadnAwardVideoPlayer.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using Dirichlet.Mediation;
|
||||
using Runtime.ADAggregator;
|
||||
using UnityEngine;
|
||||
|
||||
public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAutoAdListener
|
||||
{
|
||||
private DirichletAdNative _adNative;
|
||||
private DirichletRewardVideoAd _loadedAd;
|
||||
private bool _rewardVerified;
|
||||
|
||||
public override int MaxLoadAttempts => TapadnAdController.CurrentOptions?.RewardedMaxLoadAttempts ?? base.MaxLoadAttempts;
|
||||
public override float LoadRetryDelaySeconds => Math.Max(0f, (TapadnAdController.CurrentOptions?.RewardedLoadRetryDelayMs ?? 500) / 1000f);
|
||||
public override float ShowPendingTimeoutSeconds => Math.Max(1f, (TapadnAdController.CurrentOptions?.RewardedShowTimeoutMs ?? 20000) / 1000f);
|
||||
public override bool AutoPreloadOnInit => TapadnAdController.CurrentOptions?.RewardedPrewarmOnInit ?? false;
|
||||
|
||||
public override void OnInit()
|
||||
{
|
||||
_adNative = DirichletAdManager.CreateAdNative();
|
||||
}
|
||||
|
||||
public override bool IsReadly()
|
||||
{
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
return TapadnAdRequestFactory.TryParseSlotId(Key, out _);
|
||||
}
|
||||
|
||||
if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid)
|
||||
{
|
||||
curState = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void LoadAD()
|
||||
{
|
||||
if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _))
|
||||
{
|
||||
Debug.LogError($"[TapADN] Invalid rewarded slot id: {Key}");
|
||||
curState = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
curState = 2;
|
||||
try
|
||||
{
|
||||
_adNative.PreLoad(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), 3);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogWarning($"[TapADN] Rewarded preload skipped: {exception.Message}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (curState == 1 || IsReadly())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
curState = 1;
|
||||
_adNative.LoadRewardVideoAd(
|
||||
TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions),
|
||||
ad =>
|
||||
{
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = ad;
|
||||
_loadedAd.Shown += OnManualShown;
|
||||
_loadedAd.Clicked += OnManualClicked;
|
||||
_loadedAd.RewardVerified += OnManualRewardVerify;
|
||||
_loadedAd.Closed += OnManualClosed;
|
||||
curState = 2;
|
||||
Debug.Log($"[TapADN] Rewarded loaded. slot={Key}");
|
||||
},
|
||||
error =>
|
||||
{
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Rewarded load failed. code={error.Code}, message={error.Message}");
|
||||
});
|
||||
}
|
||||
|
||||
public override void ShowAD(Action onClose, Action<bool> onVideoComplete)
|
||||
{
|
||||
adListener.onClose = onClose;
|
||||
adListener.onVideoComplete = onVideoComplete;
|
||||
_rewardVerified = false;
|
||||
curState = 0;
|
||||
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
_adNative.ShowRewardVideoAutoAd(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loadedAd == null || !_loadedAd.Show())
|
||||
{
|
||||
adListener.OnShowError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnError(DirichletError error)
|
||||
{
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Rewarded show failed. code={error?.Code}, message={error?.Message}");
|
||||
adListener.OnShowError();
|
||||
}
|
||||
|
||||
public void OnAdShow()
|
||||
{
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
public void OnAdClose()
|
||||
{
|
||||
adListener.OnRewardVerify(_rewardVerified, TapadnAdController.CurrentOptions?.RewardAmount ?? 1, TapadnAdController.CurrentOptions?.RewardName ?? string.Empty);
|
||||
adListener.OnAdClose();
|
||||
}
|
||||
|
||||
public void OnRewardVerify(DirichletRewardVerificationEventArgs args)
|
||||
{
|
||||
_rewardVerified = args != null && args.IsVerified;
|
||||
}
|
||||
|
||||
public void OnAdClick()
|
||||
{
|
||||
}
|
||||
|
||||
private bool UseAutoLoad()
|
||||
{
|
||||
return TapadnAdController.CurrentOptions?.RewardedAutoLoad ?? true;
|
||||
}
|
||||
|
||||
private void OnManualShown()
|
||||
{
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
private void OnManualClicked()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnManualRewardVerify(DirichletRewardVerificationEventArgs args)
|
||||
{
|
||||
_rewardVerified = args != null && args.IsVerified;
|
||||
}
|
||||
|
||||
private void OnManualClosed()
|
||||
{
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = null;
|
||||
OnAdClose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb7643101da94ca69dc8f99128d4e759
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Tapadn_Adapter/Runtime/Scripts/TapadnCommercialization.cs
Normal file
34
Tapadn_Adapter/Runtime/Scripts/TapadnCommercialization.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using Runtime.ADAggregator;
|
||||
|
||||
public static class TapadnCommercialization
|
||||
{
|
||||
public static TapadnAdController CreateController()
|
||||
{
|
||||
return new TapadnAdController();
|
||||
}
|
||||
|
||||
public static void InitADManager(Action onCallback, string userId, ADConfig adConfig, params object[] args)
|
||||
{
|
||||
ADManager.Instance.Init(onCallback, userId, adConfig, CreateController(), args);
|
||||
}
|
||||
|
||||
public static ADConfig CreateConfig(
|
||||
string mediaId,
|
||||
string mediaKey,
|
||||
string mediaName,
|
||||
string rewardSlotId,
|
||||
string interstitialSlotId = null,
|
||||
string splashSlotId = null)
|
||||
{
|
||||
var config = UnityEngine.ScriptableObject.CreateInstance<ADConfig>();
|
||||
config.ConfigName = "TapADN";
|
||||
config.Id = mediaId;
|
||||
config.Key = mediaKey;
|
||||
config.Key2 = mediaName;
|
||||
config.BaseAwardAdKeyValue = new AdKeyValue { key = "reward", value = rewardSlotId };
|
||||
config.BaseInteractionAdKeyValue = new AdKeyValue { key = "interaction", value = interstitialSlotId };
|
||||
config.BaseSplashAdKeyValue = new AdKeyValue { key = "splash", value = splashSlotId };
|
||||
return config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 295d10d222a8496e872b02eff3556e86
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
370
Tapadn_Adapter/Runtime/Scripts/TapadnControllerOptions.cs
Normal file
370
Tapadn_Adapter/Runtime/Scripts/TapadnControllerOptions.cs
Normal file
@@ -0,0 +1,370 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Dirichlet.Mediation;
|
||||
using Runtime.ADAggregator;
|
||||
using UnityEngine;
|
||||
|
||||
public sealed class TapadnControllerOptions
|
||||
{
|
||||
public const string MediaNameKey = "tapadn.media_name";
|
||||
public const string MediaIdKey = "tapadn.media_id";
|
||||
public const string MediaKeyKey = "tapadn.media_key";
|
||||
public const string ChannelKey = "tapadn.channel";
|
||||
public const string SubChannelKey = "tapadn.sub_channel";
|
||||
public const string DebugKey = "tapadn.debug";
|
||||
public const string TapClientIdKey = "tapadn.tap_client_id";
|
||||
public const string ShakeEnabledKey = "tapadn.shake_enabled";
|
||||
public const string CustomConfigJsonKey = "tapadn.custom_config_json";
|
||||
public const string DataJsonKey = "tapadn.data_json";
|
||||
public const string ATagsKey = "tapadn.atags";
|
||||
public const string AllowIdfaAccessKey = "tapadn.allow_idfa_access";
|
||||
public const string RequestPermissionOnInitKey = "tapadn.request_permission_on_init";
|
||||
public const string RewardedAutoLoadKey = "tapadn.rewarded_auto_load";
|
||||
public const string RewardedPrewarmOnInitKey = "tapadn.rewarded_prewarm_on_init";
|
||||
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 RewardNameKey = "tapadn.reward_name";
|
||||
public const string RewardAmountKey = "tapadn.reward_amount";
|
||||
public const string InterstitialAutoLoadKey = "tapadn.interstitial_auto_load";
|
||||
public const string InterstitialPrewarmOnInitKey = "tapadn.interstitial_prewarm_on_init";
|
||||
public const string InterstitialMaxLoadAttemptsKey = "tapadn.interstitial_max_load_attempts";
|
||||
public const string InterstitialLoadRetryDelayMsKey = "tapadn.interstitial_load_retry_delay_ms";
|
||||
public const string InterstitialShowTimeoutMsKey = "tapadn.interstitial_show_timeout_ms";
|
||||
public const string SplashAutoLoadKey = "tapadn.splash_auto_load";
|
||||
public const string SplashPrewarmOnInitKey = "tapadn.splash_prewarm_on_init";
|
||||
public const string SplashMaxLoadAttemptsKey = "tapadn.splash_max_load_attempts";
|
||||
public const string SplashLoadRetryDelayMsKey = "tapadn.splash_load_retry_delay_ms";
|
||||
public const string SplashShowTimeoutMsKey = "tapadn.splash_show_timeout_ms";
|
||||
public const string ExpressWidthKey = "tapadn.express_width";
|
||||
public const string ExpressHeightKey = "tapadn.express_height";
|
||||
|
||||
public long MediaId { get; set; }
|
||||
public string MediaName { get; set; }
|
||||
public string MediaKey { get; set; }
|
||||
public string Channel { get; set; } = "default";
|
||||
public string SubChannel { get; set; }
|
||||
public bool Debug { get; set; }
|
||||
public string TapClientId { get; set; }
|
||||
public bool ShakeEnabled { get; set; } = true;
|
||||
public string CustomConfigJson { get; set; }
|
||||
public string DataJson { get; set; }
|
||||
public string ATags { get; set; }
|
||||
public bool AllowIDFAAccess { get; set; } = true;
|
||||
public bool RequestPermissionOnInit { get; set; }
|
||||
public bool RewardedAutoLoad { get; set; } = true;
|
||||
public bool RewardedPrewarmOnInit { get; set; }
|
||||
public int RewardedMaxLoadAttempts { get; set; } = 1;
|
||||
public int RewardedLoadRetryDelayMs { get; set; } = 500;
|
||||
public int RewardedShowTimeoutMs { get; set; } = 20000;
|
||||
public string RewardName { get; set; } = "reward";
|
||||
public int RewardAmount { get; set; } = 1;
|
||||
public bool InterstitialAutoLoad { get; set; } = true;
|
||||
public bool InterstitialPrewarmOnInit { get; set; }
|
||||
public int InterstitialMaxLoadAttempts { get; set; } = 1;
|
||||
public int InterstitialLoadRetryDelayMs { get; set; } = 500;
|
||||
public int InterstitialShowTimeoutMs { get; set; } = 20000;
|
||||
public bool SplashAutoLoad { get; set; } = true;
|
||||
public bool SplashPrewarmOnInit { get; set; }
|
||||
public int SplashMaxLoadAttempts { get; set; } = 1;
|
||||
public int SplashLoadRetryDelayMs { get; set; } = 500;
|
||||
public int SplashShowTimeoutMs { get; set; } = 20000;
|
||||
public int? ExpressWidth { get; set; }
|
||||
public int? ExpressHeight { get; set; }
|
||||
|
||||
public static TapadnControllerOptions Resolve(ADConfig adConfig, object[] args)
|
||||
{
|
||||
var options = new TapadnControllerOptions();
|
||||
options.ApplyAdConfig(adConfig);
|
||||
options.ApplyLegacyArgs(args);
|
||||
|
||||
if (args == null)
|
||||
{
|
||||
return options;
|
||||
}
|
||||
|
||||
foreach (var arg in args)
|
||||
{
|
||||
switch (arg)
|
||||
{
|
||||
case TapadnControllerOptions explicitOptions:
|
||||
options.ApplyExplicitOptions(explicitOptions);
|
||||
break;
|
||||
case IDictionary dictionary:
|
||||
options.ApplyDictionary(dictionary);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public DirichletAdConfig BuildSdkConfig()
|
||||
{
|
||||
return new DirichletAdConfig.Builder()
|
||||
.WithMediaId(MediaId)
|
||||
.WithMediaName(string.IsNullOrWhiteSpace(MediaName) ? Application.productName : MediaName)
|
||||
.WithMediaKey(MediaKey)
|
||||
.WithGameChannel(string.IsNullOrWhiteSpace(Channel) ? "default" : Channel)
|
||||
.WithSubChannel(SubChannel)
|
||||
.EnableDebug(Debug)
|
||||
.WithTapClientId(TapClientId)
|
||||
.ShakeEnabled(ShakeEnabled)
|
||||
.WithCustomConfigJson(CustomConfigJson)
|
||||
.WithDataJson(DataJson)
|
||||
.AllowIDFAAccess(AllowIDFAAccess)
|
||||
.WithATags(ATags)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private void ApplyAdConfig(ADConfig adConfig)
|
||||
{
|
||||
if (adConfig == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MediaId = ParseLong(adConfig.Id) ?? MediaId;
|
||||
MediaKey = string.IsNullOrWhiteSpace(adConfig.Key) ? MediaKey : adConfig.Key.Trim();
|
||||
MediaName = string.IsNullOrWhiteSpace(adConfig.Key2) ? MediaName : adConfig.Key2.Trim();
|
||||
ApplyCommonKeyValues(adConfig.CommonKeyValues);
|
||||
}
|
||||
|
||||
private void ApplyCommonKeyValues(List<AdKeyValue> keyValues)
|
||||
{
|
||||
if (keyValues == null || keyValues.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var keyValue in keyValues)
|
||||
{
|
||||
if (keyValue == null || string.IsNullOrWhiteSpace(keyValue.key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
map[keyValue.key.Trim()] = keyValue.value;
|
||||
}
|
||||
|
||||
ApplyMap(map);
|
||||
}
|
||||
|
||||
private void ApplyLegacyArgs(object[] args)
|
||||
{
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Length > 0 && args[0] is string channel)
|
||||
{
|
||||
Channel = channel;
|
||||
}
|
||||
|
||||
if (args.Length > 1 && TryConvertBool(args[1], out var debug))
|
||||
{
|
||||
Debug = debug;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyExplicitOptions(TapadnControllerOptions incoming)
|
||||
{
|
||||
if (incoming == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MediaId = incoming.MediaId > 0 ? incoming.MediaId : MediaId;
|
||||
MediaName = incoming.MediaName ?? MediaName;
|
||||
MediaKey = incoming.MediaKey ?? MediaKey;
|
||||
Channel = incoming.Channel ?? Channel;
|
||||
SubChannel = incoming.SubChannel ?? SubChannel;
|
||||
Debug = incoming.Debug;
|
||||
TapClientId = incoming.TapClientId ?? TapClientId;
|
||||
ShakeEnabled = incoming.ShakeEnabled;
|
||||
CustomConfigJson = incoming.CustomConfigJson ?? CustomConfigJson;
|
||||
DataJson = incoming.DataJson ?? DataJson;
|
||||
ATags = incoming.ATags ?? ATags;
|
||||
AllowIDFAAccess = incoming.AllowIDFAAccess;
|
||||
RequestPermissionOnInit = incoming.RequestPermissionOnInit;
|
||||
RewardedAutoLoad = incoming.RewardedAutoLoad;
|
||||
RewardedPrewarmOnInit = incoming.RewardedPrewarmOnInit;
|
||||
RewardedMaxLoadAttempts = incoming.RewardedMaxLoadAttempts;
|
||||
RewardedLoadRetryDelayMs = incoming.RewardedLoadRetryDelayMs;
|
||||
RewardedShowTimeoutMs = incoming.RewardedShowTimeoutMs;
|
||||
RewardName = incoming.RewardName ?? RewardName;
|
||||
RewardAmount = incoming.RewardAmount;
|
||||
InterstitialAutoLoad = incoming.InterstitialAutoLoad;
|
||||
InterstitialPrewarmOnInit = incoming.InterstitialPrewarmOnInit;
|
||||
InterstitialMaxLoadAttempts = incoming.InterstitialMaxLoadAttempts;
|
||||
InterstitialLoadRetryDelayMs = incoming.InterstitialLoadRetryDelayMs;
|
||||
InterstitialShowTimeoutMs = incoming.InterstitialShowTimeoutMs;
|
||||
SplashAutoLoad = incoming.SplashAutoLoad;
|
||||
SplashPrewarmOnInit = incoming.SplashPrewarmOnInit;
|
||||
SplashMaxLoadAttempts = incoming.SplashMaxLoadAttempts;
|
||||
SplashLoadRetryDelayMs = incoming.SplashLoadRetryDelayMs;
|
||||
SplashShowTimeoutMs = incoming.SplashShowTimeoutMs;
|
||||
ExpressWidth = incoming.ExpressWidth ?? ExpressWidth;
|
||||
ExpressHeight = incoming.ExpressHeight ?? ExpressHeight;
|
||||
}
|
||||
|
||||
private void ApplyDictionary(IDictionary dictionary)
|
||||
{
|
||||
if (dictionary == null || dictionary.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (DictionaryEntry entry in dictionary)
|
||||
{
|
||||
if (entry.Key == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
map[entry.Key.ToString()] = ConvertDictionaryValue(entry.Value);
|
||||
}
|
||||
|
||||
ApplyMap(map);
|
||||
}
|
||||
|
||||
private void ApplyMap(IDictionary<string, string> map)
|
||||
{
|
||||
MediaId = GetLong(map, MediaIdKey, "media_id") ?? MediaId;
|
||||
MediaName = GetString(map, MediaNameKey, "media_name") ?? MediaName;
|
||||
MediaKey = GetString(map, MediaKeyKey, "media_key") ?? MediaKey;
|
||||
Channel = GetString(map, ChannelKey, "channel") ?? Channel;
|
||||
SubChannel = GetString(map, SubChannelKey, "sub_channel") ?? SubChannel;
|
||||
Debug = GetBool(map, DebugKey, "debug") ?? Debug;
|
||||
TapClientId = GetString(map, TapClientIdKey, "tap_client_id") ?? TapClientId;
|
||||
ShakeEnabled = GetBool(map, ShakeEnabledKey) ?? ShakeEnabled;
|
||||
CustomConfigJson = GetString(map, CustomConfigJsonKey) ?? CustomConfigJson;
|
||||
DataJson = GetString(map, DataJsonKey) ?? DataJson;
|
||||
ATags = GetString(map, ATagsKey) ?? ATags;
|
||||
AllowIDFAAccess = GetBool(map, AllowIdfaAccessKey) ?? AllowIDFAAccess;
|
||||
RequestPermissionOnInit = GetBool(map, RequestPermissionOnInitKey) ?? RequestPermissionOnInit;
|
||||
RewardedAutoLoad = GetBool(map, RewardedAutoLoadKey) ?? RewardedAutoLoad;
|
||||
RewardedPrewarmOnInit = GetBool(map, RewardedPrewarmOnInitKey) ?? RewardedPrewarmOnInit;
|
||||
RewardedMaxLoadAttempts = GetInt(map, RewardedMaxLoadAttemptsKey) ?? RewardedMaxLoadAttempts;
|
||||
RewardedLoadRetryDelayMs = GetInt(map, RewardedLoadRetryDelayMsKey) ?? RewardedLoadRetryDelayMs;
|
||||
RewardedShowTimeoutMs = GetInt(map, RewardedShowTimeoutMsKey) ?? RewardedShowTimeoutMs;
|
||||
RewardName = GetString(map, RewardNameKey) ?? RewardName;
|
||||
RewardAmount = GetInt(map, RewardAmountKey) ?? RewardAmount;
|
||||
InterstitialAutoLoad = GetBool(map, InterstitialAutoLoadKey) ?? InterstitialAutoLoad;
|
||||
InterstitialPrewarmOnInit = GetBool(map, InterstitialPrewarmOnInitKey) ?? InterstitialPrewarmOnInit;
|
||||
InterstitialMaxLoadAttempts = GetInt(map, InterstitialMaxLoadAttemptsKey) ?? InterstitialMaxLoadAttempts;
|
||||
InterstitialLoadRetryDelayMs = GetInt(map, InterstitialLoadRetryDelayMsKey) ?? InterstitialLoadRetryDelayMs;
|
||||
InterstitialShowTimeoutMs = GetInt(map, InterstitialShowTimeoutMsKey) ?? InterstitialShowTimeoutMs;
|
||||
SplashAutoLoad = GetBool(map, SplashAutoLoadKey) ?? SplashAutoLoad;
|
||||
SplashPrewarmOnInit = GetBool(map, SplashPrewarmOnInitKey) ?? SplashPrewarmOnInit;
|
||||
SplashMaxLoadAttempts = GetInt(map, SplashMaxLoadAttemptsKey) ?? SplashMaxLoadAttempts;
|
||||
SplashLoadRetryDelayMs = GetInt(map, SplashLoadRetryDelayMsKey) ?? SplashLoadRetryDelayMs;
|
||||
SplashShowTimeoutMs = GetInt(map, SplashShowTimeoutMsKey) ?? SplashShowTimeoutMs;
|
||||
ExpressWidth = GetInt(map, ExpressWidthKey) ?? ExpressWidth;
|
||||
ExpressHeight = GetInt(map, ExpressHeightKey) ?? ExpressHeight;
|
||||
}
|
||||
|
||||
private static string GetString(IDictionary<string, string> map, params string[] keys)
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(key) &&
|
||||
map.TryGetValue(key, out var value) &&
|
||||
!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return value.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool? GetBool(IDictionary<string, string> map, params string[] keys)
|
||||
{
|
||||
var value = GetString(map, keys);
|
||||
return TryConvertBool(value, out var result) ? result : null;
|
||||
}
|
||||
|
||||
private static int? GetInt(IDictionary<string, string> map, params string[] keys)
|
||||
{
|
||||
var value = GetString(map, keys);
|
||||
return int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) ? result : (int?)null;
|
||||
}
|
||||
|
||||
private static long? GetLong(IDictionary<string, string> map, params string[] keys)
|
||||
{
|
||||
return ParseLong(GetString(map, keys));
|
||||
}
|
||||
|
||||
private static long? ParseLong(string value)
|
||||
{
|
||||
return long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) ? result : (long?)null;
|
||||
}
|
||||
|
||||
private static bool TryConvertBool(object value, out bool result)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case bool boolValue:
|
||||
result = boolValue;
|
||||
return true;
|
||||
case string stringValue:
|
||||
if (bool.TryParse(stringValue, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (string.Equals(stringValue, "1", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (string.Equals(stringValue, "0", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string ConvertDictionaryValue(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value is string stringValue)
|
||||
{
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
if (value is IEnumerable enumerable)
|
||||
{
|
||||
var items = new List<string>();
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
items.Add(item.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join(",", items.ToArray());
|
||||
}
|
||||
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb9de9cc991b4649826dc9683c8ec78e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
137
Tapadn_Adapter/Runtime/Scripts/TapadnInteractionPlayer.cs
Normal file
137
Tapadn_Adapter/Runtime/Scripts/TapadnInteractionPlayer.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using Dirichlet.Mediation;
|
||||
using Runtime.ADAggregator;
|
||||
using UnityEngine;
|
||||
|
||||
public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAutoAdListener
|
||||
{
|
||||
private DirichletAdNative _adNative;
|
||||
private DirichletInterstitialAd _loadedAd;
|
||||
|
||||
public override int MaxLoadAttempts => TapadnAdController.CurrentOptions?.InterstitialMaxLoadAttempts ?? base.MaxLoadAttempts;
|
||||
public override float LoadRetryDelaySeconds => Math.Max(0f, (TapadnAdController.CurrentOptions?.InterstitialLoadRetryDelayMs ?? 500) / 1000f);
|
||||
public override float ShowPendingTimeoutSeconds => Math.Max(1f, (TapadnAdController.CurrentOptions?.InterstitialShowTimeoutMs ?? 20000) / 1000f);
|
||||
public override bool AutoPreloadOnInit => TapadnAdController.CurrentOptions?.InterstitialPrewarmOnInit ?? false;
|
||||
|
||||
public override void OnInit()
|
||||
{
|
||||
_adNative = DirichletAdManager.CreateAdNative();
|
||||
}
|
||||
|
||||
public override bool IsReadly()
|
||||
{
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
return TapadnAdRequestFactory.TryParseSlotId(Key, out _);
|
||||
}
|
||||
|
||||
if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid)
|
||||
{
|
||||
curState = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void LoadAD()
|
||||
{
|
||||
if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _))
|
||||
{
|
||||
Debug.LogError($"[TapADN] Invalid interstitial slot id: {Key}");
|
||||
curState = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
curState = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (curState == 1 || IsReadly())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
curState = 1;
|
||||
_adNative.LoadInterstitialAd(
|
||||
TapadnAdRequestFactory.BuildInterstitial(Key, TapadnAdController.CurrentOptions),
|
||||
ad =>
|
||||
{
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = ad;
|
||||
_loadedAd.Shown += OnManualShown;
|
||||
_loadedAd.Clicked += OnManualClicked;
|
||||
_loadedAd.Closed += OnManualClosed;
|
||||
curState = 2;
|
||||
Debug.Log($"[TapADN] Interstitial loaded. slot={Key}");
|
||||
},
|
||||
error =>
|
||||
{
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Interstitial load failed. code={error.Code}, message={error.Message}");
|
||||
});
|
||||
}
|
||||
|
||||
public override void ShowAD(Action onClose, Action<bool> onVideoComplete)
|
||||
{
|
||||
adListener.onClose = onClose;
|
||||
adListener.onVideoComplete = onVideoComplete;
|
||||
curState = 0;
|
||||
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
_adNative.ShowInterstitialAutoAd(TapadnAdRequestFactory.BuildInterstitial(Key, TapadnAdController.CurrentOptions), this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loadedAd == null || !_loadedAd.Show())
|
||||
{
|
||||
adListener.OnShowError();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnError(DirichletError error)
|
||||
{
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Interstitial show failed. code={error?.Code}, message={error?.Message}");
|
||||
adListener.OnShowError();
|
||||
}
|
||||
|
||||
public void OnAdShow()
|
||||
{
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
public void OnAdClose()
|
||||
{
|
||||
adListener.OnAdClose();
|
||||
adListener.OnShowComplete();
|
||||
}
|
||||
|
||||
public void OnAdClick()
|
||||
{
|
||||
}
|
||||
|
||||
private bool UseAutoLoad()
|
||||
{
|
||||
return TapadnAdController.CurrentOptions?.InterstitialAutoLoad ?? true;
|
||||
}
|
||||
|
||||
private void OnManualShown()
|
||||
{
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
private void OnManualClicked()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnManualClosed()
|
||||
{
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = null;
|
||||
OnAdClose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b422dcac50a0451a92815d54329fce8b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
137
Tapadn_Adapter/Runtime/Scripts/TapadnSplashPlayer.cs
Normal file
137
Tapadn_Adapter/Runtime/Scripts/TapadnSplashPlayer.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using Dirichlet.Mediation;
|
||||
using Runtime.ADAggregator;
|
||||
using UnityEngine;
|
||||
|
||||
public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListener
|
||||
{
|
||||
private DirichletAdNative _adNative;
|
||||
private DirichletSplashAd _loadedAd;
|
||||
|
||||
public override int MaxLoadAttempts => TapadnAdController.CurrentOptions?.SplashMaxLoadAttempts ?? base.MaxLoadAttempts;
|
||||
public override float LoadRetryDelaySeconds => Math.Max(0f, (TapadnAdController.CurrentOptions?.SplashLoadRetryDelayMs ?? 500) / 1000f);
|
||||
public override float ShowPendingTimeoutSeconds => Math.Max(1f, (TapadnAdController.CurrentOptions?.SplashShowTimeoutMs ?? 20000) / 1000f);
|
||||
public override bool AutoPreloadOnInit => TapadnAdController.CurrentOptions?.SplashPrewarmOnInit ?? false;
|
||||
|
||||
public override void OnInit()
|
||||
{
|
||||
_adNative = DirichletAdManager.CreateAdNative();
|
||||
}
|
||||
|
||||
public override bool IsReadly()
|
||||
{
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
return TapadnAdRequestFactory.TryParseSlotId(Key, out _);
|
||||
}
|
||||
|
||||
if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid)
|
||||
{
|
||||
curState = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void LoadAD()
|
||||
{
|
||||
if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _))
|
||||
{
|
||||
Debug.LogError($"[TapADN] Invalid splash slot id: {Key}");
|
||||
curState = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
curState = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (curState == 1 || IsReadly())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
curState = 1;
|
||||
_adNative.LoadSplashAd(
|
||||
TapadnAdRequestFactory.BuildSplash(Key, TapadnAdController.CurrentOptions),
|
||||
ad =>
|
||||
{
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = ad;
|
||||
_loadedAd.Shown += OnManualShown;
|
||||
_loadedAd.Clicked += OnManualClicked;
|
||||
_loadedAd.Closed += OnManualClosed;
|
||||
curState = 2;
|
||||
Debug.Log($"[TapADN] Splash loaded. slot={Key}");
|
||||
},
|
||||
error =>
|
||||
{
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Splash load failed. code={error.Code}, message={error.Message}");
|
||||
});
|
||||
}
|
||||
|
||||
public override void ShowAD(Action onClose, Action<bool> onVideoComplete)
|
||||
{
|
||||
adListener.onClose = onClose;
|
||||
adListener.onVideoComplete = onVideoComplete;
|
||||
curState = 0;
|
||||
|
||||
if (UseAutoLoad())
|
||||
{
|
||||
_adNative.ShowSplashAutoAd(TapadnAdRequestFactory.BuildSplash(Key, TapadnAdController.CurrentOptions), this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loadedAd == null || !_loadedAd.Show())
|
||||
{
|
||||
adListener.OnShowError();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnError(DirichletError error)
|
||||
{
|
||||
curState = 0;
|
||||
Debug.LogError($"[TapADN] Splash show failed. code={error?.Code}, message={error?.Message}");
|
||||
adListener.OnShowError();
|
||||
}
|
||||
|
||||
public void OnAdShow()
|
||||
{
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
public void OnAdClose()
|
||||
{
|
||||
adListener.OnAdClose();
|
||||
adListener.OnShowComplete();
|
||||
}
|
||||
|
||||
public void OnAdClick()
|
||||
{
|
||||
}
|
||||
|
||||
private bool UseAutoLoad()
|
||||
{
|
||||
return TapadnAdController.CurrentOptions?.SplashAutoLoad ?? true;
|
||||
}
|
||||
|
||||
private void OnManualShown()
|
||||
{
|
||||
NotifyShowStarted();
|
||||
}
|
||||
|
||||
private void OnManualClicked()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnManualClosed()
|
||||
{
|
||||
_loadedAd?.Destroy();
|
||||
_loadedAd = null;
|
||||
OnAdClose();
|
||||
}
|
||||
}
|
||||
11
Tapadn_Adapter/Runtime/Scripts/TapadnSplashPlayer.cs.meta
Normal file
11
Tapadn_Adapter/Runtime/Scripts/TapadnSplashPlayer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 372f8c753ddd48d9a9e08012999a05f4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user