From 2c505116b373ad4ef17bdbdf2f91bedc5fd8642d Mon Sep 17 00:00:00 2001 From: huyfei Date: Fri, 26 Jan 2024 12:24:22 +0800 Subject: [PATCH] =?UTF-8?q?update:=20Max=20SDK=20=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E8=87=B3=206.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GuruMaxIntegrationManager.cs | 5 +- Editor/GuruEditorMax/GuruMaxSdkAPI.cs | 2 +- MaxSdk/AppLovin.meta | 2 +- MaxSdk/AppLovin/Editor.meta | 2 +- MaxSdk/AppLovin/Editor/Dependencies.xml | 4 +- MaxSdk/AppLovin/Editor/Dependencies.xml.meta | 2 +- MaxSdk/AppLovin/Plugins.meta | 2 +- MaxSdk/AppLovin/Plugins/Android.meta | 2 +- .../Android/applovin-max-unity-plugin.aar | Bin 75984 -> 77731 bytes .../applovin-max-unity-plugin.aar.meta | 2 +- MaxSdk/AppLovin/Plugins/iOS.meta | 2 +- .../AppLovin/Plugins/iOS/MAUnityAdManager.h | 134 +++++---- .../Plugins/iOS/MAUnityAdManager.h.meta | 2 +- .../AppLovin/Plugins/iOS/MAUnityAdManager.m | 245 +++++++++------- .../Plugins/iOS/MAUnityAdManager.m.meta | 2 +- MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm | 269 ++++++++++++++---- .../Plugins/iOS/MAUnityPlugin.mm.meta | 2 +- MaxSdk/Prefabs.meta | 2 +- MaxSdk/Prefabs/BannerBottom.prefab.meta | 2 +- MaxSdk/Prefabs/BannerTop.prefab.meta | 2 +- MaxSdk/Prefabs/Interstitial.prefab.meta | 2 +- MaxSdk/Prefabs/Rewarded.prefab.meta | 2 +- MaxSdk/Resources.meta | 2 +- MaxSdk/Resources/Images.meta | 2 +- MaxSdk/Resources/Images/alert_icon.png.meta | 2 +- .../Resources/Images/uninstall_icon.png.meta | 2 +- MaxSdk/Resources/Images/warning_icon.png.meta | 2 +- MaxSdk/Scripts.meta | 2 +- MaxSdk/Scripts/Editor.meta | 2 +- MaxSdk/Scripts/Editor/MaxInitialization.cs | 17 +- .../Scripts/Editor/MaxInitialization.cs.meta | 2 +- .../Editor/MaxPostProcessBuildAndroid.cs | 5 +- .../Editor/MaxPostProcessBuildAndroid.cs.meta | 2 +- .../Scripts/Editor/MaxPostProcessBuildiOS.cs | 166 +++-------- .../Editor/MaxPostProcessBuildiOS.cs.meta | 2 +- .../Editor/MaxSdk.Scripts.Editor.asmdef.meta | 2 +- MaxSdk/Scripts/IntegrationManager.meta | 2 +- MaxSdk/Scripts/IntegrationManager/Editor.meta | 2 +- .../Editor/AppLovinAutoUpdater.cs | 29 -- .../Editor/AppLovinAutoUpdater.cs.meta | 2 +- .../Editor/AppLovinCommandLine.cs.meta | 2 +- .../Editor/AppLovinDownloadHandler.cs | 75 ----- .../Editor/AppLovinEditorCoroutine.cs.meta | 2 +- .../Editor/AppLovinIntegrationManager.cs | 59 +--- .../Editor/AppLovinIntegrationManager.cs.meta | 2 +- .../AppLovinIntegrationManagerWindow.cs | 142 ++++++--- .../AppLovinIntegrationManagerWindow.cs.meta | 2 +- .../Editor/AppLovinInternalSettings.cs | 52 +--- .../Editor/AppLovinInternalSettings.cs.meta | 2 +- .../AppLovinPostProcessAndroidGradle.cs | 2 +- .../AppLovinPostProcessAndroidGradle.cs.meta | 2 +- .../Editor/AppLovinPostProcessiOS.cs | 12 +- .../Editor/AppLovinPostProcessiOS.cs.meta | 2 +- .../Editor/AppLovinPreProcess.cs | 105 +++++++ ...ler.cs.meta => AppLovinPreProcess.cs.meta} | 4 +- .../Editor/AppLovinPreProcessAndroid.cs | 66 ++--- .../Editor/AppLovinPreProcessAndroid.cs.meta | 2 +- .../Editor/AppLovinPreProcessiOS.cs | 45 +++ .../Editor/AppLovinPreProcessiOS.cs.meta | 14 + .../Editor/AppLovinProcessGradleBuildFile.cs | 12 +- .../AppLovinProcessGradleBuildFile.cs.meta | 2 +- .../Editor/AppLovinSettings.cs | 10 + .../Editor/AppLovinSettings.cs.meta | 2 +- .../MaxSdk.IntegrationManager.Editor.asmdef | 12 +- ...xSdk.IntegrationManager.Editor.asmdef.meta | 2 +- MaxSdk/Scripts/MaxCmpService.cs | 170 +++++++++++ MaxSdk/Scripts/MaxCmpService.cs.meta | 14 + MaxSdk/Scripts/MaxEventSystemChecker.cs.meta | 2 +- MaxSdk/Scripts/MaxEvents.cs.meta | 2 +- MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta | 2 +- MaxSdk/Scripts/MaxSdk.cs | 2 +- MaxSdk/Scripts/MaxSdk.cs.meta | 2 +- MaxSdk/Scripts/MaxSdkAndroid.cs | 113 ++++---- MaxSdk/Scripts/MaxSdkAndroid.cs.meta | 2 +- MaxSdk/Scripts/MaxSdkBase.cs | 185 ++++++------ MaxSdk/Scripts/MaxSdkBase.cs.meta | 2 +- MaxSdk/Scripts/MaxSdkCallbacks.cs | 28 +- MaxSdk/Scripts/MaxSdkCallbacks.cs.meta | 2 +- MaxSdk/Scripts/MaxSdkLogger.cs.meta | 2 +- MaxSdk/Scripts/MaxSdkUnityEditor.cs | 5 - MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta | 2 +- MaxSdk/Scripts/MaxSdkUtils.cs | 83 +++++- MaxSdk/Scripts/MaxSdkUtils.cs.meta | 2 +- MaxSdk/Scripts/MaxSdkiOS.cs | 138 +++++---- MaxSdk/Scripts/MaxSdkiOS.cs.meta | 2 +- MaxSdk/Scripts/MaxTargetingData.cs.meta | 2 +- MaxSdk/Scripts/MaxUserSegment.cs.meta | 2 +- MaxSdk/Scripts/MaxUserServiceAndroid.cs.meta | 2 +- .../Scripts/MaxUserServiceUnityEditor.cs.meta | 2 +- MaxSdk/Scripts/MaxUserServiceiOS.cs.meta | 2 +- MaxSdk/Scripts/MaxVariableServiceAndroid.cs | 36 --- .../Scripts/MaxVariableServiceAndroid.cs.meta | 6 - .../Scripts/MaxVariableServiceUnityEditor.cs | 30 -- .../MaxVariableServiceUnityEditor.cs.meta | 6 - MaxSdk/Scripts/MaxVariableServiceiOS.cs | 47 --- MaxSdk/Scripts/MaxVariableServiceiOS.cs.meta | 6 - MaxSdk/Scripts/ThirdParty.meta | 2 +- MaxSdk/Scripts/ThirdParty/MiniJSON.cs | 2 +- MaxSdk/Scripts/ThirdParty/MiniJSON.cs.meta | 2 +- MaxSdk/Version.md.meta | 2 +- 100 files changed, 1351 insertions(+), 1124 deletions(-) delete mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs rename MaxSdk/Scripts/IntegrationManager/Editor/{AppLovinDownloadHandler.cs.meta => AppLovinPreProcess.cs.meta} (81%) create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs.meta create mode 100644 MaxSdk/Scripts/MaxCmpService.cs create mode 100644 MaxSdk/Scripts/MaxCmpService.cs.meta delete mode 100644 MaxSdk/Scripts/MaxVariableServiceAndroid.cs delete mode 100644 MaxSdk/Scripts/MaxVariableServiceAndroid.cs.meta delete mode 100644 MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs delete mode 100644 MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs.meta delete mode 100644 MaxSdk/Scripts/MaxVariableServiceiOS.cs delete mode 100644 MaxSdk/Scripts/MaxVariableServiceiOS.cs.meta diff --git a/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs b/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs index b950036..3aacd6b 100644 --- a/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs +++ b/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs @@ -36,6 +36,7 @@ namespace Guru.Editor.Max private string _admobIOSId; private bool _qualityServiceEnabled = true; private bool _setAttributionReportEndpoint = true; + private bool _addApsSkAdNetworkIds = true; private bool _isDirty; //------- AppLovinData -------- @@ -43,8 +44,6 @@ namespace Guru.Editor.Max private PluginData pluginData; #region 生命周期 - - /// /// 打开窗体 @@ -155,6 +154,7 @@ namespace Guru.Editor.Max _admobIOSId = _settings.AdMobIosAppId; _qualityServiceEnabled = _settings.QualityServiceEnabled; _setAttributionReportEndpoint = _settings.SetAttributionReportEndpoint; + _addApsSkAdNetworkIds = _settings.AddApsSkAdNetworkIds; } else { @@ -177,6 +177,7 @@ namespace Guru.Editor.Max _settings.AdMobIosAppId = _admobIOSId; _settings.QualityServiceEnabled = _qualityServiceEnabled; _settings.SetAttributionReportEndpoint = _setAttributionReportEndpoint; + _settings.AddApsSkAdNetworkIds = _addApsSkAdNetworkIds; EditorUtility.SetDirty(_settings); AssetDatabase.SaveAssetIfDirty(_settings); diff --git a/Editor/GuruEditorMax/GuruMaxSdkAPI.cs b/Editor/GuruEditorMax/GuruMaxSdkAPI.cs index c416fbd..748fb09 100644 --- a/Editor/GuruEditorMax/GuruMaxSdkAPI.cs +++ b/Editor/GuruEditorMax/GuruMaxSdkAPI.cs @@ -16,7 +16,7 @@ namespace Guru.Editor.Max { // ------------ VERSION INFO ------------ public const string Version = "0.1.0"; - public const string SdkVersion = "5.11.3"; + public const string SdkVersion = "6.1.2"; // ------------ VERSION INFO ------------ public const string PackageName = "com.guru.unity.max"; diff --git a/MaxSdk/AppLovin.meta b/MaxSdk/AppLovin.meta index e025615..85a9d74 100644 --- a/MaxSdk/AppLovin.meta +++ b/MaxSdk/AppLovin.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 24350f435b5f14067b88bad9e54f4776 +guid: c443543f84b8b443bad7d9daa264ae4f labels: - al_max - al_max_export_path-MaxSdk/AppLovin diff --git a/MaxSdk/AppLovin/Editor.meta b/MaxSdk/AppLovin/Editor.meta index 7224034..e498210 100644 --- a/MaxSdk/AppLovin/Editor.meta +++ b/MaxSdk/AppLovin/Editor.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0c096cc384c7446b5b962f359a291792 +guid: 68a1e4d0fd5e8494684b435209c3a42d labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Editor diff --git a/MaxSdk/AppLovin/Editor/Dependencies.xml b/MaxSdk/AppLovin/Editor/Dependencies.xml index b951879..e94d30e 100644 --- a/MaxSdk/AppLovin/Editor/Dependencies.xml +++ b/MaxSdk/AppLovin/Editor/Dependencies.xml @@ -1,9 +1,9 @@ - + - + diff --git a/MaxSdk/AppLovin/Editor/Dependencies.xml.meta b/MaxSdk/AppLovin/Editor/Dependencies.xml.meta index 50f9829..3360fd3 100644 --- a/MaxSdk/AppLovin/Editor/Dependencies.xml.meta +++ b/MaxSdk/AppLovin/Editor/Dependencies.xml.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a36972e13b9b64a87a11421020969d76 +guid: 746da98302dc0402aaa37e8f7bd97e77 labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Editor/Dependencies.xml diff --git a/MaxSdk/AppLovin/Plugins.meta b/MaxSdk/AppLovin/Plugins.meta index cad18f4..620e2b3 100644 --- a/MaxSdk/AppLovin/Plugins.meta +++ b/MaxSdk/AppLovin/Plugins.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6f0263dd851654e7598f11593e8da7a8 +guid: b0fe3bb045e0d4f6f91368c84f74412f labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Plugins diff --git a/MaxSdk/AppLovin/Plugins/Android.meta b/MaxSdk/AppLovin/Plugins/Android.meta index cb45a3d..e579629 100644 --- a/MaxSdk/AppLovin/Plugins/Android.meta +++ b/MaxSdk/AppLovin/Plugins/Android.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9b47263f475c14ff8861bc3b40f416b9 +guid: b5015a52575b74babb5884f37c45b263 labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Plugins/Android diff --git a/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar b/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar index 9d2a709a5fd3be423cf718213f8b42eea54189a2..7575a83f9d679fe478789f7cdf453f3e5970ae4b 100644 GIT binary patch delta 77304 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%0DW?|a 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 K20tzV0000ocRJVr delta 75528 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 CSAB>8 diff --git a/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta b/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta index a70eb75..224076a 100644 --- a/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta +++ b/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8283280d1ffc84ea1856f8d8982fc3be +guid: 1db980bd612824d2097f78fd779e6051 labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar diff --git a/MaxSdk/AppLovin/Plugins/iOS.meta b/MaxSdk/AppLovin/Plugins/iOS.meta index 123a98f..fb615c7 100644 --- a/MaxSdk/AppLovin/Plugins/iOS.meta +++ b/MaxSdk/AppLovin/Plugins/iOS.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6d1f80dfd5b7247ff9bcf9a5532eb9a3 +guid: 35602bb97c21644338be36a4331c3874 labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Plugins/iOS diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h index b4061d2..4af5531 100644 --- a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h @@ -14,91 +14,91 @@ typedef void (*ALUnityBackgroundCallback)(const char* args); - (ALSdk *)initializeSdkWithSettings:(ALSdkSettings *)settings backgroundCallback:(ALUnityBackgroundCallback)unityBackgroundCallback andCompletionHandler:(ALSdkInitializationCompletionHandler)completionHandler; -- (void)createBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier atPosition:(NSString *)bannerPosition; -- (void)createBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset; -- (void)loadBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)setBannerBackgroundColorForAdUnitIdentifier:(NSString *)adUnitIdentifier hexColorCode:(NSString *)hexColorCode; -- (void)setBannerPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)startBannerAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)stopBannerAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)setBannerExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value; -- (void)setBannerLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value; -- (void)setBannerCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)setBannerWidth:(CGFloat)width forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)updateBannerPosition:(NSString *)bannerPosition forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)updateBannerPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)showBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)destroyBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)hideBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (NSString *)bannerLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier; +- (void)createBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier atPosition:(nullable NSString *)bannerPosition; +- (void)createBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset; +- (void)loadBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)setBannerBackgroundColorForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier hexColorCode:(nullable NSString *)hexColorCode; +- (void)setBannerPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)startBannerAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)stopBannerAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)setBannerExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setBannerLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; +- (void)setBannerCustomData:(nullable NSString *)customData forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)setBannerWidth:(CGFloat)width forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateBannerPosition:(nullable NSString *)bannerPosition forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateBannerPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)destroyBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)hideBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (NSString *)bannerLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; + (CGFloat)adaptiveBannerHeightForWidth:(CGFloat)width; -- (void)createMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier atPosition:(NSString *)mrecPosition; -- (void)createMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset; -- (void)loadMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)setMRecPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)startMRecAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)stopMRecAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifer; -- (void)setMRecExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value; -- (void)setMRecLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value; -- (void)setMRecCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)showMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)destroyMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)hideMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)updateMRecPosition:(NSString *)mrecPosition forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)updateMRecPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (NSString *)mrecLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier; +- (void)createMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier atPosition:(nullable NSString *)mrecPosition; +- (void)createMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset; +- (void)loadMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)setMRecPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)startMRecAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)stopMRecAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifer; +- (void)setMRecExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setMRecLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; +- (void)setMRecCustomData:(nullable NSString *)customData forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)destroyMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)hideMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateMRecPosition:(nullable NSString *)mrecPosition forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateMRecPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (NSString *)mrecLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; -- (void)createCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset width:(CGFloat)width height:(CGFloat)height rotation:(CGFloat)rotation; -- (void)setCrossPromoAdPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)showCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)destroyCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)hideCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)updateCrossPromoAdPositionForAdUnitIdentifier:(NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset width:(CGFloat)width height:(CGFloat)height rotation:(CGFloat)rotation; -- (NSString *)crossPromoAdLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier; +- (void)createCrossPromoAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset width:(CGFloat)width height:(CGFloat)height rotation:(CGFloat)rotation; +- (void)setCrossPromoAdPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showCrossPromoAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)destroyCrossPromoAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)hideCrossPromoAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateCrossPromoAdPositionForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset width:(CGFloat)width height:(CGFloat)height rotation:(CGFloat)rotation; +- (NSString *)crossPromoAdLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; -- (void)loadInterstitialWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (BOOL)isInterstitialReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)showInterstitialWithAdUnitIdentifier:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; -- (void)setInterstitialExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value; -- (void)setInterstitialLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value; +- (void)loadInterstitialWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (BOOL)isInterstitialReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showInterstitialWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; +- (void)setInterstitialExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setInterstitialLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; -- (void)loadAppOpenAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (BOOL)isAppOpenAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)showAppOpenAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; -- (void)setAppOpenAdExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value; -- (void)setAppOpenAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value; +- (void)loadAppOpenAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (BOOL)isAppOpenAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showAppOpenAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; +- (void)setAppOpenAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setAppOpenAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; -- (void)loadRewardedAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (BOOL)isRewardedAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)showRewardedAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; -- (void)setRewardedAdExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value; -- (void)setRewardedAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value; +- (void)loadRewardedAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (BOOL)isRewardedAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showRewardedAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; +- (void)setRewardedAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setRewardedAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; -- (void)loadRewardedInterstitialAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (BOOL)isRewardedInterstitialAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier; -- (void)showRewardedInterstitialAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; -- (void)setRewardedInterstitialAdExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value; -- (void)setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value; +- (void)loadRewardedInterstitialAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (BOOL)isRewardedInterstitialAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showRewardedInterstitialAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; +- (void)setRewardedInterstitialAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; // Event Tracking -- (void)trackEvent:(NSString *)event parameters:(NSString *)parameters; +- (void)trackEvent:(nullable NSString *)event parameters:(nullable NSString *)parameters; // Ad Info -- (NSString *)adInfoForAdUnitIdentifier:(NSString *)adUnitIdentifier; +- (NSString *)adInfoForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; // Ad Value -- (NSString *)adValueForAdUnitIdentifier:(NSString *)adUnitIdentifier withKey:(NSString *)key; +- (NSString *)adValueForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier withKey:(nullable NSString *)key; // User Service - (void)didDismissUserConsentDialog; -// Consent Flow -- (void)startConsentFlow; +// CMP Service +- (void)showCMPForExistingUser; // Utils + (NSString *)serializeParameters:(NSDictionary *)dict; -+ (NSDictionary *)deserializeParameters:(NSString *)serialized; ++ (NSDictionary *)deserializeParameters:(nullable NSString *)serialized; /** * Creates an instance of @c MAUnityAdManager if needed and returns the singleton instance. @@ -109,8 +109,4 @@ typedef void (*ALUnityBackgroundCallback)(const char* args); @end -@interface MAUnityAdManager(ALDeprecated) -- (void)loadVariables __deprecated_msg("This API has been deprecated. Please use our SDK's initialization callback to retrieve variables instead."); -@end - NS_ASSUME_NONNULL_END diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta index 47ae840..aef1db5 100644 --- a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d3a319587a4a744d898e112357c46370 +guid: 4209563f82b8a4f7dabf03705ab761c6 labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m index ad26ac6..eb874ac 100644 --- a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m @@ -5,7 +5,7 @@ #import "MAUnityAdManager.h" -#define VERSION @"5.11.4" +#define VERSION @"6.1.2" #define KEY_WINDOW [UIApplication sharedApplication].keyWindow #define DEVICE_SPECIFIC_ADVIEW_AD_FORMAT ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) ? MAAdFormat.leader : MAAdFormat.banner @@ -42,7 +42,7 @@ extern "C" { } #endif -@interface MAUnityAdManager() +@interface MAUnityAdManager() // Parent Fields @property (nonatomic, weak) ALSdk *sdk; @@ -184,7 +184,6 @@ static ALUnityBackgroundCallback backgroundCallback; self.sdk = [ALSdk sharedWithSettings: settings]; } - self.sdk.variableService.delegate = self; [self.sdk setPluginVersion: [@"Max-Unity-" stringByAppendingString: VERSION]]; self.sdk.mediationProvider = @"max"; [self.sdk initializeSdkWithCompletionHandler:^(ALSdkConfiguration *configuration) @@ -192,9 +191,11 @@ static ALUnityBackgroundCallback backgroundCallback; // Note: internal state should be updated first completionHandler( configuration ); + NSString *consentFlowUserGeographyStr = @(configuration.consentFlowUserGeography).stringValue; NSString *consentDialogStateStr = @(configuration.consentDialogState).stringValue; NSString *appTrackingStatus = @(configuration.appTrackingTransparencyStatus).stringValue; // Deliberately name it `appTrackingStatus` to be a bit more generic (in case Android introduces a similar concept) [MAUnityAdManager forwardUnityEventWithArgs: @{@"name" : @"OnSdkInitializedEvent", + @"consentFlowUserGeography" : consentFlowUserGeographyStr, @"consentDialogState" : consentDialogStateStr, @"countryCode" : configuration.countryCode, @"appTrackingStatus" : appTrackingStatus, @@ -207,87 +208,93 @@ static ALUnityBackgroundCallback backgroundCallback; #pragma mark - Banners -- (void)createBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier atPosition:(NSString *)bannerPosition +- (void)createBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier atPosition:(nullable NSString *)bannerPosition { [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] atPosition: bannerPosition withOffset: CGPointZero]; } -- (void)createBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset +- (void)createBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset { [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] atPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset)]; } -- (void)loadBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)loadBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self loadAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)setBannerBackgroundColorForAdUnitIdentifier:(NSString *)adUnitIdentifier hexColorCode:(NSString *)hexColorCode +- (void)setBannerBackgroundColorForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier hexColorCode:(nullable NSString *)hexColorCode { [self setAdViewBackgroundColorForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] hexColorCode: hexColorCode]; } -- (void)setBannerPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)setBannerPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)startBannerAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)startBannerAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self startAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)stopBannerAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)stopBannerAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self stopAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)setBannerWidth:(CGFloat)width forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)setBannerWidth:(CGFloat)width forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self setAdViewWidth: width forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)updateBannerPosition:(NSString *)bannerPosition forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)updateBannerPosition:(nullable NSString *)bannerPosition forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self updateAdViewPosition: bannerPosition withOffset: CGPointZero forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)updateBannerPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)updateBannerPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self updateAdViewPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset) forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)setBannerExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value +- (void)setBannerExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value { [self setAdViewExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] key: key value: value]; } -- (void)setBannerLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +- (void)setBannerLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value { + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + [self setAdViewLocalExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] key: key value: value]; } -- (void)setBannerCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)setBannerCustomData:(nullable NSString *)customData forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self setAdViewCustomData: customData forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)showBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)showBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)hideBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)hideBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (NSString *)bannerLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier +- (NSString *)bannerLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { return [self adViewLayoutForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } -- (void)destroyBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)destroyBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; } @@ -299,84 +306,90 @@ static ALUnityBackgroundCallback backgroundCallback; #pragma mark - MRECs -- (void)createMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier atPosition:(NSString *)mrecPosition +- (void)createMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier atPosition:(nullable NSString *)mrecPosition { [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec atPosition: mrecPosition withOffset: CGPointZero]; } -- (void)createMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset +- (void)createMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset { [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec atPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset)]; } -- (void)loadMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)loadMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self loadAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)setMRecPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)setMRecPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)startMRecAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)startMRecAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self startAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)stopMRecAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)stopMRecAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self stopAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)updateMRecPosition:(NSString *)mrecPosition forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)updateMRecPosition:(nullable NSString *)mrecPosition forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self updateAdViewPosition: mrecPosition withOffset: CGPointZero forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)updateMRecPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)updateMRecPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self updateAdViewPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset) forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)setMRecExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value +- (void)setMRecExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value { [self setAdViewExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec key: key value: value]; } -- (void)setMRecLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +- (void)setMRecLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value { + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + [self setAdViewLocalExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec key: key value: value]; } -- (void)setMRecCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier; +- (void)setMRecCustomData:(nullable NSString *)customData forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; { [self setAdViewCustomData: customData forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)showMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)showMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)destroyMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)destroyMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (void)hideMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)hideMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } -- (NSString *)mrecLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier +- (NSString *)mrecLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { return [self adViewLayoutForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; } #pragma mark - Cross Promo Ads -- (void)createCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset width:(CGFloat)width height:(CGFloat)height rotation:(CGFloat)rotation +- (void)createCrossPromoAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset width:(CGFloat)width height:(CGFloat)height rotation:(CGFloat)rotation { self.adViewWidths[adUnitIdentifier] = @(width); self.crossPromoAdViewHeights[adUnitIdentifier] = @(height); @@ -384,12 +397,12 @@ static ALUnityBackgroundCallback backgroundCallback; [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo atPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset)]; } -- (void)setCrossPromoAdPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)setCrossPromoAdPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; } -- (void)updateCrossPromoAdPositionForAdUnitIdentifier:(NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset width:(CGFloat)width height:(CGFloat)height rotation:(CGFloat)rotation +- (void)updateCrossPromoAdPositionForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset width:(CGFloat)width height:(CGFloat)height rotation:(CGFloat)rotation { self.adViewWidths[adUnitIdentifier] = @(width); self.crossPromoAdViewHeights[adUnitIdentifier] = @(height); @@ -397,157 +410,181 @@ static ALUnityBackgroundCallback backgroundCallback; [self updateAdViewPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset) forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; } -- (void)showCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)showCrossPromoAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; } -- (void)destroyCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)destroyCrossPromoAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; } -- (void)hideCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)hideCrossPromoAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { [self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; } -- (NSString *)crossPromoAdLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier +- (NSString *)crossPromoAdLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { return [self adViewLayoutForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; } #pragma mark - Interstitials -- (void)loadInterstitialWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)loadInterstitialWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; [interstitial loadAd]; } -- (BOOL)isInterstitialReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (BOOL)isInterstitialReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; return [interstitial isReady]; } -- (void)showInterstitialWithAdUnitIdentifier:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData +- (void)showInterstitialWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData { MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; [interstitial showAdForPlacement: placement customData: customData]; } -- (void)setInterstitialExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value +- (void)setInterstitialExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value { MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; [interstitial setExtraParameterForKey: key value: value]; } -- (void)setInterstitialLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +- (void)setInterstitialLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value { + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; [interstitial setLocalExtraParameterForKey: key value: value]; } #pragma mark - App Open Ads -- (void)loadAppOpenAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)loadAppOpenAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; [appOpenAd loadAd]; } -- (BOOL)isAppOpenAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (BOOL)isAppOpenAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; return [appOpenAd isReady]; } -- (void)showAppOpenAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData +- (void)showAppOpenAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData { MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; [appOpenAd showAdForPlacement: placement customData: customData]; } -- (void)setAppOpenAdExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value +- (void)setAppOpenAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value { MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; [appOpenAd setExtraParameterForKey: key value: value]; } -- (void)setAppOpenAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +- (void)setAppOpenAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value { + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; [appOpenAd setLocalExtraParameterForKey: key value: value]; } #pragma mark - Rewarded -- (void)loadRewardedAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)loadRewardedAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; [rewardedAd loadAd]; } -- (BOOL)isRewardedAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (BOOL)isRewardedAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; return [rewardedAd isReady]; } -- (void)showRewardedAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData +- (void)showRewardedAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData { MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; [rewardedAd showAdForPlacement: placement customData: customData]; } -- (void)setRewardedAdExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value +- (void)setRewardedAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value { MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; [rewardedAd setExtraParameterForKey: key value: value]; } -- (void)setRewardedAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value; +- (void)setRewardedAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; { + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; [rewardedAd setLocalExtraParameterForKey: key value: value]; } #pragma mark - Rewarded Interstitials -- (void)loadRewardedInterstitialAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (void)loadRewardedInterstitialAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; [rewardedInterstitialAd loadAd]; } -- (BOOL)isRewardedInterstitialAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier +- (BOOL)isRewardedInterstitialAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; return [rewardedInterstitialAd isReady]; } -- (void)showRewardedInterstitialAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData +- (void)showRewardedInterstitialAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData { MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; [rewardedInterstitialAd showAdForPlacement: placement customData: customData]; } -- (void)setRewardedInterstitialAdExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable NSString *)value +- (void)setRewardedInterstitialAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value { MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; [rewardedInterstitialAd setExtraParameterForKey: key value: value]; } -- (void)setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +- (void)setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value { + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; [rewardedInterstitialAd setLocalExtraParameterForKey: key value: value]; } #pragma mark - Event Tracking -- (void)trackEvent:(NSString *)event parameters:(NSString *)parameters +- (void)trackEvent:(nullable NSString *)event parameters:(nullable NSString *)parameters { NSDictionary *deserializedParameters = [MAUnityAdManager deserializeParameters: parameters]; [self.sdk.eventService trackEvent: event parameters: deserializedParameters]; @@ -555,9 +592,9 @@ static ALUnityBackgroundCallback backgroundCallback; #pragma mark - Ad Info -- (NSString *)adInfoForAdUnitIdentifier:(NSString *)adUnitIdentifier +- (NSString *)adInfoForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier { - if ( adUnitIdentifier.length == 0 ) return @""; + if ( [adUnitIdentifier al_isValidString] ) return @""; MAAd *ad = [self adWithAdUnitIdentifier: adUnitIdentifier]; if ( !ad ) return @""; @@ -644,9 +681,10 @@ static ALUnityBackgroundCallback backgroundCallback; #pragma mark - Ad Value -- (NSString *)adValueForAdUnitIdentifier:(NSString *)adUnitIdentifier withKey:(NSString *)key +- (NSString *)adValueForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier withKey:(nullable NSString *)key { - if ( adUnitIdentifier.length == 0 ) return @""; + if ( adUnitIdentifier == nil || adUnitIdentifier.length == 0 ) return @""; + if ( key == nil || key.length == 0 ) return @""; MAAd *ad = [self adWithAdUnitIdentifier: adUnitIdentifier]; if ( !ad ) return @""; @@ -1119,16 +1157,21 @@ static ALUnityBackgroundCallback backgroundCallback; self.adViewAdFormats[adUnitIdentifier] = adFormat; [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; - // Enable adaptive banners by default. - if ( ( self.adViewExtraParametersToSetAfterCreate[@"adaptive_banner"] != nil ) && ( adFormat == MAAdFormat.banner || adFormat == MAAdFormat.leader ) ) + NSDictionary *extraParameters = self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier]; + + // Enable adaptive banners by default for banners and leaders. + if ( [adFormat isBannerOrLeaderAd] ) { - [adView setExtraParameterForKey: @"adaptive_banner" value: @"true"]; + // Check if there is already a pending setting for adaptive banners. If not, enable them. + if ( !extraParameters[@"adaptive_banner"] ) + { + [adView setExtraParameterForKey: @"adaptive_banner" value: @"true"]; + } } // Handle initial extra parameters if publisher sets it before creating ad view - if ( self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier] ) + if ( extraParameters ) { - NSDictionary *extraParameters = self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier]; for ( NSString *key in extraParameters ) { [adView setExtraParameterForKey: key value: extraParameters[key]]; @@ -1186,7 +1229,7 @@ static ALUnityBackgroundCallback backgroundCallback; MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; if ( !adView ) { - [self log: @"%@ does not exist for ad unit identifier %@.", adFormat.label, adUnitIdentifier]; + [self log: @"%@ does not exist for ad unit identifier \"%@\".", adFormat.label, adUnitIdentifier]; return; } @@ -1275,13 +1318,17 @@ static ALUnityBackgroundCallback backgroundCallback; max_unity_dispatch_on_main_thread(^{ [self log: @"Setting width %f for \"%@\" with ad unit identifier \"%@\"", width, adFormat, adUnitIdentifier]; - CGFloat minWidth = adFormat.size.width; + BOOL isBannerOrLeader = adFormat.isBannerOrLeaderAd; + + // Banners and leaders need to be at least 320pts wide. + CGFloat minWidth = isBannerOrLeader ? MAAdFormat.banner.size.width : adFormat.size.width; if ( width < minWidth ) { - [self log: @"The provided with: %f is smaller than the minimum required width: %f for ad format: %@. Please set the width higher than the minimum required.", width, minWidth, adFormat]; + [self log: @"The provided width: %f is smaller than the minimum required width: %f for ad format: %@. Automatically setting width to %f.", width, minWidth, adFormat, minWidth]; } - self.adViewWidths[adUnitIdentifier] = @(width); + CGFloat widthToSet = MAX( minWidth, width ); + self.adViewWidths[adUnitIdentifier] = @(widthToSet); [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; }); } @@ -1307,7 +1354,7 @@ static ALUnityBackgroundCallback backgroundCallback; } else { - [self log: @"%@ does not exist for ad unit identifier %@. Saving extra parameter to be set when it is created.", adFormat, adUnitIdentifier]; + [self log: @"%@ does not exist for ad unit identifier \"%@\". Saving extra parameter to be set when it is created.", adFormat, adUnitIdentifier]; // The adView has not yet been created. Store the extra parameters, so that they can be added once the banner has been created. NSMutableDictionary *extraParameters = self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier]; @@ -1340,7 +1387,7 @@ static ALUnityBackgroundCallback backgroundCallback; } else { - [self log: @"%@ does not exist for ad unit identifier %@. Saving local extra parameter to be set when it is created.", adFormat, adUnitIdentifier]; + [self log: @"%@ does not exist for ad unit identifier \"%@\". Saving local extra parameter to be set when it is created.", adFormat, adUnitIdentifier]; // The adView has not yet been created. Store the loca extra parameters, so that they can be added once the adview has been created. NSMutableDictionary *localExtraParameters = self.adViewLocalExtraParametersToSetAfterCreate[adUnitIdentifier]; @@ -1698,15 +1745,7 @@ static ALUnityBackgroundCallback backgroundCallback; // All positions have constant height NSMutableArray *constraints = [NSMutableArray arrayWithObject: [adView.heightAnchor constraintEqualToConstant: adViewSize.height]]; - UILayoutGuide *layoutGuide; - if ( @available(iOS 11.0, *) ) - { - layoutGuide = superview.safeAreaLayoutGuide; - } - else - { - layoutGuide = superview.layoutMarginsGuide; - } + UILayoutGuide *layoutGuide = superview.safeAreaLayoutGuide; if ( [adViewPosition isEqual: @"top_center"] || [adViewPosition isEqual: @"bottom_center"] ) { @@ -1963,7 +2002,7 @@ static ALUnityBackgroundCallback backgroundCallback; return [[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding]; } -+ (NSDictionary *)deserializeParameters:(NSString *)serialized ++ (NSDictionary *)deserializeParameters:(nullable NSString *)serialized { if ( serialized.length > 0 ) { @@ -2004,37 +2043,27 @@ static ALUnityBackgroundCallback backgroundCallback; [MAUnityAdManager forwardUnityEventWithArgs: @{@"name" : @"OnSdkConsentDialogDismissedEvent"}]; } -#pragma mark - Consent Flow +#pragma mark - CMP Service -- (void)startConsentFlow +- (void)showCMPForExistingUser { - [self.sdk.cfService scfWithCompletionHander:^(ALCFError * _Nullable error) { + [self.sdk.cmpService showCMPForExistingUserWithCompletion:^(ALCMPError * _Nullable error) { - NSMutableDictionary *args = [NSMutableDictionary dictionaryWithCapacity: 3]; - args[@"name"] = @"OnSdkConsentFlowCompletedEvent"; + NSMutableDictionary *args = [NSMutableDictionary dictionaryWithCapacity: 2]; + args[@"name"] = @"OnCmpCompletedEvent"; if ( error ) { - args[@"code"] = @(error.code); - args[@"message"] = error.message; + args[@"error"] = @{@"code": @(error.code), + @"message": error.message, + @"cmpCode": @(error.cmpCode), + @"cmpMessage": error.cmpMessage}; } - [MAUnityAdManager forwardUnityEventWithArgs: args]; + [MAUnityAdManager forwardUnityEventWithArgs: args forwardInBackground: YES]; }]; } -#pragma mark - Variable Service (Deprecated) - -- (void)loadVariables -{ - [self.sdk.variableService loadVariables]; -} - -- (void)variableService:(ALVariableService *)variableService didUpdateVariables:(NSDictionary *)variables -{ - [MAUnityAdManager forwardUnityEventWithArgs: @{@"name" : @"OnVariablesUpdatedEvent"}]; -} - - (MAAd *)adWithAdUnitIdentifier:(NSString *)adUnitIdentifier { @synchronized ( self.adInfoDictLock ) diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta index 6cd047c..8c3581e 100644 --- a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6106db18e3d7745c0a67bd23e2996272 +guid: 2973e70bd2fa74984b35aea07ae9db52 labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm b/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm index 7db976f..edac38f 100644 --- a/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm @@ -33,6 +33,7 @@ extern "C" static NSString *_userIdentifierToSet; static NSString *_userSegmentNameToSet; static NSArray *_testDeviceIdentifiersToSet; + static NSNumber *_mutedToSet; static NSNumber *_verboseLoggingToSet; static NSNumber *_creativeDebuggerEnabledToSet; static NSNumber *_exceptionHandlerEnabledToSet; @@ -50,12 +51,17 @@ extern "C" // Helper method to create C string copy static const char * cStringCopy(NSString *string); // Helper method to log errors - void logUninitializedAccessError(char *callingMethod); + void logUninitializedAccessError(const char *callingMethod); bool isPluginInitialized() { return _isPluginInitialized; } + + bool isReadyToInteractWithSdk() + { + return isPluginInitialized() && _sdk; + } void maybeInitializePlugin() { @@ -65,12 +71,34 @@ extern "C" _isPluginInitialized = true; } + id getLocalExtraParameterValue(const char *json) + { + NSData *jsonData = [NSSTRING(json) dataUsingEncoding: NSUTF8StringEncoding]; + NSError *error; + NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData: jsonData + options: 0 + error: &error]; + + if ( error ) + { + return nil; + } + else + { + return jsonDict[@"value"]; + } + } + NSArray * toStringArray(char **arrayPointer, int size) { NSMutableArray *array = [NSMutableArray arrayWithCapacity: size]; for ( int i = 0; i < size; i++ ) { - [array addObject: NSSTRING(arrayPointer[i])]; + NSString *element = NSSTRING(arrayPointer[i]); + if ( element ) + { + [array addObject: element]; + } } return array; @@ -105,25 +133,31 @@ extern "C" _testDeviceIdentifiersToSet = nil; } - if ( _verboseLoggingToSet ) + if ( _mutedToSet != nil) + { + settings.muted = _mutedToSet.boolValue; + _mutedToSet = nil; + } + + if ( _verboseLoggingToSet != nil ) { settings.verboseLoggingEnabled = _verboseLoggingToSet.boolValue; _verboseLoggingToSet = nil; } - if ( _creativeDebuggerEnabledToSet ) + if ( _creativeDebuggerEnabledToSet != nil ) { settings.creativeDebuggerEnabled = _creativeDebuggerEnabledToSet.boolValue; _creativeDebuggerEnabledToSet = nil; } - if ( _exceptionHandlerEnabledToSet ) + if ( _exceptionHandlerEnabledToSet != nil ) { settings.exceptionHandlerEnabled = _exceptionHandlerEnabledToSet.boolValue; _exceptionHandlerEnabledToSet = nil; } - if ( _locationCollectionEnabledToSet ) + if ( _locationCollectionEnabledToSet != nil ) { settings.locationCollectionEnabled = _locationCollectionEnabledToSet.boolValue; _locationCollectionEnabledToSet = nil; @@ -214,7 +248,7 @@ extern "C" _userSegmentNameToSet = nil; } - if ( _targetingYearOfBirth ) + if ( _targetingYearOfBirth != nil ) { _sdk.targetingData.yearOfBirth = _targetingYearOfBirth.intValue <= 0 ? nil : _targetingYearOfBirth; _targetingYearOfBirth = nil; @@ -226,7 +260,7 @@ extern "C" _targetingGender = nil; } - if ( _targetingMaximumAdContentRating ) + if ( _targetingMaximumAdContentRating != nil ) { _sdk.targetingData.maximumAdContentRating = getAppLovinAdContentRating(_targetingMaximumAdContentRating.intValue); _targetingMaximumAdContentRating = nil; @@ -453,10 +487,12 @@ extern "C" return cStringCopy(@""); } + NSString *consentFlowUserGeographyStr = @(_sdk.configuration.consentFlowUserGeography).stringValue; NSString *consentDialogStateStr = @(_sdk.configuration.consentDialogState).stringValue; NSString *appTrackingStatus = @(_sdk.configuration.appTrackingTransparencyStatus).stringValue; // Deliberately name it `appTrackingStatus` to be a bit more generic (in case Android introduces a similar concept) - return cStringCopy([MAUnityAdManager serializeParameters: @{@"consentDialogState" : consentDialogStateStr, + return cStringCopy([MAUnityAdManager serializeParameters: @{@"consentFlowUserGeography" : consentFlowUserGeographyStr, + @"consentDialogState" : consentDialogStateStr, @"countryCode" : _sdk.configuration.countryCode, @"appTrackingStatus" : appTrackingStatus, @"isSuccessfullyInitialized" : @([_sdk isInitialized]), @@ -564,10 +600,28 @@ extern "C" void _MaxSetBannerLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetBannerLocalExtraParameter"); + } + [_adManager setBannerLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) key: NSSTRING(key) value: (__bridge id) value]; } + + void _MaxSetBannerLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetBannerLocalExtraParameter"); + } + + id value = getLocalExtraParameterValue(json); + [_adManager setBannerLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } void _MaxSetBannerCustomData(const char *adUnitIdentifier, const char *customData) { @@ -697,10 +751,28 @@ extern "C" void _MaxSetMRecLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetMRecLocalExtraParameter"); + } + [_adManager setMRecLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) key: NSSTRING(key) value: (__bridge id)value]; } + + void _MaxSetMRecLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetMRecLocalExtraParameter"); + } + + id value = getLocalExtraParameterValue(json); + [_adManager setMRecLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } void _MaxSetMRecCustomData(const char *adUnitIdentifier, const char *customData) { @@ -775,11 +847,29 @@ extern "C" void _MaxSetInterstitialLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetInterstitialLocalExtraParameter"); + } + [_adManager setInterstitialLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) key: NSSTRING(key) value: (__bridge id)value]; } + void _MaxSetInterstitialLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetInterstitialLocalExtraParameter"); + } + + id value = getLocalExtraParameterValue(json); + [_adManager setInterstitialLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + bool _MaxIsInterstitialReady(const char *adUnitIdentifier) { if (!isPluginInitialized()) return false; @@ -810,10 +900,28 @@ extern "C" void _MaxSetAppOpenAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetAppOpenAdLocalExtraParameter"); + } + [_adManager setAppOpenAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) key: NSSTRING(key) value: (__bridge id)value]; } + + void _MaxSetAppOpenAdLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetAppOpenAdLocalExtraParameter"); + } + + id value = getLocalExtraParameterValue(json); + [_adManager setAppOpenAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } bool _MaxIsAppOpenAdReady(const char *adUnitIdentifier) { @@ -845,11 +953,29 @@ extern "C" void _MaxSetRewardedAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetRewardedAdLocalExtraParameter"); + } + [_adManager setRewardedAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) key: NSSTRING(key) value: (__bridge id)value]; } + void _MaxSetRewardedAdLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetRewardedAdLocalExtraParameter"); + } + + id value = getLocalExtraParameterValue(json); + [_adManager setRewardedAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + bool _MaxIsRewardedAdReady(const char *adUnitIdentifier) { if (!isPluginInitialized()) return false; @@ -880,11 +1006,29 @@ extern "C" void _MaxSetRewardedInterstitialAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetRewardedInterstitialAdLocalExtraParameter"); + } + [_adManager setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) key: NSSTRING(key) value: (__bridge id)value]; } + void _MaxSetRewardedInterstitialAdLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !isReadyToInteractWithSdk() ) + { + logUninitializedAccessError("_MaxSetRewardedInterstitialAdLocalExtraParameter"); + } + + id value = getLocalExtraParameterValue(json); + [_adManager setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + bool _MaxIsRewardedInterstitialAdReady(const char *adUnitIdentifier) { if (!isPluginInitialized()) return false; @@ -905,20 +1049,6 @@ extern "C" [_adManager trackEvent: NSSTRING(event) parameters: NSSTRING(parameters)]; } - - bool _MaxGetBool(const char *key, bool defaultValue) - { - if ( !_sdk ) return defaultValue; - - return [_sdk.variableService boolForKey: NSSTRING(key) defaultValue: defaultValue]; - } - - const char * _MaxGetString(const char *key, const char *defaultValue) - { - if ( !_sdk ) return defaultValue; - - return cStringCopy([_sdk.variableService stringForKey: NSSTRING(key) defaultValue: NSSTRING(defaultValue)]); - } bool _MaxIsTablet() { @@ -929,6 +1059,32 @@ extern "C" { return !ALUtils.simulator; } + + int _MaxGetTcfConsentStatus(int vendorIdentifier) + { + NSNumber *consentStatus = [ALUtils tcfConsentStatusForVendorIdentifier: vendorIdentifier]; + if ( consentStatus ) + { + return consentStatus.intValue; + } + else + { + return -1; + } + } + + int _MaxGetAdditionalConsentStatus(int atpIdentifier) + { + NSNumber *consentStatus = [ALUtils additionalConsentStatusForATPIdentifier: atpIdentifier]; + if ( consentStatus ) + { + return consentStatus.intValue; + } + else + { + return -1; + } + } static const char * cStringCopy(NSString *string) { @@ -938,16 +1094,29 @@ extern "C" void _MaxSetMuted(bool muted) { - if ( !_sdk ) return; - - _sdk.settings.muted = muted; + if ( _sdk ) + { + _sdk.settings.muted = muted; + _mutedToSet = nil; + } + else + { + _mutedToSet = @(muted); + } } bool _MaxIsMuted() { - if ( !_sdk ) return false; + if ( _sdk ) + { + return _sdk.settings.muted; + } + else if ( _mutedToSet != nil ) + { + return _mutedToSet.boolValue; + } - return _sdk.settings.muted; + return false; } float _MaxScreenDensity() @@ -984,9 +1153,9 @@ extern "C" { return [_sdk.settings isVerboseLoggingEnabled]; } - else if ( _verboseLoggingToSet ) + else if ( _verboseLoggingToSet != nil ) { - return _verboseLoggingToSet; + return _verboseLoggingToSet.boolValue; } return false; @@ -1060,27 +1229,27 @@ extern "C" } } } - - const char * _MaxGetCFType() - { - if ( !_sdk ) - { - NSLog(@"[%@] Failed to get available mediated networks - please ensure the AppLovin MAX Unity Plugin has been initialized by calling 'MaxSdk.InitializeSdk();'!", TAG); - return cStringCopy(@(ALCFTypeUnknown).stringValue); - } - - return cStringCopy(@(_sdk.cfService.cfType).stringValue); - } - - void _MaxStartConsentFlow() + + void _MaxShowCmpForExistingUser() { if (!isPluginInitialized()) { - logUninitializedAccessError("_MaxStartConsentFlow"); + logUninitializedAccessError("_MaxShowCmpForExistingUser"); return; } - [_adManager startConsentFlow]; + [_adManager showCMPForExistingUser]; + } + + bool _MaxHasSupportedCmp() + { + if (!isPluginInitialized()) + { + logUninitializedAccessError("_MaxHasSupportedCmp"); + return false; + } + + return [_sdk.cmpService hasSupportedCMP]; } float _MaxGetAdaptiveBannerHeight(const float width) @@ -1088,18 +1257,10 @@ extern "C" return [MAUnityAdManager adaptiveBannerHeightForWidth: width]; } - void logUninitializedAccessError(char *callingMethod) + void logUninitializedAccessError(const char *callingMethod) { NSLog(@"[%@] Failed to execute: %s - please ensure the AppLovin MAX Unity Plugin has been initialized by calling 'MaxSdk.InitializeSdk();'!", TAG, callingMethod); } - - [[deprecated("This API has been deprecated. Please use our SDK's initialization callback to retrieve variables instead.")]] - void _MaxLoadVariables() - { - if (!isPluginInitialized()) return; - - [_adManager loadVariables]; - } } #pragma clang diagnostic pop diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta b/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta index 5d8ad34..5ea08ff 100644 --- a/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 193b1bac1aa9a4e1292257dc02aa3ec5 +guid: 7e373ed7168b243e6b706e991ab5a643 labels: - al_max - al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm diff --git a/MaxSdk/Prefabs.meta b/MaxSdk/Prefabs.meta index 83cc3ce..d017132 100644 --- a/MaxSdk/Prefabs.meta +++ b/MaxSdk/Prefabs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2f02c68646b3246d1822c96d17458b4d +guid: 60751ca71e0eb4db49941064964cb08c labels: - al_max - al_max_export_path-MaxSdk/Prefabs diff --git a/MaxSdk/Prefabs/BannerBottom.prefab.meta b/MaxSdk/Prefabs/BannerBottom.prefab.meta index fc73161..153cfcf 100644 --- a/MaxSdk/Prefabs/BannerBottom.prefab.meta +++ b/MaxSdk/Prefabs/BannerBottom.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c40cd08161edf43b49140ec091e9f067 +guid: 54c062c0526b148efa2ea2e9489b3aa0 labels: - al_max - al_max_export_path-MaxSdk/Prefabs/BannerBottom.prefab diff --git a/MaxSdk/Prefabs/BannerTop.prefab.meta b/MaxSdk/Prefabs/BannerTop.prefab.meta index c1e2ca1..52ef464 100644 --- a/MaxSdk/Prefabs/BannerTop.prefab.meta +++ b/MaxSdk/Prefabs/BannerTop.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9b4937edd18714f3ebeb656de6e4d54b +guid: 6521750c87fd14f709d09a1e38ffde47 labels: - al_max - al_max_export_path-MaxSdk/Prefabs/BannerTop.prefab diff --git a/MaxSdk/Prefabs/Interstitial.prefab.meta b/MaxSdk/Prefabs/Interstitial.prefab.meta index d8b7b5b..4fa240b 100644 --- a/MaxSdk/Prefabs/Interstitial.prefab.meta +++ b/MaxSdk/Prefabs/Interstitial.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 06407a673b7194053b3fb593a9933c95 +guid: 3fc0c2627ce8a4490b8e319326f8a535 labels: - al_max - al_max_export_path-MaxSdk/Prefabs/Interstitial.prefab diff --git a/MaxSdk/Prefabs/Rewarded.prefab.meta b/MaxSdk/Prefabs/Rewarded.prefab.meta index 503754d..214bea1 100644 --- a/MaxSdk/Prefabs/Rewarded.prefab.meta +++ b/MaxSdk/Prefabs/Rewarded.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 72244923a898c463c912b2675256c85c +guid: a28c1544d6f094d5eafc8da2343c9119 labels: - al_max - al_max_export_path-MaxSdk/Prefabs/Rewarded.prefab diff --git a/MaxSdk/Resources.meta b/MaxSdk/Resources.meta index 85845f7..be36d03 100644 --- a/MaxSdk/Resources.meta +++ b/MaxSdk/Resources.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a1858b796f36642b8bcdcd9e7e3499e4 +guid: 3d4208cf7aaa64c71b19b2d4468d029b labels: - al_max - al_max_export_path-MaxSdk/Resources diff --git a/MaxSdk/Resources/Images.meta b/MaxSdk/Resources/Images.meta index 557d3a8..cfacfa5 100644 --- a/MaxSdk/Resources/Images.meta +++ b/MaxSdk/Resources/Images.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: afea262d96e02419e89cbd76ec9c309b +guid: 5c7cba3bc9ef5454ea7d5f9bd1dffd22 labels: - al_max - al_max_export_path-MaxSdk/Resources/Images diff --git a/MaxSdk/Resources/Images/alert_icon.png.meta b/MaxSdk/Resources/Images/alert_icon.png.meta index b3b2d45..634d290 100644 --- a/MaxSdk/Resources/Images/alert_icon.png.meta +++ b/MaxSdk/Resources/Images/alert_icon.png.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 39fa469b3fe3544888d5f706a27da06f +guid: 572fee4574afa4f6dbf2846e0c152fe8 labels: - al_max - al_max_export_path-MaxSdk/Resources/Images/alert_icon.png diff --git a/MaxSdk/Resources/Images/uninstall_icon.png.meta b/MaxSdk/Resources/Images/uninstall_icon.png.meta index d458454..0f39816 100644 --- a/MaxSdk/Resources/Images/uninstall_icon.png.meta +++ b/MaxSdk/Resources/Images/uninstall_icon.png.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 63817ca5b9e284a488a67b769db18813 +guid: d24994f48fdd0430692e3d49279cd782 labels: - al_max - al_max_export_path-MaxSdk/Resources/Images/uninstall_icon.png diff --git a/MaxSdk/Resources/Images/warning_icon.png.meta b/MaxSdk/Resources/Images/warning_icon.png.meta index d74ff37..ee4941c 100644 --- a/MaxSdk/Resources/Images/warning_icon.png.meta +++ b/MaxSdk/Resources/Images/warning_icon.png.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 966e6c9af57a640288672d89ee58a2fc +guid: b504c956e7ed744b6b0e7f014e1cac5a labels: - al_max - al_max_export_path-MaxSdk/Resources/Images/warning_icon.png diff --git a/MaxSdk/Scripts.meta b/MaxSdk/Scripts.meta index befb8c9..bda0c74 100644 --- a/MaxSdk/Scripts.meta +++ b/MaxSdk/Scripts.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: da3d2b54764a24ac0a8ce8394b67467f +guid: 7f9882faebe0b4edaabf65e14a921fcb labels: - al_max - al_max_export_path-MaxSdk/Scripts diff --git a/MaxSdk/Scripts/Editor.meta b/MaxSdk/Scripts/Editor.meta index 15aed79..7adfefb 100644 --- a/MaxSdk/Scripts/Editor.meta +++ b/MaxSdk/Scripts/Editor.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2b64bca2685cb419f847736eb5a1ac92 +guid: b6903b66cb8984df289e6d66f9c52ddc labels: - al_max - al_max_export_path-MaxSdk/Scripts/Editor diff --git a/MaxSdk/Scripts/Editor/MaxInitialization.cs b/MaxSdk/Scripts/Editor/MaxInitialization.cs index 16c0ccb..a1dc1df 100644 --- a/MaxSdk/Scripts/Editor/MaxInitialization.cs +++ b/MaxSdk/Scripts/Editor/MaxInitialization.cs @@ -20,11 +20,11 @@ namespace AppLovinMax.Scripts.Editor private static readonly List ObsoleteNetworks = new List { "Snap", + "Tapjoy", "VerizonAds", "VoodooAds" }; -#if UNITY_2018_2_OR_NEWER private static readonly List ObsoleteFileExportPathsToDelete = new List { // The `EventSystemChecker` has been renamed to `MaxEventSystemChecker`. @@ -45,7 +45,7 @@ namespace AppLovinMax.Scripts.Editor "Plugins/Android/MaxMediationGoogle.androidlib", "Plugins/Android/MaxMediationGoogle.androidlib.meta", - // Google Ad Manager adapter pre/post process scripts. The logic has been migrated to the main plugin + // Google Ad Manager adapter pre/post process scripts. The logic has been migrated to the main plugin. "MaxSdk/Mediation/GoogleAdManager/Editor/MaxGoogleAdManagerInitialize.cs", "MaxSdk/Mediation/GoogleAdManager/Editor/MaxGoogleAdManagerInitialize.cs.meta", "MaxSdk/Mediation/GoogleAdManager/Editor/PostProcessor.cs", @@ -53,9 +53,16 @@ namespace AppLovinMax.Scripts.Editor "MaxSdk/Mediation/GoogleAdManager/Editor/MaxSdk.Mediation.GoogleAdManager.Editor.asmdef", "MaxSdk/Mediation/GoogleAdManager/Editor/MaxSdk.Mediation.GoogleAdManager.Editor.asmdef.meta", "Plugins/Android/MaxMediationGoogleAdManager.androidlib", - "Plugins/Android/MaxMediationGoogleAdManager.androidlib.meta" + "Plugins/Android/MaxMediationGoogleAdManager.androidlib.meta", + + // The `VariableService` has been removed. + "MaxSdk/Scripts/MaxVariableServiceAndroid.cs", + "MaxSdk/Scripts/MaxVariableServiceAndroid.cs.meta", + "MaxSdk/Scripts/MaxVariableServiceiOS.cs", + "MaxSdk/Scripts/MaxVariableServiceiOS.cs.meta", + "MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs", + "MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs.meta" }; -#endif static MaxInitialize() { @@ -84,7 +91,6 @@ namespace AppLovinMax.Scripts.Editor AppLovinIntegrationManager.AddLabelsToAssetsIfNeeded(pluginParentDir, isPluginOutsideAssetsDir); -#if UNITY_2018_2_OR_NEWER foreach (var obsoleteFileExportPathToDelete in ObsoleteFileExportPathsToDelete) { var pathToDelete = MaxSdkUtils.GetAssetPathForExportPath(obsoleteFileExportPathToDelete); @@ -95,7 +101,6 @@ namespace AppLovinMax.Scripts.Editor changesMade = true; } } -#endif // Check if any obsolete networks are installed foreach (var obsoleteNetwork in ObsoleteNetworks) diff --git a/MaxSdk/Scripts/Editor/MaxInitialization.cs.meta b/MaxSdk/Scripts/Editor/MaxInitialization.cs.meta index aaafdd0..a96a577 100644 --- a/MaxSdk/Scripts/Editor/MaxInitialization.cs.meta +++ b/MaxSdk/Scripts/Editor/MaxInitialization.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 512169ab4bfaf406c81d28878b456b30 +guid: bc0c5693335e0408a95293c0d7b61137 labels: - al_max - al_max_export_path-MaxSdk/Scripts/Editor/MaxInitialization.cs diff --git a/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs b/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs index 8ad8aee..c0d1e13 100644 --- a/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs +++ b/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs @@ -6,7 +6,7 @@ // Copyright © 2020 AppLovin. All rights reserved. // -#if UNITY_ANDROID && UNITY_2018_2_OR_NEWER +#if UNITY_ANDROID using AppLovinMax.Scripts.IntegrationManager.Editor; using System; using System.Collections.Generic; @@ -93,9 +93,8 @@ namespace AppLovinMax.Scripts.Editor ProcessAndroidManifest(path); var rawResourceDirectory = Path.Combine(path, "src/main/res/raw"); - if (AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager) + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) { - // For Unity 2018.1 or older, the consent flow is enabled in AppLovinPreProcessAndroid. AppLovinPreProcessAndroid.EnableConsentFlowIfNeeded(rawResourceDirectory); } else diff --git a/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs.meta b/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs.meta index 80d55e9..07e4133 100644 --- a/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs.meta +++ b/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 87732883951bc404e85f2a223d3bd7c8 +guid: 75fed160a41749d4990cee871ee618a4 labels: - al_max - al_max_export_path-MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs diff --git a/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs b/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs index 9dd3d7d..816c336 100644 --- a/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs +++ b/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs @@ -45,17 +45,21 @@ namespace AppLovinMax.Scripts.Editor private const string KeyConsentFlowEnabled = "ConsentFlowEnabled"; private const string KeyConsentFlowTermsOfService = "ConsentFlowTermsOfService"; private const string KeyConsentFlowPrivacyPolicy = "ConsentFlowPrivacyPolicy"; - private const string KeyConsentFlowAdvertisingPartners = "ConsentFlowAdvertisingPartners"; - private const string KeyConsentFlowIncludeDefaultAdvertisingPartners = "ConsentFlowIncludeDefaultAdvertisingPartners"; - private const string KeyConsentFlowAnalyticsPartners = "ConsentFlowAnalyticsPartners"; - private const string KeyConsentFlowIncludeDefaultAnalyticsPartners = "ConsentFlowIncludeDefaultAnalyticsPartners"; + private const string KeyConsentFlowDebugUserGeography = "ConsentFlowDebugUserGeography"; private static readonly List DynamicLibrariesToEmbed = new List { "DTBiOSSDK.xcframework", + "FBAEMKit.xcframework", "FBSDKCoreKit_Basics.xcframework", + "FBSDKCoreKit.xcframework", + "FBSDKGamingServicesKit.xcframework", + "FBSDKLoginKit.xcframework", + "FBSDKShareKit.xcframework", "HyprMX.xcframework", + "LinkedinAudienceNetwork.xcframework", "IASDKCore.xcframework", + "Maio.xcframework", "MobileFuseSDK.xcframework", "OMSDK_Appodeal.xcframework", "OMSDK_Ogury.xcframework", @@ -63,31 +67,6 @@ namespace AppLovinMax.Scripts.Editor "OMSDK_Smaato.xcframework" }; - private static List SwiftLanguageNetworks - { - get - { - var swiftLanguageNetworks = new List(); - if (AppLovinIntegrationManager.IsAdapterInstalled("Facebook", "6.9.0.0")) - { - swiftLanguageNetworks.Add("Facebook"); - } - - if (AppLovinIntegrationManager.IsAdapterInstalled("UnityAds", "4.4.0.0")) - { - swiftLanguageNetworks.Add("UnityAds"); - } - - return swiftLanguageNetworks; - } - } - - private static readonly List EmbedSwiftStandardLibrariesNetworks = new List - { - "Facebook", - "UnityAds" - }; - private static string PluginMediationDirectory { get @@ -113,7 +92,7 @@ namespace AppLovinMax.Scripts.Editor #endif EmbedDynamicLibrariesIfNeeded(buildPath, project, unityMainTargetGuid); - var internalSettingsEnabled = AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager; + var internalSettingsEnabled = AppLovinInternalSettings.Instance.ConsentFlowEnabled; var userTrackingUsageDescriptionDe = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe : AppLovinSettings.Instance.UserTrackingUsageDescriptionDe; LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionDe, "de", buildPath, project, unityMainTargetGuid); var userTrackingUsageDescriptionEn = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn : AppLovinSettings.Instance.UserTrackingUsageDescriptionEn; @@ -131,8 +110,7 @@ namespace AppLovinMax.Scripts.Editor var userTrackingUsageDescriptionZhHant = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant : AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHant; LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionZhHant, "zh-Hant", buildPath, project, unityMainTargetGuid); - AddSwiftSupportIfNeeded(buildPath, project, unityFrameworkTargetGuid); - EmbedSwiftStandardLibrariesIfNeeded(buildPath, project, unityMainTargetGuid); + AddSwiftSupport(buildPath, project, unityFrameworkTargetGuid, unityMainTargetGuid); AddYandexSettingsIfNeeded(project, unityMainTargetGuid); project.WriteToFile(projectPath); @@ -171,11 +149,7 @@ namespace AppLovinMax.Scripts.Editor } #else string runpathSearchPaths; -#if UNITY_2018_2_OR_NEWER runpathSearchPaths = project.GetBuildPropertyForAnyConfig(targetGuid, "LD_RUNPATH_SEARCH_PATHS"); -#else - runpathSearchPaths = "$(inherited)"; -#endif runpathSearchPaths += string.IsNullOrEmpty(runpathSearchPaths) ? "" : " "; // Check if runtime search paths already contains the required search paths for dynamic libraries. @@ -258,77 +232,32 @@ namespace AppLovinMax.Scripts.Editor if (string.IsNullOrEmpty(localizedUserTrackingDescription)) return true; var settings = AppLovinSettings.Instance; - var internalSettingsEnabled = settings.ShowInternalSettingsInIntegrationManager; - if (internalSettingsEnabled) - { - var internalSettings = AppLovinInternalSettings.Instance; - return !internalSettings.ConsentFlowEnabled || !internalSettings.UserTrackingUsageLocalizationEnabled; - } + var internalSettings = AppLovinInternalSettings.Instance; - return !settings.ConsentFlowEnabled || !settings.UserTrackingUsageLocalizationEnabled; + return (!internalSettings.ConsentFlowEnabled || !internalSettings.UserTrackingUsageLocalizationEnabled) + && !settings.ConsentFlowEnabled || !settings.UserTrackingUsageLocalizationEnabled; } - private static void AddSwiftSupportIfNeeded(string buildPath, PBXProject project, string targetGuid) + private static void AddSwiftSupport(string buildPath, PBXProject project, string unityFrameworkTargetGuid, string unityMainTargetGuid) { var swiftFileRelativePath = "Classes/MAXSwiftSupport.swift"; var swiftFilePath = Path.Combine(buildPath, swiftFileRelativePath); - var maxMediationDirectory = PluginMediationDirectory; - var hasSwiftLanguageNetworksInProject = SwiftLanguageNetworks.Any(network => Directory.Exists(Path.Combine(maxMediationDirectory, network))); - - // Remove Swift file if no need to support Swift - if (!hasSwiftLanguageNetworksInProject) - { - if (File.Exists(swiftFilePath)) - { - MaxSdkLogger.UserDebug("Removing Swift file references."); - - var fileGuid = project.FindFileGuidByRealPath(swiftFilePath, PBXSourceTree.Source); - if (!string.IsNullOrEmpty(fileGuid)) - { - project.RemoveFile(fileGuid); - project.RemoveFileFromBuild(targetGuid, fileGuid); - - FileUtil.DeleteFileOrDirectory(swiftFilePath); - } - } - - return; - } // Add Swift file CreateSwiftFile(swiftFilePath); var swiftFileGuid = project.AddFile(swiftFileRelativePath, swiftFileRelativePath, PBXSourceTree.Source); - project.AddFileToBuild(targetGuid, swiftFileGuid); + project.AddFileToBuild(unityFrameworkTargetGuid, swiftFileGuid); // Add Swift version property if needed -#if UNITY_2018_2_OR_NEWER - var swiftVersion = project.GetBuildPropertyForAnyConfig(targetGuid, "SWIFT_VERSION"); -#else - // Assume that swift version is not set on older versions of Unity. - const string swiftVersion = ""; -#endif + var swiftVersion = project.GetBuildPropertyForAnyConfig(unityFrameworkTargetGuid, "SWIFT_VERSION"); if (string.IsNullOrEmpty(swiftVersion)) { - project.SetBuildProperty(targetGuid, "SWIFT_VERSION", "5.0"); + project.SetBuildProperty(unityFrameworkTargetGuid, "SWIFT_VERSION", "5.0"); } // Enable Swift modules - project.AddBuildProperty(targetGuid, "CLANG_ENABLE_MODULES", "YES"); - } - - /// - /// For Swift 5+ code that uses the standard libraries, the Swift Standard Libraries MUST be embedded for iOS < 12.2 - /// Swift 5 introduced ABI stability, which allowed iOS to start bundling the standard libraries in the OS starting with iOS 12.2 - /// Issue Reference: https://github.com/facebook/facebook-sdk-for-unity/issues/506 - /// - private static void EmbedSwiftStandardLibrariesIfNeeded(string buildPath, PBXProject project, string mainTargetGuid) - { - var maxMediationDirectory = PluginMediationDirectory; - var hasEmbedSwiftStandardLibrariesNetworksInProject = EmbedSwiftStandardLibrariesNetworks.Any(network => Directory.Exists(Path.Combine(maxMediationDirectory, network))); - if (!hasEmbedSwiftStandardLibrariesNetworksInProject) return; - - // This needs to be added the main target. App Store may reject builds if added to UnityFramework (i.e. MoPub in FT). - project.AddBuildProperty(mainTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES"); + project.AddBuildProperty(unityFrameworkTargetGuid, "CLANG_ENABLE_MODULES", "YES"); + project.AddBuildProperty(unityMainTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES"); } private static void CreateSwiftFile(string swiftFilePath) @@ -356,10 +285,8 @@ namespace AppLovinMax.Scripts.Editor SetSdkKeyIfNeeded(plist); SetAttributionReportEndpointIfNeeded(plist); -#if UNITY_2018_2_OR_NEWER EnableVerboseLoggingIfNeeded(plist); AddGoogleApplicationIdIfNeeded(plist); -#endif AddSdkSettingsIfNeeded(plist, path); EnableTermsFlowIfNeeded(plist); @@ -396,7 +323,6 @@ namespace AppLovinMax.Scripts.Editor } } -#if UNITY_2018_2_OR_NEWER private static void EnableVerboseLoggingIfNeeded(PlistDocument plist) { if (!EditorPrefs.HasKey(MaxSdkLogger.KeyVerboseLoggingEnabled)) return; @@ -428,7 +354,6 @@ namespace AppLovinMax.Scripts.Editor plist.root.SetString(googleApplicationIdentifier, appId); } -#endif private static void AddYandexSettingsIfNeeded(PBXProject project, string unityMainTargetGuid) { @@ -445,8 +370,6 @@ namespace AppLovinMax.Scripts.Editor private static void AddSdkSettingsIfNeeded(PlistDocument infoPlist, string buildPath) { - if (!AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager) return; - // Right now internal settings is only needed for Consent Flow. Remove this setting once we add more settings. if (!AppLovinInternalSettings.Instance.ConsentFlowEnabled) return; @@ -495,44 +418,22 @@ namespace AppLovinMax.Scripts.Editor consentFlowInfoRoot.SetString(KeyConsentFlowPrivacyPolicy, privacyPolicyUrl); var termsOfServiceUrl = AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl; - if (!string.IsNullOrEmpty(termsOfServiceUrl)) + if (MaxSdkUtils.IsValidString(termsOfServiceUrl)) { consentFlowInfoRoot.SetString(KeyConsentFlowTermsOfService, termsOfServiceUrl); } - var advertisingPartnerUrls = AppLovinInternalSettings.Instance.ConsentFlowAdvertisingPartnerUrls; - if (MaxSdkUtils.IsValidString(advertisingPartnerUrls)) + var debugUserGeography = AppLovinInternalSettings.Instance.DebugUserGeography; + if (debugUserGeography == MaxSdkBase.ConsentFlowUserGeography.Gdpr) { - var advertisingPartnerUrlsList = advertisingPartnerUrls.Split(','); - var advertisingPartnersArray = consentFlowInfoRoot.CreateArray(KeyConsentFlowAdvertisingPartners); - foreach (var advertisingPartner in advertisingPartnerUrlsList) - { - advertisingPartnersArray.AddString(advertisingPartner); - } + consentFlowInfoRoot.SetString(KeyConsentFlowDebugUserGeography, "gdpr"); } - consentFlowInfoRoot.SetBoolean(KeyConsentFlowIncludeDefaultAdvertisingPartners, AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAdvertisingPartnerUrls); - - var analyticsPartnerUrls = AppLovinInternalSettings.Instance.ConsentFlowAnalyticsPartnerUrls; - if (MaxSdkUtils.IsValidString(analyticsPartnerUrls)) - { - var analyticsPartnerUrlsList = analyticsPartnerUrls.Split(','); - var analyticsPartnersArray = consentFlowInfoRoot.CreateArray(KeyConsentFlowAnalyticsPartners); - foreach (var analyticsPartnerUrl in analyticsPartnerUrlsList) - { - analyticsPartnersArray.AddString(analyticsPartnerUrl); - } - } - - consentFlowInfoRoot.SetBoolean(KeyConsentFlowIncludeDefaultAnalyticsPartners, AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAnalyticsPartnerUrls); - infoPlist.root.SetString("NSUserTrackingUsageDescription", userTrackingUsageDescription); } private static void EnableTermsFlowIfNeeded(PlistDocument plist) { - if (AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager) return; - // Check if terms flow is enabled. No need to update info.plist if consent flow is disabled. var consentFlowEnabled = AppLovinSettings.Instance.ConsentFlowEnabled; if (!consentFlowEnabled) return; @@ -625,37 +526,36 @@ namespace AppLovinMax.Scripts.Editor private static SkAdNetworkData GetSkAdNetworkData() { - var uriBuilder = new UriBuilder("https://dash.applovin.com/docs/v1/unity_integration_manager/sk_ad_networks_info"); + var uriBuilder = new UriBuilder("https://unity.applovin.com/max/1.0/skadnetwork_ids"); // Get the list of installed ad networks to be passed up var maxMediationDirectory = PluginMediationDirectory; if (Directory.Exists(maxMediationDirectory)) { var mediationNetworkDirectories = Directory.GetDirectories(maxMediationDirectory); - var installedNetworks = mediationNetworkDirectories.Select(Path.GetFileName).ToArray(); - var adNetworks = string.Join(",", installedNetworks); + var installedNetworks = mediationNetworkDirectories.Select(Path.GetFileName).ToList(); + if (AppLovinSettings.Instance.AddApsSkAdNetworkIds) + { + installedNetworks.Add("AmazonPublisherServices"); + } + + var adNetworks = string.Join(",", installedNetworks.ToArray()); if (!string.IsNullOrEmpty(adNetworks)) { - uriBuilder.Query += string.Format("adnetworks={0}", adNetworks); + uriBuilder.Query += string.Format("ad_networks={0}", adNetworks); } } using (var unityWebRequest = UnityWebRequest.Get(uriBuilder.ToString())) { -#if UNITY_2017_2_OR_NEWER var operation = unityWebRequest.SendWebRequest(); -#else - var operation = unityWebRequest.Send(); -#endif // Wait for the download to complete or the request to timeout. while (!operation.isDone) { } #if UNITY_2020_1_OR_NEWER if (unityWebRequest.result != UnityWebRequest.Result.Success) -#elif UNITY_2017_2_OR_NEWER - if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) #else - if (unityWebRequest.isError) + if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) #endif { MaxSdkLogger.UserError("Failed to retrieve SKAdNetwork IDs with error: " + unityWebRequest.error); diff --git a/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs.meta b/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs.meta index 0c510bc..78d2f6d 100644 --- a/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs.meta +++ b/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e71caf465f5b24f848fa05c337203e79 +guid: 29959b3cd36c484a9d57d6b7ca7f7bfa labels: - al_max - al_max_export_path-MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs diff --git a/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef.meta b/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef.meta index 690992a..b13c71a 100644 --- a/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef.meta +++ b/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 75f93d930c51d43579f691746bd04a70 +guid: 691e0eb4b7a542dba2219d48c3254f1c labels: - al_max - al_max_export_path-MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef diff --git a/MaxSdk/Scripts/IntegrationManager.meta b/MaxSdk/Scripts/IntegrationManager.meta index 054e7b9..39f65cc 100644 --- a/MaxSdk/Scripts/IntegrationManager.meta +++ b/MaxSdk/Scripts/IntegrationManager.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9903db0d6994746d4bee2e4ac615e8ef +guid: e01816bc45c944d03afb95d035caf0e1 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager diff --git a/MaxSdk/Scripts/IntegrationManager/Editor.meta b/MaxSdk/Scripts/IntegrationManager/Editor.meta index 06993c4..1d8400a 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 735b8675e6ac746d0ac244312653f7f2 +guid: 0da229e279400497786c39933fe02e52 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs index 01cc639..2b3e87b 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs @@ -19,9 +19,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor public class AppLovinAutoUpdater { public const string KeyAutoUpdateEnabled = "com.applovin.auto_update_enabled"; -#if !UNITY_2018_2_OR_NEWER - private const string KeyOldUnityVersionWarningShown = "com.applovin.old_unity_version_warning_shown"; -#endif private const string KeyLastUpdateCheckTime = "com.applovin.last_update_check_time_v2"; // Updated to v2 to force adapter version checks in plugin version 3.1.10. private static readonly DateTime EpochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static readonly int SecondsInADay = (int) TimeSpan.FromDays(1).TotalSeconds; @@ -39,7 +36,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor {"IRONSOURCE_NETWORK", "android_7.0.1.1.1_ios_7.0.1.0.1"}, {"MYTARGET_NETWORK", "android_5.9.1.2_ios_5.7.5.1"}, {"SMAATO_NETWORK", "android_21.5.2.5_ios_21.5.2.3"}, - {"TAPJOY_NETWORK", "android_12.6.1.5_ios_12.6.1.6"}, {"TIKTOK_NETWORK", "android_3.1.0.1.6_ios_3.2.5.1.1"}, {"UNITY_NETWORK", "android_3.4.8.2_ios_3.4.8.2"}, {"VERIZON_NETWORK", "android_1.6.0.5_ios_1.7.1.1"}, @@ -64,10 +60,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor // Update last checked time. EditorPrefs.SetInt(KeyLastUpdateCheckTime, now); -#if !UNITY_2018_2_OR_NEWER - ShowNotSupportingOldUnityVersionsIfNeeded(); -#endif - // Load the plugin data AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.LoadPluginData(data => { @@ -156,27 +148,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor AppLovinIntegrationManager.ShowBuildFailureDialog(message); } -#if !UNITY_2018_2_OR_NEWER - private static void ShowNotSupportingOldUnityVersionsIfNeeded() - { - // Check if publisher has seen the warning before - if (EditorPrefs.GetBool(KeyOldUnityVersionWarningShown, false)) return; - - // Show a dialog if they haven't seen the warning yet. - var option = EditorUtility.DisplayDialog( - "WARNING: Old Unity Version Detected", - "AppLovin MAX Unity plugin will soon require Unity 2018.2 or newer to function. Please upgrade to a newer Unity version.", - "Ok", - "Don't Ask Again" - ); - - if (!option) // 'false' means `Don't Ask Again` was clicked. - { - EditorPrefs.SetBool(KeyOldUnityVersionWarningShown, true); - } - } -#endif - private static bool GoogleNetworkAdaptersCompatible(string googleVersion, string googleAdManagerVersion, string breakingVersion) { var googleResult = MaxSdkUtils.CompareVersions(googleVersion, breakingVersion); diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta index 33f843c..0070e74 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: cad9b94a708924ff0a04401d8fe8f91e +guid: 8bcdd5226273242c5bd9ec79568202e6 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta index 8b9aea2..2c3ff20 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 869a2cef2a7a64292929ad064f924d02 +guid: 2d0aa55f9a7d2440f871dfb256372a33 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs deleted file mode 100644 index 75f359a..0000000 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// AppLovinDownloadHandler.cs -// AppLovin MAX Unity Plugin -// -// Created by Santosh Bagadi on 7/26/19. -// Copyright © 2019 AppLovin. All rights reserved. -// - -#if !UNITY_2017_2_OR_NEWER - -using System; -using System.IO; -using UnityEngine.Networking; - -namespace AppLovinMax.Scripts.IntegrationManager.Editor -{ - public class AppLovinDownloadHandler : DownloadHandlerScript - { - // Required by DownloadHandler base class. Called when you address the 'bytes' property. - protected override byte[] GetData() - { - return null; - } - - private FileStream fileStream; - - public AppLovinDownloadHandler(string path) : base(new byte[2048]) - { - var downloadDirectory = Path.GetDirectoryName(path); - if (!Directory.Exists(downloadDirectory)) - { - Directory.CreateDirectory(downloadDirectory); - } - - try - { - //Open the current file to write to - fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite); - } - catch (Exception exception) - { - MaxSdkLogger.UserError(string.Format("Failed to create file at {0}\n{1}", path, exception.Message)); - } - } - - protected override bool ReceiveData(byte[] byteFromServer, int dataLength) - { - if (byteFromServer == null || byteFromServer.Length < 1 || fileStream == null) - { - return false; - } - - try - { - //Write the current data to the file - fileStream.Write(byteFromServer, 0, dataLength); - } - catch (Exception exception) - { - fileStream.Close(); - fileStream = null; - MaxSdkLogger.UserError(string.Format("Failed to download file{0}", exception.Message)); - } - - return true; - } - - protected override void CompleteContent() - { - fileStream.Close(); - } - } -} - -#endif diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta index 8c0e60e..c622bab 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3c817f90804464e0b85d008d27c91f9e +guid: 95747c688378548eeb92aeb528ac96ff labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs index 1b328e1..3b1b9d9 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs @@ -24,6 +24,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor { public Network AppLovinMax; public Network[] MediatedNetworks; + public Network[] PartnerMicroSdks; } [Serializable] @@ -183,14 +184,10 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor /// /// Whether or not the plugin is under the Assets/ folder. /// -//--- INJECT PluginOutside START --- public static bool IsPluginOutsideAssetsDirectory - { get => !(PluginParentDirectory.StartsWith("Assets") || PluginParentDirectory.StartsWith("Packages")); } -//--- INJECT PluginOutside OVER --- -// { -// get { return !PluginParentDirectory.StartsWith("Assets"); } -// } - + { + get { return !PluginParentDirectory.StartsWith("Assets"); } + } /// /// Whether or not gradle build system is enabled. @@ -213,7 +210,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor /// public static bool CanProcessAndroidQualityServiceSettings { - get { return GradleTemplateEnabled || (GradleBuildEnabled && IsUnity2018_2OrNewer()); } + get { return GradleTemplateEnabled || GradleBuildEnabled; } } /// @@ -283,23 +280,17 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor /// Callback to be called once the plugin data download completes. public IEnumerator LoadPluginData(Action callback) { - var url = string.Format("https://dash.applovin.com/docs/v1/unity_integration_manager?plugin_version={0}", GetPluginVersionForUrl()); + var url = string.Format("https://unity.applovin.com/max/1.0/integration_manager_info?plugin_version={0}", MaxSdk.Version); using (var www = UnityWebRequest.Get(url)) { -#if UNITY_2017_2_OR_NEWER var operation = www.SendWebRequest(); -#else - var operation = www.Send(); -#endif while (!operation.isDone) yield return new WaitForSeconds(0.1f); // Just wait till www is done. Our coroutine is pretty rudimentary. #if UNITY_2020_1_OR_NEWER if (www.result != UnityWebRequest.Result.Success) -#elif UNITY_2017_2_OR_NEWER - if (www.isNetworkError || www.isHttpError) #else - if (www.isError) + if (www.isNetworkError || www.isHttpError) #endif { callback(null); @@ -329,6 +320,11 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor { UpdateCurrentVersions(network, mediationPluginParentDirectory); } + + foreach (var partnerMicroSdk in pluginData.PartnerMicroSdks) + { + UpdateCurrentVersions(partnerMicroSdk, mediationPluginParentDirectory); + } } callback(pluginData); @@ -410,22 +406,14 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor public IEnumerator DownloadPlugin(Network network, bool showImport = true) { var path = Path.Combine(Application.temporaryCachePath, GetPluginFileName(network)); // TODO: Maybe delete plugin file after finishing import. -#if UNITY_2017_2_OR_NEWER var downloadHandler = new DownloadHandlerFile(path); -#else - var downloadHandler = new AppLovinDownloadHandler(path); -#endif webRequest = new UnityWebRequest(network.DownloadUrl) { method = UnityWebRequest.kHttpVerbGET, downloadHandler = downloadHandler }; -#if UNITY_2017_2_OR_NEWER var operation = webRequest.SendWebRequest(); -#else - var operation = webRequest.Send(); -#endif while (!operation.isDone) { yield return new WaitForSeconds(0.1f); // Just wait till webRequest is completed. Our coroutine is pretty rudimentary. @@ -434,10 +422,8 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor #if UNITY_2020_1_OR_NEWER if (webRequest.result != UnityWebRequest.Result.Success) -#elif UNITY_2017_2_OR_NEWER - if (webRequest.isNetworkError || webRequest.isHttpError) #else - if (webRequest.isError) + if (webRequest.isNetworkError || webRequest.isHttpError) #endif { MaxSdkLogger.UserError(webRequest.error); @@ -593,16 +579,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor return importingNetwork != null && GetPluginFileName(importingNetwork).Contains(packageName); } - /// - /// Returns a URL friendly version string by replacing periods with underscores. - /// - private static string GetPluginVersionForUrl() - { - var version = MaxSdk.Version; - var versionsSplit = version.Split('.'); - return string.Join("_", versionsSplit); - } - /// /// Adds labels to assets so that they can be easily found. /// @@ -795,15 +771,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor return defaultValue; } - private static bool IsUnity2018_2OrNewer() - { -#if UNITY_2018_2_OR_NEWER - return true; -#else - return false; -#endif - } - private static string GetPluginFileName(Network network) { return network.Name.ToLowerInvariant() + "_" + network.LatestVersions.Unity + ".unitypackage"; diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta index b9938d2..e9e3603 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: da789f9f05f40451a9e20176746ee18d +guid: c5b874c1e65274159bcc0dc15d9458cc labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs index 59a3911..5c3f2d1 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs @@ -25,6 +25,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor private const string appLovinSdkKeyLink = "https://dash.applovin.com/o/account#keys"; private const string userTrackingUsageDescriptionDocsLink = "https://developer.apple.com/documentation/bundleresources/information_property_list/nsusertrackingusagedescription"; + private const string documentationTermsAndPrivacyPolicyFlow = "https://dash.applovin.com/documentation/mediation/ios/getting-started/terms-and-privacy-policy-flow"; private const string documentationAdaptersLink = "https://dash.applovin.com/documentation/mediation/unity/mediation-adapters"; private const string documentationNote = "Please ensure that integration instructions (e.g. permissions, ATS settings, etc) specific to each network are implemented as well. Click the link below for more info:"; private const string uninstallIconExportPath = "MaxSdk/Resources/Images/uninstall_icon.png"; @@ -33,8 +34,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor private const string qualityServiceRequiresGradleBuildErrorMsg = "AppLovin Quality Service integration via AppLovin Integration Manager requires Custom Gradle Template enabled or Unity 2018.2 or higher.\n" + "If you would like to continue using your existing setup, please add Quality Service Plugin to your build.gradle manually."; - + private readonly string[] termsFlowPlatforms = new string[3] {"Both", "Android", "iOS"}; + private readonly string[] debugUserGeographies = new string[2] {"Not Set", "GDPR"}; private Vector2 scrollPosition; private static readonly Vector2 windowMinSize = new Vector2(750, 750); @@ -146,10 +148,11 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor // Plugin downloaded and imported. Update current versions for the imported package. AppLovinIntegrationManager.importPackageCompletedCallback = OnImportPackageCompleted; - // Disable old consent flow if internal settings are enabled. - if (AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager) + // Disable old consent flow if new flow is enabled. + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) { AppLovinSettings.Instance.ConsentFlowEnabled = false; + AppLovinSettings.Instance.SaveAsync(); } Load(); @@ -190,6 +193,12 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor DrawPluginDetails(); + if (pluginData != null && pluginData.PartnerMicroSdks != null) + { + EditorGUILayout.LabelField("AppLovin Micro SDK Partners", titleLabelStyle); + DrawPartnerMicroSdks(); + } + // Draw mediated networks using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandHeight(false))) { @@ -313,10 +322,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor GUILayout.Space(5); } - -#if !UNITY_2018_2_OR_NEWER - EditorGUILayout.HelpBox("AppLovin MAX Unity plugin will soon require Unity 2018.2 or newer to function. Please upgrade to a newer Unity version.", MessageType.Warning); -#endif } GUILayout.Space(5); @@ -397,6 +402,29 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor GUILayout.EndHorizontal(); } + private void DrawPartnerMicroSdks() + { + if (pluginData == null) return; + + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + DrawHeaders("Network", true); + + var partnerMicroSdks = pluginData.PartnerMicroSdks; + foreach (var partnerMicroSdk in partnerMicroSdks) + { + DrawNetworkDetailRow(partnerMicroSdk); + } + + GUILayout.Space(10); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + /// /// Draws the network specific details for a given network. /// @@ -476,7 +504,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor var pluginRoot = AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; foreach (var pluginFilePath in network.PluginFilePaths) { - FileUtil.DeleteFileOrDirectory(Path.Combine(pluginRoot, pluginFilePath)); + var filePath = Path.Combine(pluginRoot, pluginFilePath); + FileUtil.DeleteFileOrDirectory(filePath); + FileUtil.DeleteFileOrDirectory(filePath + ".meta"); } AppLovinIntegrationManager.UpdateCurrentVersions(network, pluginRoot); @@ -626,14 +656,13 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor GUILayout.Space(10); using (new EditorGUILayout.VerticalScope("box")) { - var shouldDrawInternalSettings = AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager; - if (shouldDrawInternalSettings) + if (AppLovinSettings.Instance.ConsentFlowEnabled) { - DrawConsentFlowSettings(); + DrawTermsFlowSettings(); } else { - DrawTermsFlowSettings(); + DrawConsentFlowSettings(); } } @@ -643,6 +672,25 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor private void DrawTermsFlowSettings() { + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox("The Terms Flow has been deprecated; switch to the MAX Terms and Privacy Policy Flow instead.", MessageType.Warning); // TODO Refine + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Switch to MAX Terms and Privacy Policy Flow")) + { + AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl = AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl; + AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl = AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl; + AppLovinInternalSettings.Instance.ConsentFlowEnabled = true; + AppLovinSettings.Instance.ConsentFlowEnabled = false; + } + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + GUILayout.BeginHorizontal(); GUILayout.Space(4); AppLovinSettings.Instance.ConsentFlowEnabled = GUILayout.Toggle(AppLovinSettings.Instance.ConsentFlowEnabled, " Enable Terms Flow"); @@ -702,6 +750,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor Application.OpenURL(userTrackingUsageDescriptionDocsLink); } + GUILayout.Space(4); GUILayout.EndHorizontal(); GUILayout.Space(4); @@ -711,39 +760,36 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor { GUILayout.BeginHorizontal(); GUILayout.Space(4); - AppLovinInternalSettings.Instance.ConsentFlowEnabled = GUILayout.Toggle(AppLovinInternalSettings.Instance.ConsentFlowEnabled, " Enable Consent Flow"); + AppLovinInternalSettings.Instance.ConsentFlowEnabled = GUILayout.Toggle(AppLovinInternalSettings.Instance.ConsentFlowEnabled, " Enable MAX Terms and Privacy Policy Flow"); GUILayout.EndHorizontal(); + GUILayout.Space(6); GUILayout.Space(4); + EditorGUILayout.HelpBox("This flow automatically includes Google UMP.", MessageType.Info); + GUI.enabled = true; if (!AppLovinInternalSettings.Instance.ConsentFlowEnabled) return; + GUILayout.Space(6); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.LabelField("Click the link below to access the guide on creating the GDPR form within AdMob's dashboard."); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + if (GUILayout.Button(new GUIContent(documentationTermsAndPrivacyPolicyFlow), linkLabelStyle)) + { + Application.OpenURL(documentationTermsAndPrivacyPolicyFlow); + } + GUILayout.Space(4); + GUILayout.EndHorizontal(); + + GUILayout.Space(8); + AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl = DrawTextField("Privacy Policy URL", AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl = DrawTextField("Terms of Service URL (optional)", AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); - GUILayout.Space(4); - GUILayout.BeginHorizontal(); - GUILayout.Space(4); - AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAdvertisingPartnerUrls = GUILayout.Toggle(AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAdvertisingPartnerUrls, " Include Default Advertising Partner URLs"); - GUILayout.EndHorizontal(); - - GUILayout.Space(4); - GUILayout.BeginHorizontal(); - GUILayout.Space(4); - AppLovinInternalSettings.Instance.ConsentFlowAdvertisingPartnerUrls = DrawTextField("Advertising Partner URLs (CSV)", AppLovinInternalSettings.Instance.ConsentFlowAdvertisingPartnerUrls, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); - GUILayout.EndHorizontal(); - - GUILayout.Space(4); - GUILayout.BeginHorizontal(); - GUILayout.Space(4); - AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAnalyticsPartnerUrls = GUILayout.Toggle(AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAnalyticsPartnerUrls, " Include Default Analytics Partner URLs"); - GUILayout.EndHorizontal(); - - GUILayout.Space(4); - GUILayout.BeginHorizontal(); - GUILayout.Space(4); - AppLovinInternalSettings.Instance.ConsentFlowAnalyticsPartnerUrls = DrawTextField("Analytics Partner URLs (CSV)", AppLovinInternalSettings.Instance.ConsentFlowAnalyticsPartnerUrls, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); - GUILayout.EndHorizontal(); GUILayout.Space(4); GUILayout.BeginHorizontal(); GUILayout.Space(4); @@ -800,7 +846,21 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor GUILayout.Space(4); GUILayout.EndHorizontal(); + GUILayout.Space(8); + + GUILayout.BeginHorizontal(); GUILayout.Space(4); + EditorGUILayout.LabelField("Testing:", headerLabelStyle); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.LabelField("Debug User Geography"); + AppLovinInternalSettings.Instance.DebugUserGeography = (MaxSdkBase.ConsentFlowUserGeography) EditorGUILayout.Popup((int) AppLovinInternalSettings.Instance.DebugUserGeography, debugUserGeographies, privacySettingFieldWidthOption); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + + EditorGUILayout.HelpBox("Debug User Geography is only enabled in debug mode", MessageType.Info); } private void DrawOtherSettings() @@ -812,16 +872,12 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor GUILayout.Space(5); AppLovinSettings.Instance.SetAttributionReportEndpoint = DrawOtherSettingsToggle(AppLovinSettings.Instance.SetAttributionReportEndpoint, " Set Advertising Attribution Report Endpoint in Info.plist (iOS only)"); GUILayout.Space(5); + AppLovinSettings.Instance.AddApsSkAdNetworkIds = DrawOtherSettingsToggle(AppLovinSettings.Instance.AddApsSkAdNetworkIds, " Add Amazon Publisher Services SKAdNetworkID's"); + GUILayout.Space(5); var autoUpdateEnabled = DrawOtherSettingsToggle(EditorPrefs.GetBool(AppLovinAutoUpdater.KeyAutoUpdateEnabled, true), " Enable Auto Update"); EditorPrefs.SetBool(AppLovinAutoUpdater.KeyAutoUpdateEnabled, autoUpdateEnabled); GUILayout.Space(5); - var verboseLoggingEnabled = DrawOtherSettingsToggle(EditorPrefs.GetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, false), -#if UNITY_2018_2_OR_NEWER - " Enable Verbose Logging" -#else - " Enable Build Verbose Logging" -#endif - ); + var verboseLoggingEnabled = DrawOtherSettingsToggle(EditorPrefs.GetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, false), " Enable Verbose Logging"); EditorPrefs.SetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, verboseLoggingEnabled); GUILayout.Space(5); } diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta index 4163743..d7996fd 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2bb13a4fb97554d838321056d4d1f81b +guid: 84c61b4c05e114cec91df447d1b585f8 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs index 61962f3..41552d9 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs @@ -34,11 +34,8 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor [SerializeField] private bool consentFlowEnabled; [SerializeField] private string consentFlowPrivacyPolicyUrl = string.Empty; [SerializeField] private string consentFlowTermsOfServiceUrl = string.Empty; - [SerializeField] private string consentFlowAdvertisingPartnerUrls = string.Empty; - [SerializeField] private bool includeDefaultAdvertisingPartnerUrls = true; - [SerializeField] private string consentFlowAnalyticsPartnerUrls = string.Empty; - [SerializeField] private bool consentFlowIncludeDefaultAnalyticsPartnerUrls = true; [SerializeField] private bool overrideDefaultUserTrackingUsageDescriptions; + [SerializeField] private MaxSdkBase.ConsentFlowUserGeography debugUserGeography; [SerializeField] private string userTrackingUsageDescriptionEn = string.Empty; [SerializeField] private bool userTrackingUsageLocalizationEnabled; [SerializeField] private string userTrackingUsageDescriptionDe = string.Empty; @@ -121,8 +118,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor UserTrackingUsageDescriptionEn = string.Empty; UserTrackingUsageLocalizationEnabled = false; OverrideDefaultUserTrackingUsageDescriptions = false; - ConsentFlowIncludeDefaultAdvertisingPartnerUrls = true; - ConsentFlowIncludeDefaultAnalyticsPartnerUrls = true; } } } @@ -145,42 +140,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor set { consentFlowTermsOfServiceUrl = value; } } - /// - /// An array of advertising partner URLs. These URLs list are shown during the GDPR flow. - /// - public string ConsentFlowAdvertisingPartnerUrls - { - get { return consentFlowAdvertisingPartnerUrls; } - set { consentFlowAdvertisingPartnerUrls = value; } - } - - /// - /// Whether or not to include a default set of advertising partners. Defaults to true. - /// - public bool ConsentFlowIncludeDefaultAdvertisingPartnerUrls - { - get { return includeDefaultAdvertisingPartnerUrls; } - set { includeDefaultAdvertisingPartnerUrls = value; } - } - - /// - /// An array of analytics partner URLs. These URLs list are shown during the GDPR flow. - /// - public string ConsentFlowAnalyticsPartnerUrls - { - get { return consentFlowAnalyticsPartnerUrls; } - set { consentFlowAnalyticsPartnerUrls = value; } - } - - /// - /// Whether or not to include a default set of analytics partners. Defaults to true. - /// - public bool ConsentFlowIncludeDefaultAnalyticsPartnerUrls - { - get { return consentFlowIncludeDefaultAnalyticsPartnerUrls; } - set { consentFlowIncludeDefaultAnalyticsPartnerUrls = value; } - } - /// /// A User Tracking Usage Description in English to be shown to users when requesting permission to use data for tracking. /// For more information see Apple's documentation. @@ -191,6 +150,15 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor set { userTrackingUsageDescriptionEn = value; } } + /// + /// An optional string to set debug user geography + /// + public MaxSdkBase.ConsentFlowUserGeography DebugUserGeography + { + get { return debugUserGeography; } + set { debugUserGeography = value; } + } + public bool OverrideDefaultUserTrackingUsageDescriptions { get { return overrideDefaultUserTrackingUsageDescriptions; } diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta index 80da2bf..a863905 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 5a9f7c32d2d9e41e89f201dfc8770b13 +guid: 65c51e21887ae42c2839962fb9585e9f labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs index ad4b31c..5e094fd 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs @@ -6,7 +6,7 @@ // Copyright © 2019 AppLovin. All rights reserved. // -#if UNITY_2018_2_OR_NEWER && UNITY_ANDROID +#if UNITY_ANDROID using System.IO; using UnityEditor.Android; diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta index 25d8a71..c167f0c 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6af46e436a4b44671b5320be741172db +guid: f75e54e2eb78f427ca8643c97684387b labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs index 078ae4a..41c1561 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs @@ -49,11 +49,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor } // Download the ruby script needed to install Quality Service -#if UNITY_2017_2_OR_NEWER var downloadHandler = new DownloadHandlerFile(outputFilePath); -#else - var downloadHandler = new AppLovinDownloadHandler(path); -#endif var postJson = string.Format("{{\"sdk_key\" : \"{0}\"}}", sdkKey); var bodyRaw = Encoding.UTF8.GetBytes(postJson); var uploadHandler = new UploadHandlerRaw(bodyRaw); @@ -64,21 +60,15 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor unityWebRequest.method = UnityWebRequest.kHttpVerbPOST; unityWebRequest.downloadHandler = downloadHandler; unityWebRequest.uploadHandler = uploadHandler; -#if UNITY_2017_2_OR_NEWER var operation = unityWebRequest.SendWebRequest(); -#else - var operation = webRequest.Send(); -#endif // Wait for the download to complete or the request to timeout. while (!operation.isDone) { } #if UNITY_2020_1_OR_NEWER if (unityWebRequest.result != UnityWebRequest.Result.Success) -#elif UNITY_2017_2_OR_NEWER - if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) #else - if (webRequest.isError) + if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) #endif { MaxSdkLogger.UserError("AppLovin Quality Service installation failed. Failed to download script with error: " + unityWebRequest.error); diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta index 7166385..8182708 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: cc867a09c5aa14978b1cf1d2522961ce +guid: d5d209f90444f4a90830b48b5f3f3ff4 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs new file mode 100644 index 0000000..2b8500d --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs @@ -0,0 +1,105 @@ +// +// AppLovinPreProcess.cs +// AppLovin MAX Unity Plugin +// +// Created by Jonathan Liu on 10/19/2023. +// Copyright © 2023 AppLovin. All rights reserved. +// + +using System; +using System.Linq; +using System.Xml; +using System.Xml.Linq; +using UnityEngine; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public abstract class AppLovinPreProcess + { + private const string AppLovinDependenciesFileExportPath = "MaxSdk/AppLovin/Editor/Dependencies.xml"; + + private static readonly XmlWriterSettings DependenciesFileXmlWriterSettings = new XmlWriterSettings + { + Indent = true, + IndentChars = " ", + NewLineChars = "\n", + NewLineHandling = NewLineHandling.Replace + }; + + /// + /// Adds a string into AppLovin's Dependencies.xml file inside the containerElementString if it doesn't exist + /// + /// The line you want to add into the xml file + /// The root XML element under which to add the line. For example, to add a new dependency to Android, pass in "androidPackages" + protected static void TryAddStringToDependencyFile(string lineToAdd, string containerElementString) + { + try + { + var dependenciesFilePath = MaxSdkUtils.GetAssetPathForExportPath(AppLovinDependenciesFileExportPath); + var dependencies = XDocument.Load(dependenciesFilePath); + // Get the container where we are going to insert the line + var containerElement = dependencies.Descendants(containerElementString).FirstOrDefault(); + + if (containerElement == null) + { + Debug.LogError(containerElementString + " not found in Dependencies.xml file"); + return; + } + + var elementToAdd = XElement.Parse(lineToAdd); + + // Check if the xml file doesn't already contain the string. + if (containerElement.Elements().Any(element => XNode.DeepEquals(element, elementToAdd))) return; + + // Append the new element to the container element + containerElement.Add(elementToAdd); + + using (var xmlWriter = XmlWriter.Create(dependenciesFilePath, DependenciesFileXmlWriterSettings)) + { + dependencies.Save(xmlWriter); + } + } + catch (Exception exception) + { + Debug.LogError("Google CMP will not function. Unable to add string to dependency file due to exception: " + exception.Message); + } + } + + /// + /// Removes a string from AppLovin's Dependencies.xml file inside the containerElementString if it exists + /// + /// The line you want to remove from the xml file + /// The root XML element from which to remove the line. For example, to remove an Android dependency, pass in "androidPackages" + protected static void TryRemoveStringFromDependencyFile(string lineToRemove, string containerElementString) + { + try + { + var dependenciesFilePath = MaxSdkUtils.GetAssetPathForExportPath(AppLovinDependenciesFileExportPath); + var dependencies = XDocument.Load(dependenciesFilePath); + var containerElement = dependencies.Descendants(containerElementString).FirstOrDefault(); + + if (containerElement == null) + { + Debug.LogError(containerElementString + " not found in Dependencies.xml file"); + return; + } + + // Check if the dependency line exists. + var elementToFind = XElement.Parse(lineToRemove); + var existingElement = containerElement.Elements().FirstOrDefault(element => XNode.DeepEquals(element, elementToFind)); + if (existingElement == null) return; + + existingElement.Remove(); + + using (var xmlWriter = XmlWriter.Create(dependenciesFilePath, DependenciesFileXmlWriterSettings)) + { + dependencies.Save(xmlWriter); + } + } + catch (Exception exception) + { + Debug.LogError("Unable to remove string from dependency file due to exception: " + exception.Message); + } + } + } +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs.meta similarity index 81% rename from MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs.meta rename to MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs.meta index b6e7d3c..f5e00db 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs.meta @@ -1,8 +1,8 @@ fileFormatVersion: 2 -guid: 4ed678026df674e9d8df1cd02e2469e4 +guid: 0e6254f24e89548b3a7644fa7bf25f9d labels: - al_max -- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs index 366288b..2761fec 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs @@ -15,23 +15,16 @@ using System.IO; using AppLovinMax.ThirdParty.MiniJson; using UnityEditor; using UnityEditor.Build; -#if UNITY_2018_1_OR_NEWER using UnityEditor.Build.Reporting; using UnityEngine; -#endif namespace AppLovinMax.Scripts.IntegrationManager.Editor { /// /// Adds the AppLovin Quality Service plugin to the gradle template file. See for more details. /// - public class AppLovinPreProcessAndroid : AppLovinProcessGradleBuildFile, -#if UNITY_2018_1_OR_NEWER - IPreprocessBuildWithReport -#else - IPreprocessBuild -#endif + public class AppLovinPreProcessAndroid : AppLovinProcessGradleBuildFile, IPreprocessBuildWithReport { private const string AppLovinSettingsFileName = "applovin_settings.json"; @@ -44,16 +37,15 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor private const string KeyConsentFlowEnabled = "consent_flow_enabled"; private const string KeyConsentFlowTermsOfService = "consent_flow_terms_of_service"; private const string KeyConsentFlowPrivacyPolicy = "consent_flow_privacy_policy"; - private const string KeyConsentFlowAdvertisingPartners = "consent_flow_advertising_partners"; - private const string KeyConsentFlowIncludeDefaultAdvertisingPartners = "consent_flow_should_include_default_advertising_partners"; - private const string KeyConsentFlowAnalyticsPartners = "consent_flow_analytics_partners"; - private const string KeyConsentFlowIncludeDefaultAnalyticsPartners = "consent_flow_should_include_default_analytics_partners"; + private const string KeyConsentFlowDebugUserGeography = "consent_flow_debug_user_geography"; -#if UNITY_2018_1_OR_NEWER public void OnPreprocessBuild(BuildReport report) -#else - public void OnPreprocessBuild(BuildTarget target, string path) -#endif + { + PreprocessAppLovinQualityServicePlugin(); + AddGoogleCmpDependencyIfNeeded(); + } + + private static void PreprocessAppLovinQualityServicePlugin() { // We can only process gradle template file here. If it is not available, we will try again in post build on Unity IDEs newer than 2018_2 (see AppLovinPostProcessGradleProject). if (!AppLovinIntegrationManager.GradleTemplateEnabled) return; @@ -65,15 +57,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor #else AddAppLovinQualityServicePlugin(AppLovinIntegrationManager.GradleTemplatePath); #endif - - // For Unity 2018.2 or newer, the consent flow is enabled in MaxPostProcessBuildAndroid. -#if !UNITY_2018_2_OR_NEWER - if (AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager) - { - var consentFlowSettingsFilePath = Path.Combine("Assets", "Plugin/Android/res/raw/"); - EnableConsentFlowIfNeeded(consentFlowSettingsFilePath); - } -#endif } public static void EnableConsentFlowIfNeeded(string rawResourceDirectory) @@ -105,20 +88,10 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor consentFlowSettings[KeyConsentFlowTermsOfService] = termsOfServiceUrl; } - consentFlowSettings[KeyConsentFlowIncludeDefaultAdvertisingPartners] = AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAdvertisingPartnerUrls; - var advertisingPartnerUrls = AppLovinInternalSettings.Instance.ConsentFlowAdvertisingPartnerUrls; - if (MaxSdkUtils.IsValidString(advertisingPartnerUrls)) + var debugUserGeography = AppLovinInternalSettings.Instance.DebugUserGeography; + if (debugUserGeography == MaxSdkBase.ConsentFlowUserGeography.Gdpr) { - var advertisingPartnerUrlsList = advertisingPartnerUrls.Split(',').ToList(); - consentFlowSettings[KeyConsentFlowAdvertisingPartners] = advertisingPartnerUrlsList; - } - - consentFlowSettings[KeyConsentFlowIncludeDefaultAnalyticsPartners] = AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAnalyticsPartnerUrls; - var analyticsPartnerUrls = AppLovinInternalSettings.Instance.ConsentFlowAnalyticsPartnerUrls; - if (MaxSdkUtils.IsValidString(analyticsPartnerUrls)) - { - var analyticsPartnerUrlsList = analyticsPartnerUrls.Split(',').ToList(); - consentFlowSettings[KeyConsentFlowAnalyticsPartners] = analyticsPartnerUrlsList; + consentFlowSettings[KeyConsentFlowDebugUserGeography] = "gdpr"; } var applovinSdkSettings = new Dictionary(); @@ -130,7 +103,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor public static void EnableTermsFlowIfNeeded(string rawResourceDirectory) { - if (AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager) return; + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) return; // Check if terms flow is enabled for this format. No need to create the applovin_consent_flow_settings.json if consent flow is disabled. var consentFlowEnabled = AppLovinSettings.Instance.ConsentFlowEnabled; @@ -206,6 +179,21 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor } } + private static void AddGoogleCmpDependencyIfNeeded() + { + const string umpDependencyLine = ""; + const string containerElementString = "androidPackages"; + + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) + { + TryAddStringToDependencyFile(umpDependencyLine, containerElementString); + } + else + { + TryRemoveStringFromDependencyFile(umpDependencyLine, containerElementString); + } + } + public int callbackOrder { get { return int.MaxValue; } diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta index 1446db4..4dd79e8 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0e2f9480fec024b45bb33af29d3022d6 +guid: 8ccaf444d0d4f4cadb5debe7c41b20c4 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs new file mode 100644 index 0000000..dcffbc6 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs @@ -0,0 +1,45 @@ +// +// AppLovinBuildPreProcessiOS.cs +// AppLovin MAX Unity Plugin +// +// Created by Jonathan Liu on 10/17/2023. +// Copyright © 2023 AppLovin. All rights reserved. +// + +#if UNITY_IOS + +using UnityEditor.Build; +using UnityEditor.Build.Reporting; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public class AppLovinPreProcessiOS : AppLovinPreProcess, IPreprocessBuildWithReport + { + public void OnPreprocessBuild(BuildReport report) + { + AddGoogleCmpDependencyIfNeeded(); + } + + private static void AddGoogleCmpDependencyIfNeeded() + { + const string umpDependencyLine = ""; + const string containerElementString = "iosPods"; + + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) + { + TryAddStringToDependencyFile(umpDependencyLine, containerElementString); + } + else + { + TryRemoveStringFromDependencyFile(umpDependencyLine, containerElementString); + } + } + + public int callbackOrder + { + get { return int.MaxValue; } + } + } +} + +#endif diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs.meta new file mode 100644 index 0000000..33bdffb --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: ee45537a5833240d7afcfac4a38df1b9 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs index 1ad2a82..48b4d0e 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs @@ -29,7 +29,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor /// Adds or updates the AppLovin Quality Service plugin to the provided build.gradle file. /// If the gradle file already has the plugin, the API key is updated. /// - public abstract class AppLovinProcessGradleBuildFile + public abstract class AppLovinProcessGradleBuildFile : AppLovinPreProcess { private static readonly Regex TokenBuildScriptRepositories = new Regex(".*repositories.*"); private static readonly Regex TokenBuildScriptDependencies = new Regex(".*classpath \'com.android.tools.build:gradle.*"); @@ -63,7 +63,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor /// Updates the provided Gradle script to add Quality Service plugin. /// /// The gradle file to update. - protected void AddAppLovinQualityServicePlugin(string applicationGradleBuildFilePath) + protected static void AddAppLovinQualityServicePlugin(string applicationGradleBuildFilePath) { if (!AppLovinSettings.Instance.QualityServiceEnabled) return; @@ -297,21 +297,15 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor unityWebRequest.uploadHandler = uploadHandler; unityWebRequest.downloadHandler = new DownloadHandlerBuffer(); -#if UNITY_2017_2_OR_NEWER var operation = unityWebRequest.SendWebRequest(); -#else - var operation = webRequest.Send(); -#endif // Wait for the download to complete or the request to timeout. while (!operation.isDone) { } #if UNITY_2020_1_OR_NEWER if (unityWebRequest.result != UnityWebRequest.Result.Success) -#elif UNITY_2017_2_OR_NEWER - if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) #else - if (webRequest.isError) + if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) #endif { MaxSdkLogger.UserError("Failed to retrieve API Key for SDK Key: " + sdkKey + "with error: " + unityWebRequest.error); diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta index 3b9b19c..5e49844 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a25d66215002f4728b56848ff01f7424 +guid: 732b7510bc9c94aafb3fd3b8c0dc5d2d labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs index 94bc0d0..540cbe8 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs @@ -58,6 +58,7 @@ public class AppLovinSettings : ScriptableObject [SerializeField] private string sdkKey; [SerializeField] private bool setAttributionReportEndpoint; + [SerializeField] private bool addApsSkAdNetworkIds; [SerializeField] private bool consentFlowEnabled; [SerializeField] private Platform consentFlowPlatform; @@ -163,6 +164,15 @@ public class AppLovinSettings : ScriptableObject set { Instance.setAttributionReportEndpoint = value; } } + /// + /// Whether or not to add Amazon Publisher Services SKAdNetworkID's. + /// + public bool AddApsSkAdNetworkIds + { + get { return Instance.addApsSkAdNetworkIds; } + set { Instance.addApsSkAdNetworkIds = value; } + } + /// /// Whether or not AppLovin Consent Flow is enabled. /// diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta index 9c8ec08..7e40d73 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 589f0157fc8d1480a908eb38be2be8e6 +guid: ebc0ba1b5ef6b4a6b9dd53d7eadfea16 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef b/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef index 2737229..1cc80b7 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef +++ b/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef @@ -1,18 +1,10 @@ { "name": "MaxSdk.Scripts.IntegrationManager.Editor", - "rootNamespace": "", "references": [ "MaxSdk.Scripts" ], "includePlatforms": [ "Editor" ], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file + "excludePlatforms": [] +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta b/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta index a99dbb6..272b872 100644 --- a/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta +++ b/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0772632c471804ae89859df0956a3692 +guid: a10a05a8449c42519fd80f2b8b580de3 labels: - al_max - al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef diff --git a/MaxSdk/Scripts/MaxCmpService.cs b/MaxSdk/Scripts/MaxCmpService.cs new file mode 100644 index 0000000..c142439 --- /dev/null +++ b/MaxSdk/Scripts/MaxCmpService.cs @@ -0,0 +1,170 @@ +// +// MaxCmpService.cs +// AppLovin User Engagement Unity Plugin +// +// Created by Santosh Bagadi on 10/1/23. +// Copyright © 2023 AppLovin. All rights reserved. +// + +using System; +using System.Collections.Generic; + +#if UNITY_EDITOR +#elif UNITY_ANDROID +using UnityEngine; +#elif UNITY_IOS +using System.Runtime.InteropServices; +#endif + +/// +/// This class provides direct APIs for interfacing with the Google-certified CMP installed, if any. +/// +public class MaxCmpService +{ + private static readonly MaxCmpService _instance = new MaxCmpService(); + + private MaxCmpService() { } + + private static Action OnCompletedAction; + +#if UNITY_EDITOR +#elif UNITY_ANDROID + private static readonly AndroidJavaClass MaxUnityPluginClass = new AndroidJavaClass("com.applovin.mediation.unity.MaxUnityPlugin"); +#elif UNITY_IOS + [DllImport("__Internal")] + private static extern void _MaxShowCmpForExistingUser(); + + [DllImport("__Internal")] + private static extern bool _MaxHasSupportedCmp(); +#endif + + internal static MaxCmpService Instance + { + get { return _instance; } + } + + /// + /// Shows the CMP flow to an existing user. + /// Note that the user's current consent will be reset before the CMP alert is shown. + /// + /// Called when the CMP flow finishes showing. + public void ShowCmpForExistingUser(Action onCompletedAction) + { + OnCompletedAction = onCompletedAction; + +#if UNITY_EDITOR + var errorProps = new Dictionary + { + {"code", (int) MaxCmpError.ErrorCode.FormUnavailable}, + {"message", "CMP is not supported in Unity editor"} + }; + + NotifyCompletedIfNeeded(errorProps); +#elif UNITY_ANDROID + MaxUnityPluginClass.CallStatic("showCmpForExistingUser"); +#elif UNITY_IOS + _MaxShowCmpForExistingUser(); +#endif + } + + /// + /// Returns true if a supported CMP SDK is detected. + /// + public bool HasSupportedCmp + { + get + { +#if UNITY_EDITOR + return false; +#elif UNITY_ANDROID + return MaxUnityPluginClass.CallStatic("hasSupportedCmp"); +#elif UNITY_IOS + return _MaxHasSupportedCmp(); +#else + return false; +#endif + } + } + + internal static void NotifyCompletedIfNeeded(Dictionary errorProps) + { + if (OnCompletedAction == null) return; + + var error = (errorProps == null) ? null : MaxCmpError.Create(errorProps); + OnCompletedAction(error); + } +} + +public class MaxCmpError +{ + public enum ErrorCode + { + /// + /// Indicates that an unspecified error has occurred. + /// + Unspecified = -1, + + /// + /// Indicates that the CMP has not been integrated correctly. + /// + IntegrationError = 1, + + /// + /// Indicates that the CMP form is unavailable. + /// + FormUnavailable = 2, + + /// + /// Indicates that the CMP form is not required. + /// + FormNotRequired = 3 + } + + public static MaxCmpError Create(IDictionary error) + { + return new MaxCmpError() + { + Code = GetCode(MaxSdkUtils.GetIntFromDictionary(error, "code")), + Message = MaxSdkUtils.GetStringFromDictionary(error, "message"), + CmpCode = MaxSdkUtils.GetIntFromDictionary(error, "cmpCode", -1), + CmpMessage = MaxSdkUtils.GetStringFromDictionary(error, "cmpMessage") + }; + } + + private static ErrorCode GetCode(int code) + { + switch (code) + { + case 1: + return ErrorCode.IntegrationError; + case 2: + return ErrorCode.FormUnavailable; + case 3: + return ErrorCode.FormNotRequired; + default: + return ErrorCode.Unspecified; + } + } + + private MaxCmpError() { } + + /// + /// The error code for this error. + /// + public ErrorCode Code { get; private set; } + + /// + /// The error message for this error. + /// + public string Message { get; private set; } + + /// + /// The error code returned by the CMP. + /// + public int CmpCode { get; private set; } + + /// + /// The error message returned by the CMP. + /// + public string CmpMessage { get; private set; } +} diff --git a/MaxSdk/Scripts/MaxCmpService.cs.meta b/MaxSdk/Scripts/MaxCmpService.cs.meta new file mode 100644 index 0000000..598fc90 --- /dev/null +++ b/MaxSdk/Scripts/MaxCmpService.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: f2e895983b04846af81b59189de0310c +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxCmpService.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta b/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta index f75521a..12874b6 100644 --- a/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta +++ b/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 93afd2b1bb96f411d9e7bfa15fc9a0eb +guid: e0acf281ba86b4929a6942ecd998395b labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxEventSystemChecker.cs diff --git a/MaxSdk/Scripts/MaxEvents.cs.meta b/MaxSdk/Scripts/MaxEvents.cs.meta index 3a28e28..bfb6ad5 100644 --- a/MaxSdk/Scripts/MaxEvents.cs.meta +++ b/MaxSdk/Scripts/MaxEvents.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c13d7e9087ead447aa741d6d06aef9e1 +guid: 67ec2f620c6b0405ba16ea2c032dc9a2 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxEvents.cs diff --git a/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta b/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta index cf4cd69..b55da72 100644 --- a/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta +++ b/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b2529e5083a524b099f54b2bb80f05fc +guid: a4cfc1a18fa3a469b96d885db522f42e labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdk.Scripts.asmdef diff --git a/MaxSdk/Scripts/MaxSdk.cs b/MaxSdk/Scripts/MaxSdk.cs index 1ffcf2c..9d24ee3 100644 --- a/MaxSdk/Scripts/MaxSdk.cs +++ b/MaxSdk/Scripts/MaxSdk.cs @@ -18,7 +18,7 @@ public class MaxSdk : MaxSdkUnityEditor #endif { - private const string _version = "5.11.4"; + private const string _version = "6.1.2"; /// /// Returns the current plugin version. diff --git a/MaxSdk/Scripts/MaxSdk.cs.meta b/MaxSdk/Scripts/MaxSdk.cs.meta index 9f55566..c1c32f4 100644 --- a/MaxSdk/Scripts/MaxSdk.cs.meta +++ b/MaxSdk/Scripts/MaxSdk.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b9c276744a7284b6788f515c12cc403c +guid: 2fc7aa576843c44e68c7ab14b475bb82 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdk.cs diff --git a/MaxSdk/Scripts/MaxSdkAndroid.cs b/MaxSdk/Scripts/MaxSdkAndroid.cs index 47aecb1..0ed7612 100644 --- a/MaxSdk/Scripts/MaxSdkAndroid.cs +++ b/MaxSdk/Scripts/MaxSdkAndroid.cs @@ -13,11 +13,6 @@ public class MaxSdkAndroid : MaxSdkBase private static BackgroundCallbackProxy BackgroundCallback = new BackgroundCallbackProxy(); - public static MaxVariableServiceAndroid VariableService - { - get { return MaxVariableServiceAndroid.Instance; } - } - public static MaxUserServiceAndroid UserService { get { return MaxUserServiceAndroid.Instance; } @@ -415,17 +410,19 @@ public class MaxSdkAndroid : MaxSdkBase /// /// Ad unit identifier of the banner to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the extra parameter. Needs to be of type or null + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetBannerLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(AndroidJavaObject)) - { - MaxSdkLogger.E("Failed to set local extra parameter. Android local extra parameters need to be of type AndroidJavaObject"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set banner local extra parameter"); - MaxUnityPluginClass.CallStatic("setBannerLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setBannerLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setBannerLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } /// @@ -598,17 +595,19 @@ public class MaxSdkAndroid : MaxSdkBase /// /// Ad unit identifier of the MREC to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the extra parameter. Needs to be of type or null + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetMRecLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(AndroidJavaObject)) - { - MaxSdkLogger.E("Failed to set local extra parameter. Android local extra parameters need to be of type AndroidJavaObject"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC local extra parameter"); - MaxUnityPluginClass.CallStatic("setMRecLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setMRecLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setMRecLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } /// @@ -791,17 +790,19 @@ public class MaxSdkAndroid : MaxSdkBase /// /// Ad unit identifier of the interstitial to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the extra parameter. Needs to be of type or null + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetInterstitialLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(AndroidJavaObject)) - { - MaxSdkLogger.E("Failed to set local extra parameter. Android local extra parameters need to be of type AndroidJavaObject"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set interstitial local extra parameter"); - MaxUnityPluginClass.CallStatic("setInterstitialLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setInterstitialLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setInterstitialLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } #endregion @@ -866,17 +867,19 @@ public class MaxSdkAndroid : MaxSdkBase /// /// Ad unit identifier of the app open ad to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the extra parameter. Needs to be of type or null + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetAppOpenAdLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(AndroidJavaObject)) - { - MaxSdkLogger.E("Failed to set local extra parameter. Android local extra parameters need to be of type AndroidJavaObject"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set app open ad local extra parameter"); - MaxUnityPluginClass.CallStatic("setAppOpenAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setAppOpenAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setAppOpenAdLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } #endregion @@ -941,17 +944,19 @@ public class MaxSdkAndroid : MaxSdkBase /// /// Ad unit identifier of the rewarded to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the extra parameter. Needs to be of type or null + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetRewardedAdLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(AndroidJavaObject)) - { - MaxSdkLogger.E("Failed to set local extra parameter. Android local extra parameters need to be of type AndroidJavaObject"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded ad local extra parameter"); - MaxUnityPluginClass.CallStatic("setRewardedAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setRewardedAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setRewardedAdLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } #endregion @@ -1016,17 +1021,19 @@ public class MaxSdkAndroid : MaxSdkBase /// /// Ad unit identifier of the rewarded interstitial to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the extra parameter. Needs to be of type or null + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetRewardedInterstitialAdLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(AndroidJavaObject)) - { - MaxSdkLogger.E("Failed to set local extra parameter. Android local extra parameters need to be of type AndroidJavaObject"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded interstitial ad local extra parameter"); - MaxUnityPluginClass.CallStatic("setRewardedInterstitialAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setRewardedInterstitialAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setRewardedInterstitialAdLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } #endregion diff --git a/MaxSdk/Scripts/MaxSdkAndroid.cs.meta b/MaxSdk/Scripts/MaxSdkAndroid.cs.meta index c5cacde..2cf5448 100644 --- a/MaxSdk/Scripts/MaxSdkAndroid.cs.meta +++ b/MaxSdk/Scripts/MaxSdkAndroid.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e64643507f25d48268e8df04710b9dec +guid: 10335fad6bfef47b8819a411aa591dc8 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdkAndroid.cs diff --git a/MaxSdk/Scripts/MaxSdkBase.cs b/MaxSdk/Scripts/MaxSdkBase.cs index 539e4cf..dfe1228 100644 --- a/MaxSdk/Scripts/MaxSdkBase.cs +++ b/MaxSdk/Scripts/MaxSdkBase.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -16,6 +17,26 @@ public abstract class MaxSdkBase protected static readonly MaxUserSegment SharedUserSegment = new MaxUserSegment(); protected static readonly MaxTargetingData SharedTargetingData = new MaxTargetingData(); + /// + /// This enum represents the user's geography used to determine the type of consent flow shown to the user. + /// + public enum ConsentFlowUserGeography + { + /// + /// User's geography is unknown. + /// + Unknown, + + /// + /// The user is in GDPR region. + /// + Gdpr, + + /// + /// The user is in a non-GDPR region. + /// + Other + } #if UNITY_EDITOR || UNITY_IPHONE || UNITY_IOS /// @@ -97,6 +118,12 @@ public abstract class MaxSdkBase public bool IsTestModeEnabled { get; private set; } + /// + /// Get the user's geography used to determine the type of consent flow shown to the user. + /// If no such determination could be made, will be returned. + /// + public ConsentFlowUserGeography ConsentFlowUserGeography { get; private set; } + [Obsolete("This API has been deprecated and will be removed in a future release.")] public ConsentDialogState ConsentDialogState { get; private set; } @@ -127,6 +154,21 @@ public abstract class MaxSdkBase sdkConfiguration.CountryCode = MaxSdkUtils.GetStringFromDictionary(eventProps, "countryCode", ""); sdkConfiguration.IsTestModeEnabled = MaxSdkUtils.GetBoolFromDictionary(eventProps, "isTestModeEnabled"); + var consentFlowUserGeographyStr = MaxSdkUtils.GetStringFromDictionary(eventProps, "consentFlowUserGeography", ""); + if ("1".Equals(consentFlowUserGeographyStr)) + { + sdkConfiguration.ConsentFlowUserGeography = ConsentFlowUserGeography.Gdpr; + } + else if ("2".Equals(consentFlowUserGeographyStr)) + { + sdkConfiguration.ConsentFlowUserGeography = ConsentFlowUserGeography.Other; + } + else + { + sdkConfiguration.ConsentFlowUserGeography = ConsentFlowUserGeography.Unknown; + } + + #pragma warning disable 0618 var consentDialogStateStr = MaxSdkUtils.GetStringFromDictionary(eventProps, "consentDialogState", ""); if ("1".Equals(consentDialogStateStr)) @@ -453,6 +495,14 @@ public abstract class MaxSdkBase } } + /// + /// The CMP service, which provides direct APIs for interfacing with the Google-certified CMP installed, if any. + /// + public static MaxCmpService CmpService + { + get { return MaxCmpService.Instance; } + } + protected static void ValidateAdUnitIdentifier(string adUnitIdentifier, string debugPurpose) { if (string.IsNullOrEmpty(adUnitIdentifier)) @@ -525,6 +575,22 @@ public abstract class MaxSdkBase } } + protected static string SerializeLocalExtraParameterValue(object value) + { + if (!(value.GetType().IsPrimitive || value is string || value is IList || value is IDictionary)) + { + MaxSdkLogger.UserError("Local extra parameters must be an IList, IDictionary, string, or a primitive type"); + return ""; + } + + Dictionary data = new Dictionary + { + {"value", value} + }; + + return Json.Serialize(data); + } + [Obsolete("This API has been deprecated and will be removed in a future release.")] public enum ConsentDialogState { @@ -622,44 +688,15 @@ internal static class AdPositionExtenstion namespace AppLovinMax.Internal.API { + [Obsolete("This class has been deprecated and will be removed in a future SDK release.")] public class CFError { - /// - /// Indicates that the flow ended in an unexpected state. - /// - public const int ErrorCodeUnspecified = -1; - - /// - /// Indicates that the consent flow has not been integrated correctly. - /// - public const int ErrorCodeInvalidIntegration = -100; - - /// - /// Indicates that the consent flow is already being shown. - /// - public const int ErrorCodeFlowAlreadyInProgress = -200; - - /// - /// Indicates that the user is not in a GDPR region. - /// - public const int ErrorCodeNotInGdprRegion = -300; - - /// - /// The error code for this error. Will be one of the error codes listed in this file. - /// public int Code { get; private set; } - /// - /// The error message for this error. - /// public string Message { get; private set; } - public static CFError Create(IDictionary errorObject) + public static CFError Create(int code = -1, string message = "") { - if (!errorObject.ContainsKey("code") && !errorObject.ContainsKey("message")) return null; - - var code = MaxSdkUtils.GetIntFromDictionary(errorObject, "code", ErrorCodeUnspecified); - var message = MaxSdkUtils.GetStringFromDictionary(errorObject, "message"); return new CFError(code, message); } @@ -676,97 +713,45 @@ namespace AppLovinMax.Internal.API } } + [Obsolete("This enum has been deprecated. Please use `MaxSdk.GetSdkConfiguration().ConsentFlowUserGeography` instead.")] public enum CFType { - /// - /// The flow type is not known. - /// Unknown, - - /// - /// A standard flow where a TOS/PP alert is shown. - /// Standard, - - /// - /// A detailed modal shown to users in GDPR region. - /// Detailed } public class CFService { - private static Action OnConsentFlowCompletedAction; - -#if UNITY_EDITOR -#elif UNITY_ANDROID - private static readonly AndroidJavaClass MaxUnityPluginClass = new AndroidJavaClass("com.applovin.mediation.unity.MaxUnityPlugin"); -#elif UNITY_IOS - [DllImport("__Internal")] - private static extern string _MaxGetCFType(); - - [DllImport("__Internal")] - private static extern void _MaxStartConsentFlow(); -#endif - - /// - /// The consent flow type that will be displayed. - /// + [Obsolete("This property has been deprecated. Please use `MaxSdk.GetSdkConfiguration().ConsentFlowUserGeography` instead.")] public static CFType CFType { get { - var cfType = "0"; -#if UNITY_EDITOR -#elif UNITY_ANDROID - cfType = MaxUnityPluginClass.CallStatic("getCFType"); -#elif UNITY_IOS - cfType = _MaxGetCFType(); -#endif - - if ("1".Equals(cfType)) + switch (MaxSdk.GetSdkConfiguration().ConsentFlowUserGeography) { - return CFType.Standard; + case MaxSdkBase.ConsentFlowUserGeography.Unknown: + return CFType.Unknown; + case MaxSdkBase.ConsentFlowUserGeography.Gdpr: + return CFType.Detailed; + case MaxSdkBase.ConsentFlowUserGeography.Other: + return CFType.Standard; + default: + throw new ArgumentOutOfRangeException(); } - else if ("2".Equals(cfType)) - { - return CFType.Detailed; - } - - return CFType.Unknown; } } - /// - /// Starts the consent flow. Call this method to re-show the consent flow for a user in GDPR region. - /// - /// Note: The flow will only be shown to users in GDPR regions. - /// - /// Called when we finish showing the consent flow. Error object will be null if the flow completed successfully. + [Obsolete("This method has been deprecated. Please use `MaxSdk.CmpService.ShowCmpForExistingUser` instead.")] public static void SCF(Action onFlowCompletedAction) { - OnConsentFlowCompletedAction = onFlowCompletedAction; - -#if UNITY_EDITOR - var errorDict = new Dictionary() + MaxSdkBase.CmpService.ShowCmpForExistingUser(error => { - {"code", CFError.ErrorCodeUnspecified}, - {"message", "Consent flow is not supported in Unity Editor."} - }; + if (onFlowCompletedAction == null) return; - NotifyConsentFlowCompletedIfNeeded(errorDict); -#elif UNITY_ANDROID - MaxUnityPluginClass.CallStatic("startConsentFlow"); -#elif UNITY_IOS - _MaxStartConsentFlow(); -#endif - } - - public static void NotifyConsentFlowCompletedIfNeeded(IDictionary error) - { - if (OnConsentFlowCompletedAction == null) return; - - OnConsentFlowCompletedAction(CFError.Create(error)); + var cfError = error == null ? null : CFError.Create((int) error.Code, error.Message); + onFlowCompletedAction(cfError); + }); } } } diff --git a/MaxSdk/Scripts/MaxSdkBase.cs.meta b/MaxSdk/Scripts/MaxSdkBase.cs.meta index 5874250..f27f769 100644 --- a/MaxSdk/Scripts/MaxSdkBase.cs.meta +++ b/MaxSdk/Scripts/MaxSdkBase.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0822c80ecfc5248e2b853d8d5b449fb3 +guid: 893e4e55a7e394274957f1034f7afc45 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdkBase.cs diff --git a/MaxSdk/Scripts/MaxSdkCallbacks.cs b/MaxSdk/Scripts/MaxSdkCallbacks.cs index d4ade54..bf3084f 100644 --- a/MaxSdk/Scripts/MaxSdkCallbacks.cs +++ b/MaxSdk/Scripts/MaxSdkCallbacks.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Globalization; using UnityEngine; -using AppLovinMax.Internal.API; using AppLovinMax.ThirdParty.MiniJson; public class MaxSdkCallbacks : MonoBehaviour @@ -48,23 +47,6 @@ public class MaxSdkCallbacks : MonoBehaviour } } - // Fire when the MaxVariableService has finished loading the latest set of variables. - private static Action _onVariablesUpdatedEvent; - [System.Obsolete("This API has been deprecated. Please use our SDK's initialization callback to retrieve variables instead.")] - public static event Action OnVariablesUpdatedEvent - { - add - { - LogSubscribedToEvent("OnVariablesUpdatedEvent"); - _onVariablesUpdatedEvent += value; - } - remove - { - LogUnsubscribedToEvent("OnVariablesUpdatedEvent"); - _onVariablesUpdatedEvent -= value; - } - } - // Fire when the Consent Dialog has been dismissed. private static Action _onSdkConsentDialogDismissedEvent; public static event Action OnSdkConsentDialogDismissedEvent @@ -1360,17 +1342,14 @@ public class MaxSdkCallbacks : MonoBehaviour var sdkConfiguration = MaxSdkBase.SdkConfiguration.Create(eventProps); InvokeEvent(_onSdkInitializedEvent, sdkConfiguration, eventName); } - else if (eventName == "OnVariablesUpdatedEvent") - { - InvokeEvent(_onVariablesUpdatedEvent, eventName); - } else if (eventName == "OnSdkConsentDialogDismissedEvent") { InvokeEvent(_onSdkConsentDialogDismissedEvent, eventName); } - else if (eventName == "OnSdkConsentFlowCompletedEvent") + else if (eventName == "OnCmpCompletedEvent") { - CFService.NotifyConsentFlowCompletedIfNeeded(eventProps); + var errorProps = MaxSdkUtils.GetDictionaryFromDictionary(eventProps, "error"); + MaxCmpService.NotifyCompletedIfNeeded(errorProps); } // Ad Events else @@ -1734,7 +1713,6 @@ public class MaxSdkCallbacks : MonoBehaviour private static void ResetOnDomainReload() { _onSdkInitializedEvent = null; - _onVariablesUpdatedEvent = null; _onSdkConsentDialogDismissedEvent = null; _onInterstitialAdLoadedEventV2 = null; diff --git a/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta b/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta index c383446..dd08049 100644 --- a/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta +++ b/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1bc9fb13147694ac795ea28866c87af9 +guid: 4dc129a60049645f7a492a0a658a6c22 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdkCallbacks.cs diff --git a/MaxSdk/Scripts/MaxSdkLogger.cs.meta b/MaxSdk/Scripts/MaxSdkLogger.cs.meta index 1f09051..01a3427 100644 --- a/MaxSdk/Scripts/MaxSdkLogger.cs.meta +++ b/MaxSdk/Scripts/MaxSdkLogger.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 54635e7165bf2486a9cc1da416db8ae6 +guid: ff2b160afdfd4a74b731954323772a90 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdkLogger.cs diff --git a/MaxSdk/Scripts/MaxSdkUnityEditor.cs b/MaxSdk/Scripts/MaxSdkUnityEditor.cs index 8aa8a53..61c93b1 100644 --- a/MaxSdk/Scripts/MaxSdkUnityEditor.cs +++ b/MaxSdk/Scripts/MaxSdkUnityEditor.cs @@ -32,11 +32,6 @@ public class MaxSdkUnityEditor : MaxSdkBase private static readonly HashSet ReadyAdUnits = new HashSet(); private static readonly Dictionary StubBanners = new Dictionary(); - public static MaxVariableServiceUnityEditor VariableService - { - get { return MaxVariableServiceUnityEditor.Instance; } - } - public static MaxUserServiceUnityEditor UserService { get { return MaxUserServiceUnityEditor.Instance; } diff --git a/MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta b/MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta index 932a5ac..145875b 100644 --- a/MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta +++ b/MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c8c53ddc186d74166a4a1381519cbb2c +guid: 13b3e537a64f24986bb8ffe3a0beef5c labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdkUnityEditor.cs diff --git a/MaxSdk/Scripts/MaxSdkUtils.cs b/MaxSdk/Scripts/MaxSdkUtils.cs index c24f081..063106d 100644 --- a/MaxSdk/Scripts/MaxSdkUtils.cs +++ b/MaxSdk/Scripts/MaxSdkUtils.cs @@ -12,7 +12,7 @@ using UnityEditor; #endif -public partial class MaxSdkUtils +public class MaxSdkUtils { /// /// An Enum to be used when comparing two versions. @@ -349,6 +349,83 @@ public partial class MaxSdkUtils #endif } + /// + /// Parses the IAB TCF String to determine the consent status for the IAB vendor with the provided ID. + /// + /// Vendor ID as defined in the Global Vendor List. + /// The consent status of the IAB vendor. Returns true if the vendor has consent, false if not, or null if no TCF string is available on disk. + /// Current Version of Global Vendor List + public static bool? GetTcfConsentStatus(int vendorId) + { + var tcfConsentStatus = GetPlatformSpecificTcfConsentStatus(vendorId); + if (tcfConsentStatus == -1) + { + return null; + } + else + { + return tcfConsentStatus == 1; + } + } + +#if UNITY_IOS + [DllImport("__Internal")] + private static extern int _MaxGetTcfConsentStatus(int vendorIdentifier); +#endif + + private static int GetPlatformSpecificTcfConsentStatus(int vendorId) + { +#if UNITY_EDITOR + return -1; +#elif UNITY_IOS + return _MaxGetTcfConsentStatus(vendorId); +#elif UNITY_ANDROID + return MaxUnityPluginClass.CallStatic("getTcfConsentStatus", vendorId); +#else + return -1; +#endif + } + + /// + /// Parses the Google UMP's Additional Consent (AC) string to determine the consent status for the advertising entity represented by the provided Ad Technology Provider (ATP) ID. + /// + /// The ID representing the advertising entity (e.g. 89 for Meta Audience Network). + /// + /// The consent status of the advertising entity. Returns true if the entity has consent, false if not, or null if no AC string is available on disk. + /// + /// Google’s Additional Consent Mode technical specification + /// List of Google ATPs and their IDs + public static bool? GetAdditionalConsentStatus(int atpId) + { + var additionalConsentStatus = GetPlatformSpecificAdditionalConsentStatus(atpId); + if (additionalConsentStatus == -1) + { + return null; + } + else + { + return additionalConsentStatus == 1; + } + } + +#if UNITY_IOS + [DllImport("__Internal")] + private static extern int _MaxGetAdditionalConsentStatus(int atpIdentifier); +#endif + + private static int GetPlatformSpecificAdditionalConsentStatus(int atpId) + { +#if UNITY_EDITOR + return -1; +#elif UNITY_IOS + return _MaxGetAdditionalConsentStatus(atpId); +#elif UNITY_ANDROID + return MaxUnityPluginClass.CallStatic("getAdditionalConsentStatus", atpId); +#else + return -1; +#endif + } + /// /// Compares AppLovin MAX Unity mediation adapter plugin versions. Returns , , /// or as the first version is less than, equal to, or greater than the second. @@ -521,8 +598,4 @@ public partial class MaxSdkUtils return assetGuids.Length < 1 ? defaultPath : AssetDatabase.GUIDToAssetPath(assetGuids[0]); } #endif - - - - } diff --git a/MaxSdk/Scripts/MaxSdkUtils.cs.meta b/MaxSdk/Scripts/MaxSdkUtils.cs.meta index 21bbc33..a1b67cf 100644 --- a/MaxSdk/Scripts/MaxSdkUtils.cs.meta +++ b/MaxSdk/Scripts/MaxSdkUtils.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 5b1f7446ccb2846569bdf5db9ef4d548 +guid: 47f1bc9a8eebd4d088e22e6baf00ede3 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdkUtils.cs diff --git a/MaxSdk/Scripts/MaxSdkiOS.cs b/MaxSdk/Scripts/MaxSdkiOS.cs index 7a46c11..4254776 100644 --- a/MaxSdk/Scripts/MaxSdkiOS.cs +++ b/MaxSdk/Scripts/MaxSdkiOS.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using AOT; @@ -18,11 +19,6 @@ public class MaxSdkiOS : MaxSdkBase } #if UNITY_IOS - public static MaxVariableServiceiOS VariableService - { - get { return MaxVariableServiceiOS.Instance; } - } - public static MaxUserServiceiOS UserService { get { return MaxUserServiceiOS.Instance; } @@ -507,24 +503,28 @@ public class MaxSdkiOS : MaxSdkBase [DllImport("__Internal")] private static extern void _MaxSetBannerLocalExtraParameter(string adUnitIdentifier, string key, IntPtr value); + [DllImport("__Internal")] + private static extern void _MaxSetBannerLocalExtraParameterJSON(string adUnitIdentifier, string key, string json); + /// /// Set a local extra parameter for the banner ad. /// /// Ad unit identifier of the banner to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the local extra parameter. Needs to be of type or null + /// The value for the local extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetBannerLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(IntPtr)) - { - MaxSdkLogger.E("Failed to set local extra parameter. iOS local extra parameters need to be of type IntPtr"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set banner local extra parameter"); - var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; - _MaxSetBannerLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + if (value == null || value is IntPtr) + { + var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; + _MaxSetBannerLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + } + else + { + _MaxSetBannerLocalExtraParameterJSON(adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } [DllImport("__Internal")] @@ -737,24 +737,28 @@ public class MaxSdkiOS : MaxSdkBase [DllImport("__Internal")] private static extern void _MaxSetMRecLocalExtraParameter(string adUnitIdentifier, string key, IntPtr value); + [DllImport("__Internal")] + private static extern void _MaxSetMRecLocalExtraParameterJSON(string adUnitIdentifier, string key, string json); + /// /// Set a local extra parameter for the MREC ad. /// /// Ad unit identifier of the MREC to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the local extra parameter. Needs to be of type or null + /// The value for the local extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetMRecLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(IntPtr)) - { - MaxSdkLogger.E("Failed to set local extra parameter. iOS local extra parameters need to be of type IntPtr"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC local extra parameter"); - var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; - _MaxSetMRecLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + if (value == null || value is IntPtr) + { + var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; + _MaxSetMRecLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + } + else + { + _MaxSetMRecLocalExtraParameterJSON(adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } [DllImport("__Internal")] @@ -974,24 +978,28 @@ public class MaxSdkiOS : MaxSdkBase [DllImport("__Internal")] private static extern void _MaxSetInterstitialLocalExtraParameter(string adUnitIdentifier, string key, IntPtr value); + [DllImport("__Internal")] + private static extern void _MaxSetInterstitialLocalExtraParameterJSON(string adUnitIdentifier, string key, string json); + /// /// Set a local extra parameter for the ad. /// /// Ad unit identifier of the interstitial to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the local extra parameter. Needs to be of type or null + /// The value for the local extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetInterstitialLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(IntPtr)) - { - MaxSdkLogger.E("Failed to set local extra parameter. iOS local extra parameters need to be of type IntPtr"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set interstitial local extra parameter"); - var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; - _MaxSetInterstitialLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + if (value == null || value is IntPtr) + { + var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; + _MaxSetInterstitialLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + } + else + { + _MaxSetInterstitialLocalExtraParameterJSON(adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } #endregion @@ -1066,24 +1074,28 @@ public class MaxSdkiOS : MaxSdkBase [DllImport("__Internal")] private static extern void _MaxSetAppOpenAdLocalExtraParameter(string adUnitIdentifier, string key, IntPtr value); + [DllImport("__Internal")] + private static extern void _MaxSetAppOpenAdLocalExtraParameterJSON(string adUnitIdentifier, string key, string json); + /// /// Set a local extra parameter for the ad. /// /// Ad unit identifier of the app open ad to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the local extra parameter. Needs to be of type or null + /// The value for the local extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetAppOpenAdLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(IntPtr)) - { - MaxSdkLogger.E("Failed to set local extra parameter. iOS local extra parameters need to be of type IntPtr"); - return; - } - ValidateAdUnitIdentifier(adUnitIdentifier, "set app open ad local extra parameter"); - var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; - _MaxSetAppOpenAdLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + if (value == null || value is IntPtr) + { + var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; + _MaxSetAppOpenAdLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + } + else + { + _MaxSetAppOpenAdLocalExtraParameterJSON(adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } } #endregion @@ -1158,24 +1170,28 @@ public class MaxSdkiOS : MaxSdkBase [DllImport("__Internal")] private static extern void _MaxSetRewardedAdLocalExtraParameter(string adUnitIdentifier, string key, IntPtr value); + [DllImport("__Internal")] + private static extern void _MaxSetRewardedAdLocalExtraParameterJSON(string adUnitIdentifier, string key, string json); + /// /// Set a local extra parameter for the ad. /// /// Ad unit identifier of the rewarded ad to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for local the extra parameter. Needs to be of type or null + /// The value for the local extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetRewardedAdLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(IntPtr)) + ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded ad local extra parameter"); + + if (value == null || value is IntPtr) { - MaxSdkLogger.E("Failed to set local extra parameter. iOS local extra parameters need to be of type IntPtr"); - return; + var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; + _MaxSetRewardedAdLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + } + else + { + _MaxSetRewardedAdLocalExtraParameterJSON(adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); } - - ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded local extra parameter"); - - var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; - _MaxSetRewardedAdLocalExtraParameter(adUnitIdentifier, key, intPtrValue); } #endregion @@ -1250,24 +1266,28 @@ public class MaxSdkiOS : MaxSdkBase [DllImport("__Internal")] private static extern void _MaxSetRewardedInterstitialAdLocalExtraParameter(string adUnitIdentifier, string key, IntPtr value); + [DllImport("__Internal")] + private static extern void _MaxSetRewardedInterstitialAdLocalExtraParameterJSON(string adUnitIdentifier, string key, string json); + /// /// Set a local extra parameter for the ad. /// /// Ad unit identifier of the rewarded interstitial ad to set the local extra parameter for. /// The key for the local extra parameter. - /// The value for the local extra parameter. Needs to be of type or null + /// The value for the local extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types public static void SetRewardedInterstitialAdLocalExtraParameter(string adUnitIdentifier, string key, object value) { - if (value != null && value.GetType() != typeof(IntPtr)) + ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded interstitial ad local extra parameter"); + + if (value == null || value is IntPtr) { - MaxSdkLogger.E("Failed to set local extra parameter. iOS local extra parameters need to be of type IntPtr"); - return; + var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; + _MaxSetRewardedInterstitialAdLocalExtraParameter(adUnitIdentifier, key, intPtrValue); + } + else + { + _MaxSetRewardedInterstitialAdLocalExtraParameterJSON(adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); } - - ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded interstitial local extra parameter"); - - var intPtrValue = value == null ? IntPtr.Zero : (IntPtr) value; - _MaxSetRewardedInterstitialAdLocalExtraParameter(adUnitIdentifier, key, intPtrValue); } #endregion diff --git a/MaxSdk/Scripts/MaxSdkiOS.cs.meta b/MaxSdk/Scripts/MaxSdkiOS.cs.meta index 977d50d..9adec1b 100644 --- a/MaxSdk/Scripts/MaxSdkiOS.cs.meta +++ b/MaxSdk/Scripts/MaxSdkiOS.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1c0c0863c6b44422ba7dbf7939009f74 +guid: e7c7ed6cdbdca44cd8eae28d3b60d28c labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxSdkiOS.cs diff --git a/MaxSdk/Scripts/MaxTargetingData.cs.meta b/MaxSdk/Scripts/MaxTargetingData.cs.meta index a10f79a..35e7771 100644 --- a/MaxSdk/Scripts/MaxTargetingData.cs.meta +++ b/MaxSdk/Scripts/MaxTargetingData.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: eac21c202a5f94a2f8e6683afa591d7b +guid: 409fe14211f31433da09f5b4bd5467b9 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxTargetingData.cs diff --git a/MaxSdk/Scripts/MaxUserSegment.cs.meta b/MaxSdk/Scripts/MaxUserSegment.cs.meta index 9d8df97..9c1916a 100644 --- a/MaxSdk/Scripts/MaxUserSegment.cs.meta +++ b/MaxSdk/Scripts/MaxUserSegment.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e2f0d7f5729cd4f46a8498cdeb6a70e7 +guid: 8fb1f6f31b19c407b9d3fa62557d373a labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxUserSegment.cs diff --git a/MaxSdk/Scripts/MaxUserServiceAndroid.cs.meta b/MaxSdk/Scripts/MaxUserServiceAndroid.cs.meta index bb05c50..5457a76 100644 --- a/MaxSdk/Scripts/MaxUserServiceAndroid.cs.meta +++ b/MaxSdk/Scripts/MaxUserServiceAndroid.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6cc873cf061ec4b29be81d16f52762d9 +guid: d2eacd6aa14494de6809b4b06027a332 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxUserServiceAndroid.cs diff --git a/MaxSdk/Scripts/MaxUserServiceUnityEditor.cs.meta b/MaxSdk/Scripts/MaxUserServiceUnityEditor.cs.meta index 587807d..4e6640c 100644 --- a/MaxSdk/Scripts/MaxUserServiceUnityEditor.cs.meta +++ b/MaxSdk/Scripts/MaxUserServiceUnityEditor.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e3754fa2823844ae19be8cf9775fefb4 +guid: 16d44e29e68204f36975abec0feb1d35 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxUserServiceUnityEditor.cs diff --git a/MaxSdk/Scripts/MaxUserServiceiOS.cs.meta b/MaxSdk/Scripts/MaxUserServiceiOS.cs.meta index d70cda4..0220cdc 100644 --- a/MaxSdk/Scripts/MaxUserServiceiOS.cs.meta +++ b/MaxSdk/Scripts/MaxUserServiceiOS.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 25fbc36c2e04d4127bb60c436fa54315 +guid: 6233dd3f0b4664e7dbdca14cc8904176 labels: - al_max - al_max_export_path-MaxSdk/Scripts/MaxUserServiceiOS.cs diff --git a/MaxSdk/Scripts/MaxVariableServiceAndroid.cs b/MaxSdk/Scripts/MaxVariableServiceAndroid.cs deleted file mode 100644 index ee8651a..0000000 --- a/MaxSdk/Scripts/MaxVariableServiceAndroid.cs +++ /dev/null @@ -1,36 +0,0 @@ -using UnityEngine; - -public class MaxVariableServiceAndroid -{ - private static readonly AndroidJavaClass _maxUnityPluginClass = new AndroidJavaClass("com.applovin.mediation.unity.MaxUnityPlugin"); - private static readonly MaxVariableServiceAndroid _instance = new MaxVariableServiceAndroid(); - - public static MaxVariableServiceAndroid Instance - { - get { return _instance; } - } - - /// - /// Returns the variable value associated with the given key, or false if no mapping of the desired type exists for the given key. - /// - /// The variable name to retrieve the value for. - public bool GetBoolean(string key, bool defaultValue = false) - { - return _maxUnityPluginClass.CallStatic("getBoolean", key, defaultValue); - } - - /// - /// Returns the variable value associated with the given key, or an empty string if no mapping of the desired type exists for the given key. - /// - /// The variable name to retrieve the value for. - public string GetString(string key, string defaultValue = "") - { - return _maxUnityPluginClass.CallStatic("getString", key, defaultValue); - } - - [System.Obsolete("This API has been deprecated. Please use our SDK's initialization callback to retrieve variables instead.")] - public void LoadVariables() - { - _maxUnityPluginClass.CallStatic("loadVariables"); - } -} diff --git a/MaxSdk/Scripts/MaxVariableServiceAndroid.cs.meta b/MaxSdk/Scripts/MaxVariableServiceAndroid.cs.meta deleted file mode 100644 index d153c60..0000000 --- a/MaxSdk/Scripts/MaxVariableServiceAndroid.cs.meta +++ /dev/null @@ -1,6 +0,0 @@ -fileFormatVersion: 2 -guid: 837643e15fc734f7ab2fd5f71c919d01 -labels: -- al_max -- al_max_export_path-MaxSdk/Scripts/MaxVariableServiceAndroid.cs -timeCreated: 1547608580 diff --git a/MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs b/MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs deleted file mode 100644 index 43f8857..0000000 --- a/MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs +++ /dev/null @@ -1,30 +0,0 @@ -public class MaxVariableServiceUnityEditor -{ - private static readonly MaxVariableServiceUnityEditor _instance = new MaxVariableServiceUnityEditor(); - - public static MaxVariableServiceUnityEditor Instance - { - get { return _instance; } - } - - /// - /// Returns the variable value associated with the given key, or false if no mapping of the desired type exists for the given key. - /// - /// The variable name to retrieve the value for. - public bool GetBoolean(string key, bool defaultValue = false) - { - return defaultValue; - } - - /// - /// Returns the variable value associated with the given key, or an empty string if no mapping of the desired type exists for the given key. - /// - /// The variable name to retrieve the value for. - public string GetString(string key, string defaultValue = "") - { - return defaultValue; - } - - [System.Obsolete("This API has been deprecated. Please use our SDK's initialization callback to retrieve variables instead.")] - public void LoadVariables() { } -} diff --git a/MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs.meta b/MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs.meta deleted file mode 100644 index 772b2c3..0000000 --- a/MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs.meta +++ /dev/null @@ -1,6 +0,0 @@ -fileFormatVersion: 2 -guid: cc5e13a9689324605aa62b30ba0fca1f -labels: -- al_max -- al_max_export_path-MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs -timeCreated: 1547608594 diff --git a/MaxSdk/Scripts/MaxVariableServiceiOS.cs b/MaxSdk/Scripts/MaxVariableServiceiOS.cs deleted file mode 100644 index b039bb8..0000000 --- a/MaxSdk/Scripts/MaxVariableServiceiOS.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Runtime.InteropServices; - -#if UNITY_IOS -public class MaxVariableServiceiOS -{ - private static readonly MaxVariableServiceiOS _instance = new MaxVariableServiceiOS(); - - public static MaxVariableServiceiOS Instance - { - get { return _instance; } - } - - [DllImport("__Internal")] - private static extern void _MaxLoadVariables(); - - [DllImport("__Internal")] - private static extern bool _MaxGetBool(string name, bool defaultValue); - - [DllImport("__Internal")] - private static extern string _MaxGetString(string name, string defaultValue); - - /// - /// Returns the variable value associated with the given key, or false if no mapping of the desired type exists for the given key. - /// - /// The variable name to retrieve the value for. - public bool GetBoolean(string key, bool defaultValue = false) - { - return _MaxGetBool(key, defaultValue); - } - - /// - /// Returns the variable value associated with the given key, or an empty string if no mapping of the desired type exists for the given key. - /// - /// The variable name to retrieve the value for. - public string GetString(string key, string defaultValue = "") - { - return _MaxGetString(key, defaultValue); - } - - [System.Obsolete("This API has been deprecated. Please use our SDK's initialization callback to retrieve variables instead.")] - public void LoadVariables() - { - _MaxLoadVariables(); - } -} - -#endif diff --git a/MaxSdk/Scripts/MaxVariableServiceiOS.cs.meta b/MaxSdk/Scripts/MaxVariableServiceiOS.cs.meta deleted file mode 100644 index eacfb37..0000000 --- a/MaxSdk/Scripts/MaxVariableServiceiOS.cs.meta +++ /dev/null @@ -1,6 +0,0 @@ -fileFormatVersion: 2 -guid: 0d10ea5dac9bb46bfb388623e6153986 -labels: -- al_max -- al_max_export_path-MaxSdk/Scripts/MaxVariableServiceiOS.cs -timeCreated: 1547608568 diff --git a/MaxSdk/Scripts/ThirdParty.meta b/MaxSdk/Scripts/ThirdParty.meta index f78bcbe..81ce936 100644 --- a/MaxSdk/Scripts/ThirdParty.meta +++ b/MaxSdk/Scripts/ThirdParty.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a6dee059874b348009ba86a51a2bc978 +guid: 68fc43fe05dea4106bb4b376720d6708 labels: - al_max - al_max_export_path-MaxSdk/Scripts/ThirdParty diff --git a/MaxSdk/Scripts/ThirdParty/MiniJSON.cs b/MaxSdk/Scripts/ThirdParty/MiniJSON.cs index 32e0dec..b5fbd51 100644 --- a/MaxSdk/Scripts/ThirdParty/MiniJSON.cs +++ b/MaxSdk/Scripts/ThirdParty/MiniJSON.cs @@ -85,7 +85,7 @@ namespace AppLovinMax.ThirdParty.MiniJson public static object Deserialize(string json) { // save the string for debug information - if (json == null) + if (string.IsNullOrEmpty(json)) { return null; } diff --git a/MaxSdk/Scripts/ThirdParty/MiniJSON.cs.meta b/MaxSdk/Scripts/ThirdParty/MiniJSON.cs.meta index 1bed086..0200dde 100644 --- a/MaxSdk/Scripts/ThirdParty/MiniJSON.cs.meta +++ b/MaxSdk/Scripts/ThirdParty/MiniJSON.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 741e50fb3b1ea46a5b4d05b3da5015fa +guid: 52789a1d5a5754d46816fd9ed114a375 labels: - al_max - al_max_export_path-MaxSdk/Scripts/ThirdParty/MiniJSON.cs diff --git a/MaxSdk/Version.md.meta b/MaxSdk/Version.md.meta index 708a8bb..9b80f0c 100644 --- a/MaxSdk/Version.md.meta +++ b/MaxSdk/Version.md.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9410432e795b9407ab5a8b5b9e02e01d +guid: 8a6ad2e147c3a4553bda59a84413f07b labels: - al_max - al_max_export_path-MaxSdk/Version.md