From 5ab0b8da4186b337b3c4bdf98c91cf86e818b878 Mon Sep 17 00:00:00 2001 From: HuYufei Date: Tue, 26 Dec 2023 11:47:44 +0800 Subject: [PATCH] init commit --- .gitattributes | 2 + .gitignore | 2 + Amazon.meta | 8 + Amazon/Amazon.asmdef | 17 + Amazon/Amazon.asmdef.meta | 7 + Amazon/Plugins.meta | 8 + Amazon/Plugins/iOS.meta | 8 + Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec | 16 + .../iOS/Amazon-SDK-Plugin.podspec.meta | 7 + Amazon/Plugins/iOS/AmazonBinding.m | 283 +++ Amazon/Plugins/iOS/AmazonBinding.m.meta | 104 + Amazon/Plugins/iOS/AmazonManager.h | 71 + Amazon/Plugins/iOS/AmazonManager.h.meta | 89 + Amazon/Plugins/iOS/AmazonManager.mm | 295 +++ Amazon/Plugins/iOS/AmazonManager.mm.meta | 110 + Amazon/Plugins/iOS/AmazonUnityCallback.h | 20 + Amazon/Plugins/iOS/AmazonUnityCallback.h.meta | 105 + Amazon/Plugins/iOS/AmazonUnityCallback.mm | 38 + .../Plugins/iOS/AmazonUnityCallback.mm.meta | 85 + Amazon/Plugins/iOS/DTBBannerDelegate.h | 26 + Amazon/Plugins/iOS/DTBBannerDelegate.h.meta | 80 + Amazon/Plugins/iOS/DTBBannerDelegate.mm | 45 + Amazon/Plugins/iOS/DTBBannerDelegate.mm.meta | 85 + Amazon/Plugins/iOS/DTBInterstitialDelegate.h | 31 + .../iOS/DTBInterstitialDelegate.h.meta | 80 + Amazon/Plugins/iOS/DTBInterstitialDelegate.mm | 69 + .../iOS/DTBInterstitialDelegate.mm.meta | 85 + Amazon/Sample.meta | 8 + Amazon/Sample/APSMaxMediation.unity | 1679 ++++++++++++++ Amazon/Sample/APSMaxMediation.unity.meta | 7 + Amazon/Sample/AmazonMaxDemo.cs | 297 +++ Amazon/Sample/AmazonMaxDemo.cs.meta | 11 + Amazon/Scripts.meta | 8 + Amazon/Scripts/Amazon.cs | 123 + Amazon/Scripts/Amazon.cs.meta | 11 + Amazon/Scripts/AmazonConstants.cs | 30 + Amazon/Scripts/AmazonConstants.cs.meta | 11 + Amazon/Scripts/Common.meta | 8 + Amazon/Scripts/Common/IAdInterstitial.cs | 12 + Amazon/Scripts/Common/IAdInterstitial.cs.meta | 11 + Amazon/Scripts/Common/IAdRequest.cs | 84 + Amazon/Scripts/Common/IAdRequest.cs.meta | 11 + Amazon/Scripts/Common/IAdSize.cs | 9 + Amazon/Scripts/Common/IAdSize.cs.meta | 11 + Amazon/Scripts/Common/IAdView.cs | 11 + Amazon/Scripts/Common/IAdView.cs.meta | 11 + Amazon/Scripts/Common/IFetchManager.cs | 17 + Amazon/Scripts/Common/IFetchManager.cs.meta | 11 + Amazon/Scripts/Common/ISlotGroup.cs | 8 + Amazon/Scripts/Common/ISlotGroup.cs.meta | 11 + Amazon/Scripts/Editor.meta | 8 + Amazon/Scripts/Editor/Amazon.Editor.asmdef | 17 + .../Scripts/Editor/Amazon.Editor.asmdef.meta | 3 + Amazon/Scripts/Editor/AmazonAboutDialog.cs | 21 + .../Scripts/Editor/AmazonAboutDialog.cs.meta | 11 + Amazon/Scripts/Editor/AmazonBuildScript.cs | 104 + .../Scripts/Editor/AmazonBuildScript.cs.meta | 11 + .../Editor/AmazonCoroutineExtensions.cs | 51 + .../Editor/AmazonCoroutineExtensions.cs.meta | 11 + Amazon/Scripts/Editor/AmazonCoroutines.cs | 351 +++ .../Scripts/Editor/AmazonCoroutines.cs.meta | 11 + Amazon/Scripts/Editor/AmazonDependencies.xml | 16 + .../Editor/AmazonDependencies.xml.meta | 7 + Amazon/Scripts/Editor/AmazonPostBuildiOS.cs | 54 + .../Scripts/Editor/AmazonPostBuildiOS.cs.meta | 11 + Amazon/Scripts/Editor/AmazonSDKManager.cs | 400 ++++ .../Scripts/Editor/AmazonSDKManager.cs.meta | 11 + Amazon/Scripts/Editor/Tests.meta | 8 + Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs | 41 + .../Editor/Tests/AmazonSDKTests.cs.meta | 11 + Amazon/Scripts/Editor/Tests/AmazonTest.cs | 14 + .../Scripts/Editor/Tests/AmazonTest.cs.meta | 11 + .../Scripts/Editor/Tests/AmazonUtilsTests.cs | 102 + .../Editor/Tests/AmazonUtilsTests.cs.meta | 11 + Amazon/Scripts/Internal.meta | 8 + Amazon/Scripts/Internal/APSAdDelegate.cs | 34 + Amazon/Scripts/Internal/APSAdDelegate.cs.meta | 11 + Amazon/Scripts/Internal/APSBannerAdRequest.cs | 88 + .../Internal/APSBannerAdRequest.cs.meta | 11 + .../Internal/APSInterstitialAdRequest.cs | 8 + .../Internal/APSInterstitialAdRequest.cs.meta | 11 + Amazon/Scripts/Internal/APSMediationUtils.cs | 41 + .../Internal/APSMediationUtils.cs.meta | 11 + Amazon/Scripts/Internal/APSVideoAdRequest.cs | 8 + .../Internal/APSVideoAdRequest.cs.meta | 11 + Amazon/Scripts/Internal/AdError.cs | 57 + Amazon/Scripts/Internal/AdError.cs.meta | 11 + Amazon/Scripts/Internal/AdInterstitial.cs | 26 + .../Scripts/Internal/AdInterstitial.cs.meta | 11 + Amazon/Scripts/Internal/AdNetworkInfo.cs | 30 + Amazon/Scripts/Internal/AdNetworkInfo.cs.meta | 11 + Amazon/Scripts/Internal/AdRequest.cs | 59 + Amazon/Scripts/Internal/AdRequest.cs.meta | 11 + Amazon/Scripts/Internal/AdResponce.cs | 4 + Amazon/Scripts/Internal/AdResponce.cs.meta | 11 + Amazon/Scripts/Internal/AdResponse.cs | 28 + Amazon/Scripts/Internal/AdResponse.cs.meta | 11 + Amazon/Scripts/Internal/AdSize.cs | 47 + Amazon/Scripts/Internal/AdSize.cs.meta | 11 + Amazon/Scripts/Internal/AdView.cs | 22 + Amazon/Scripts/Internal/AdView.cs.meta | 11 + .../Scripts/Internal/AmazonPackageConfig.cs | 4 + .../Internal/AmazonPackageConfig.cs.meta | 11 + Amazon/Scripts/Internal/AmazonUtils.cs | 75 + Amazon/Scripts/Internal/AmazonUtils.cs.meta | 11 + Amazon/Scripts/Internal/Android.meta | 8 + .../Internal/Android/AdRegistration.cs | 161 ++ .../Internal/Android/AdRegistration.cs.meta | 11 + .../Internal/Android/AndroidAdInterstitial.cs | 34 + .../Android/AndroidAdInterstitial.cs.meta | 11 + .../Internal/Android/AndroidAdResponce.cs | 4 + .../Android/AndroidAdResponce.cs.meta | 11 + .../Internal/Android/AndroidAdResponse.cs | 104 + .../Android/AndroidAdResponse.cs.meta | 11 + .../Scripts/Internal/Android/AndroidAdView.cs | 28 + .../Internal/Android/AndroidAdView.cs.meta | 11 + .../Internal/Android/AndroidPlatform.cs | 94 + .../Internal/Android/AndroidPlatform.cs.meta | 11 + .../Internal/Android/DTBAdBannerListener.cs | 50 + .../Android/DTBAdBannerListener.cs.meta | 11 + .../Android/DTBAdInterstitialListener.cs | 56 + .../Android/DTBAdInterstitialListener.cs.meta | 11 + .../Scripts/Internal/Android/DTBAdRequest.cs | 215 ++ .../Internal/Android/DTBAdRequest.cs.meta | 11 + Amazon/Scripts/Internal/Android/DTBAdSize.cs | 49 + .../Internal/Android/DTBAdSize.cs.meta | 11 + .../Scripts/Internal/Android/DTBCallback.cs | 44 + .../Internal/Android/DTBCallback.cs.meta | 11 + .../Internal/Android/DTBFetchFactory.cs | 32 + .../Internal/Android/DTBFetchFactory.cs.meta | 11 + .../Internal/Android/DTBFetchManager.cs | 35 + .../Internal/Android/DTBFetchManager.cs.meta | 11 + .../Scripts/Internal/Android/DTBSlotGroup.cs | 33 + .../Internal/Android/DTBSlotGroup.cs.meta | 11 + Amazon/Scripts/Internal/IOS.meta | 8 + .../Internal/IOS/DTBAdBannerDispatcher.cs | 61 + .../IOS/DTBAdBannerDispatcher.cs.meta | 11 + .../IOS/DTBAdInterstitialDispatcher.cs | 74 + .../IOS/DTBAdInterstitialDispatcher.cs.meta | 11 + Amazon/Scripts/Internal/IOS/DTBAdRequest.cs | 185 ++ .../Scripts/Internal/IOS/DTBAdRequest.cs.meta | 11 + Amazon/Scripts/Internal/IOS/DTBAdSize.cs | 69 + Amazon/Scripts/Internal/IOS/DTBAdSize.cs.meta | 11 + Amazon/Scripts/Internal/IOS/DTBCallback.cs | 84 + .../Scripts/Internal/IOS/DTBCallback.cs.meta | 11 + .../Scripts/Internal/IOS/DTBFetchManager.cs | 44 + .../Internal/IOS/DTBFetchManager.cs.meta | 11 + Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs | 31 + .../Scripts/Internal/IOS/DTBSlotGroup.cs.meta | 11 + Amazon/Scripts/Internal/IOS/Externs.cs | 218 ++ Amazon/Scripts/Internal/IOS/Externs.cs.meta | 11 + .../Scripts/Internal/IOS/IOSAdInterstitial.cs | 27 + .../Internal/IOS/IOSAdInterstitial.cs.meta | 11 + Amazon/Scripts/Internal/IOS/IOSAdResponce.cs | 4 + .../Internal/IOS/IOSAdResponce.cs.meta | 11 + Amazon/Scripts/Internal/IOS/IOSAdResponse.cs | 92 + .../Internal/IOS/IOSAdResponse.cs.meta | 11 + Amazon/Scripts/Internal/IOS/IOSAdView.cs | 21 + Amazon/Scripts/Internal/IOS/IOSAdView.cs.meta | 11 + Amazon/Scripts/Internal/IOS/IOSPlatform.cs | 131 ++ .../Scripts/Internal/IOS/IOSPlatform.cs.meta | 11 + Amazon/Scripts/Internal/MiniJSON.cs | 550 +++++ Amazon/Scripts/Internal/MiniJSON.cs.meta | 11 + Amazon/Scripts/Internal/PlatformApi.cs | 28 + Amazon/Scripts/Internal/PlatformApi.cs.meta | 11 + Amazon/Scripts/Internal/SlotGroup.cs | 31 + Amazon/Scripts/Internal/SlotGroup.cs.meta | 11 + Amazon/Scripts/Mediations.meta | 8 + .../Scripts/Mediations/AppLovinMediation.meta | 8 + .../Mediations/AppLovinMediation/Editor.meta | 8 + .../Editor/APSAppLovinPackageConfig.cs | 14 + .../Editor/APSAppLovinPackageConfig.cs.meta | 11 + .../AppLovinMediation/Editor/Dependencies.xml | 9 + .../Editor/Dependencies.xml.meta | 10 + Editor.meta | 3 + Editor/CodeMods.meta | 3 + Editor/CodeMods/AmazonMod.cs | 116 + Editor/CodeMods/AmazonMod.cs.meta | 3 + Editor/CodeMods/ApplovinMod.cs | 173 ++ Editor/CodeMods/ApplovinMod.cs.meta | 3 + Editor/CodeMods/GuruMaxCodeFixer.cs | 77 + Editor/CodeMods/GuruMaxCodeFixer.cs.meta | 11 + Editor/CodeMods/GuruModifier.cs | 28 + Editor/CodeMods/GuruModifier.cs.meta | 3 + Editor/CodeMods/PubmaticMod.cs | 39 + Editor/CodeMods/PubmaticMod.cs.meta | 3 + Editor/EasyGUILayout.cs | 192 ++ Editor/EasyGUILayout.cs.meta | 3 + Editor/EditorExtention.cs | 59 + Editor/EditorExtention.cs.meta | 3 + Editor/GuruEditorMax.asmdef | 18 + Editor/GuruEditorMax.asmdef.meta | 3 + Editor/GuruEditorMax.meta | 3 + .../GuruMaxIntegrationManager.cs | 381 +++ .../GuruMaxIntegrationManager.cs.meta | 3 + Editor/GuruEditorMax/GuruMaxMenuItems.cs | 16 + Editor/GuruEditorMax/GuruMaxMenuItems.cs.meta | 3 + Editor/GuruEditorMax/GuruMaxSdkAPI.cs | 184 ++ Editor/GuruEditorMax/GuruMaxSdkAPI.cs.meta | 11 + Editor/IFileIO.cs | 7 + Editor/IFileIO.cs.meta | 3 + Editor/Test.meta | 8 + Editor/Test/GuruMaxTest.cs | 35 + Editor/Test/GuruMaxTest.cs.meta | 11 + GuruMax.asmdef | 17 + GuruMax.asmdef.meta | 7 + MaxSdk.meta | 8 + MaxSdk/AppLovin.meta | 11 + MaxSdk/AppLovin/Editor.meta | 11 + MaxSdk/AppLovin/Editor/Dependencies.xml | 9 + MaxSdk/AppLovin/Editor/Dependencies.xml.meta | 10 + MaxSdk/AppLovin/Plugins.meta | 11 + MaxSdk/AppLovin/Plugins/Android.meta | 11 + .../Android/applovin-max-unity-plugin.aar | Bin 0 -> 75984 bytes .../applovin-max-unity-plugin.aar.meta | 35 + MaxSdk/AppLovin/Plugins/iOS.meta | 11 + .../AppLovin/Plugins/iOS/MAUnityAdManager.h | 116 + .../Plugins/iOS/MAUnityAdManager.h.meta | 115 + .../AppLovin/Plugins/iOS/MAUnityAdManager.m | 2046 +++++++++++++++++ .../Plugins/iOS/MAUnityAdManager.m.meta | 109 + MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm | 1105 +++++++++ .../Plugins/iOS/MAUnityPlugin.mm.meta | 109 + MaxSdk/MaxSdk.asmdef | 14 + MaxSdk/MaxSdk.asmdef.meta | 10 + MaxSdk/Mediation.meta | 11 + MaxSdk/Mediation/BidMachine.meta | 11 + MaxSdk/Mediation/BidMachine/Editor.meta | 11 + .../BidMachine/Editor/Dependencies.xml | 13 + .../BidMachine/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/ByteDance.meta | 11 + MaxSdk/Mediation/ByteDance/Editor.meta | 11 + .../ByteDance/Editor/Dependencies.xml | 13 + .../ByteDance/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/Chartboost.meta | 11 + MaxSdk/Mediation/Chartboost/Editor.meta | 11 + .../Chartboost/Editor/Dependencies.xml | 14 + .../Chartboost/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/Facebook.meta | 11 + MaxSdk/Mediation/Facebook/Editor.meta | 11 + .../Facebook/Editor/Dependencies.xml | 13 + .../Facebook/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/Fyber.meta | 11 + MaxSdk/Mediation/Fyber/Editor.meta | 11 + .../Mediation/Fyber/Editor/Dependencies.xml | 9 + .../Fyber/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/Google.meta | 11 + MaxSdk/Mediation/Google/Editor.meta | 11 + .../Mediation/Google/Editor/Dependencies.xml | 10 + .../Google/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/GoogleAdManager.meta | 11 + MaxSdk/Mediation/GoogleAdManager/Editor.meta | 11 + .../GoogleAdManager/Editor/Dependencies.xml | 10 + .../Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/HyprMX.meta | 11 + MaxSdk/Mediation/HyprMX/Editor.meta | 11 + .../Mediation/HyprMX/Editor/Dependencies.xml | 9 + .../HyprMX/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/InMobi.meta | 11 + MaxSdk/Mediation/InMobi/Editor.meta | 11 + .../Mediation/InMobi/Editor/Dependencies.xml | 12 + .../InMobi/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/IronSource.meta | 11 + MaxSdk/Mediation/IronSource/Editor.meta | 11 + .../IronSource/Editor/Dependencies.xml | 13 + .../IronSource/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/MediationAdapters.txt | 2 + MaxSdk/Mediation/MediationAdapters.txt.meta | 6 + MaxSdk/Mediation/Mintegral.meta | 11 + MaxSdk/Mediation/Mintegral/Editor.meta | 11 + .../Mintegral/Editor/Dependencies.xml | 14 + .../Mintegral/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/MobileFuse.meta | 11 + MaxSdk/Mediation/MobileFuse/Editor.meta | 11 + .../MobileFuse/Editor/Dependencies.xml | 9 + .../MobileFuse/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/OguryPresage.meta | 11 + MaxSdk/Mediation/OguryPresage/Editor.meta | 11 + .../OguryPresage/Editor/Dependencies.xml | 13 + .../OguryPresage/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/Smaato.meta | 11 + MaxSdk/Mediation/Smaato/Editor.meta | 11 + .../Mediation/Smaato/Editor/Dependencies.xml | 13 + .../Smaato/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/UnityAds.meta | 11 + MaxSdk/Mediation/UnityAds/Editor.meta | 11 + .../UnityAds/Editor/Dependencies.xml | 9 + .../UnityAds/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/Verve.meta | 11 + MaxSdk/Mediation/Verve/Editor.meta | 11 + .../Mediation/Verve/Editor/Dependencies.xml | 12 + .../Verve/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/Vungle.meta | 11 + MaxSdk/Mediation/Vungle/Editor.meta | 11 + .../Mediation/Vungle/Editor/Dependencies.xml | 9 + .../Vungle/Editor/Dependencies.xml.meta | 10 + MaxSdk/Mediation/Yandex.meta | 11 + MaxSdk/Mediation/Yandex/Editor.meta | 11 + .../Mediation/Yandex/Editor/Dependencies.xml | 9 + .../Yandex/Editor/Dependencies.xml.meta | 10 + MaxSdk/Prefabs.meta | 11 + MaxSdk/Prefabs/BannerBottom.prefab | 402 ++++ MaxSdk/Prefabs/BannerBottom.prefab.meta | 10 + MaxSdk/Prefabs/BannerTop.prefab | 402 ++++ MaxSdk/Prefabs/BannerTop.prefab.meta | 10 + MaxSdk/Prefabs/Interstitial.prefab | 523 +++++ MaxSdk/Prefabs/Interstitial.prefab.meta | 10 + MaxSdk/Prefabs/Rewarded.prefab | 795 +++++++ MaxSdk/Prefabs/Rewarded.prefab.meta | 10 + MaxSdk/README.md | 91 + MaxSdk/README.md.meta | 10 + MaxSdk/Resources.meta | 11 + MaxSdk/Resources/Images.meta | 11 + MaxSdk/Resources/Images/alert_icon.png | Bin 0 -> 1154 bytes MaxSdk/Resources/Images/alert_icon.png.meta | 94 + MaxSdk/Resources/Images/uninstall_icon.png | Bin 0 -> 159 bytes .../Resources/Images/uninstall_icon.png.meta | 94 + MaxSdk/Resources/Images/warning_icon.png | Bin 0 -> 959 bytes MaxSdk/Resources/Images/warning_icon.png.meta | 91 + MaxSdk/Scripts.meta | 11 + MaxSdk/Scripts/Editor.meta | 11 + MaxSdk/Scripts/Editor/MaxInitialization.cs | 129 ++ .../Scripts/Editor/MaxInitialization.cs.meta | 14 + .../Editor/MaxPostProcessBuildAndroid.cs | 272 +++ .../Editor/MaxPostProcessBuildAndroid.cs.meta | 14 + .../Scripts/Editor/MaxPostProcessBuildiOS.cs | 690 ++++++ .../Editor/MaxPostProcessBuildiOS.cs.meta | 14 + .../Editor/MaxSdk.Scripts.Editor.asmdef | 11 + .../Editor/MaxSdk.Scripts.Editor.asmdef.meta | 6 + MaxSdk/Scripts/IntegrationManager.meta | 11 + MaxSdk/Scripts/IntegrationManager/Editor.meta | 11 + .../Editor/AppLovinAutoUpdater.cs | 195 ++ .../Editor/AppLovinAutoUpdater.cs.meta | 14 + .../Editor/AppLovinCommandLine.cs | 94 + .../Editor/AppLovinCommandLine.cs.meta | 14 + .../Editor/AppLovinDownloadHandler.cs | 75 + .../Editor/AppLovinDownloadHandler.cs.meta | 14 + .../Editor/AppLovinEditorCoroutine.cs | 91 + .../Editor/AppLovinEditorCoroutine.cs.meta | 14 + .../Editor/AppLovinIntegrationManager.cs | 814 +++++++ .../Editor/AppLovinIntegrationManager.cs.meta | 14 + .../AppLovinIntegrationManagerWindow.cs | 1013 ++++++++ .../AppLovinIntegrationManagerWindow.cs.meta | 14 + .../Editor/AppLovinInternalSettings.cs | 329 +++ .../Editor/AppLovinInternalSettings.cs.meta | 14 + .../Editor/AppLovinMenuItems.cs.backup | 60 + .../Editor/AppLovinMenuItems.cs.backup.meta | 10 + .../AppLovinPostProcessAndroidGradle.cs | 65 + .../AppLovinPostProcessAndroidGradle.cs.meta | 14 + .../Editor/AppLovinPostProcessiOS.cs | 108 + .../Editor/AppLovinPostProcessiOS.cs.meta | 14 + .../Editor/AppLovinPreProcessAndroid.cs | 216 ++ .../Editor/AppLovinPreProcessAndroid.cs.meta | 14 + .../Editor/AppLovinProcessGradleBuildFile.cs | 583 +++++ .../AppLovinProcessGradleBuildFile.cs.meta | 14 + .../Editor/AppLovinSettings.cs | 390 ++++ .../Editor/AppLovinSettings.cs.meta | 14 + .../MaxSdk.IntegrationManager.Editor.asmdef | 18 + ...xSdk.IntegrationManager.Editor.asmdef.meta | 6 + MaxSdk/Scripts/MaxEventSystemChecker.cs | 37 + MaxSdk/Scripts/MaxEventSystemChecker.cs.meta | 14 + MaxSdk/Scripts/MaxEvents.cs | 21 + MaxSdk/Scripts/MaxEvents.cs.meta | 14 + MaxSdk/Scripts/MaxSdk.Scripts.asmdef | 6 + MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta | 10 + MaxSdk/Scripts/MaxSdk.cs | 30 + MaxSdk/Scripts/MaxSdk.cs.meta | 14 + MaxSdk/Scripts/MaxSdkAndroid.cs | 1236 ++++++++++ MaxSdk/Scripts/MaxSdkAndroid.cs.meta | 14 + MaxSdk/Scripts/MaxSdkBase.cs | 772 +++++++ MaxSdk/Scripts/MaxSdkBase.cs.meta | 14 + MaxSdk/Scripts/MaxSdkCallbacks.cs | 1828 +++++++++++++++ MaxSdk/Scripts/MaxSdkCallbacks.cs.meta | 14 + MaxSdk/Scripts/MaxSdkLogger.cs | 70 + MaxSdk/Scripts/MaxSdkLogger.cs.meta | 14 + MaxSdk/Scripts/MaxSdkUnityEditor.cs | 1536 +++++++++++++ MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta | 14 + MaxSdk/Scripts/MaxSdkUtils.cs | 528 +++++ MaxSdk/Scripts/MaxSdkUtils.cs.meta | 14 + MaxSdk/Scripts/MaxSdkiOS.cs | 1532 ++++++++++++ MaxSdk/Scripts/MaxSdkiOS.cs.meta | 14 + MaxSdk/Scripts/MaxTargetingData.cs | 142 ++ MaxSdk/Scripts/MaxTargetingData.cs.meta | 14 + MaxSdk/Scripts/MaxUserSegment.cs | 31 + MaxSdk/Scripts/MaxUserSegment.cs.meta | 14 + MaxSdk/Scripts/MaxUserServiceAndroid.cs | 35 + MaxSdk/Scripts/MaxUserServiceAndroid.cs.meta | 14 + MaxSdk/Scripts/MaxUserServiceUnityEditor.cs | 32 + .../Scripts/MaxUserServiceUnityEditor.cs.meta | 14 + MaxSdk/Scripts/MaxUserServiceiOS.cs | 29 + MaxSdk/Scripts/MaxUserServiceiOS.cs.meta | 14 + 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 | 11 + MaxSdk/Scripts/ThirdParty/MiniJSON.cs | 629 +++++ MaxSdk/Scripts/ThirdParty/MiniJSON.cs.meta | 14 + MaxSdk/Version.md | 3 + MaxSdk/Version.md.meta | 10 + Moloco.meta | 8 + Moloco/Editor.meta | 8 + Moloco/Editor/ALMolocoAdapterDependencies.xml | 10 + .../ALMolocoAdapterDependencies.xml.meta | 10 + Moloco/Moloco.asmdef | 3 + Moloco/Moloco.asmdef.meta | 3 + Moloco/Scripts.meta | 8 + Moloco/Scripts/Editor.meta | 8 + Moloco/Scripts/Editor/Moloco.Editor.asmdef | 6 + .../Scripts/Editor/Moloco.Editor.asmdef.meta | 3 + .../Editor/MolocoPostProcessBuildiOS.cs | 90 + .../Editor/MolocoPostProcessBuildiOS.cs.meta | 11 + Moloco/Scripts/Editor/PodfileEditor.cs | 63 + Moloco/Scripts/Editor/PodfileEditor.cs.meta | 11 + OpenWrapSDK.meta | 8 + OpenWrapSDK/Editor.meta | 8 + OpenWrapSDK/Editor/OpenWrapSDK.Editor.asmdef | 17 + .../Editor/OpenWrapSDK.Editor.asmdef.meta | 7 + .../Editor/OpenWrapSDKDependencies.xml | 19 + .../Editor/OpenWrapSDKDependencies.xml.meta | 7 + .../Editor/OpenWrapSDKSKAdNetworkIDs.xml | 37 + .../Editor/OpenWrapSDKSKAdNetworkIDs.xml.meta | 7 + OpenWrapSDK/Editor/POBATTPostProcessBuild.cs | 53 + .../Editor/POBATTPostProcessBuild.cs.meta | 11 + OpenWrapSDK/Editor/POBPlistProcessor.cs | 138 ++ OpenWrapSDK/Editor/POBPlistProcessor.cs.meta | 11 + OpenWrapSDK/Editor/POBPostProcessBuildiOS.cs | 71 + .../Editor/POBPostProcessBuildiOS.cs.meta | 11 + OpenWrapSDK/Mediation.meta | 8 + OpenWrapSDK/Mediation/AppLovinMAX.meta | 8 + OpenWrapSDK/Mediation/AppLovinMAX/Editor.meta | 8 + .../ALOpenWrapMediationDependencies.xml | 16 + .../ALOpenWrapMediationDependencies.xml.meta | 7 + .../Mediation/AppLovinMAX/POBMAXConstants.cs | 60 + .../AppLovinMAX/POBMAXConstants.cs.meta | 11 + .../Mediation/AppLovinMAX/POBMAXUtil.cs | 115 + .../Mediation/AppLovinMAX/POBMAXUtil.cs.meta | 11 + OpenWrapSDK/OpenWrapSDK.asmdef | 3 + OpenWrapSDK/OpenWrapSDK.asmdef.meta | 7 + OpenWrapSDK/Platform.meta | 8 + OpenWrapSDK/Platform/Android.meta | 8 + OpenWrapSDK/Platform/Android/Ads.meta | 8 + .../Android/Ads/POBBannerViewClient.cs | 275 +++ .../Android/Ads/POBBannerViewClient.cs.meta | 11 + .../Android/Ads/POBInterstitialClient.cs | 301 +++ .../Android/Ads/POBInterstitialClient.cs.meta | 11 + .../Android/Ads/POBRewardedAdClient.cs | 339 +++ .../Android/Ads/POBRewardedAdClient.cs.meta | 11 + OpenWrapSDK/Platform/Android/Models.meta | 8 + .../Platform/Android/Models/POBBidClient.cs | 267 +++ .../Android/Models/POBBidClient.cs.meta | 11 + .../Android/Models/POBDataProviderClient.cs | 174 ++ .../Models/POBDataProviderClient.cs.meta | 11 + .../Android/Models/POBExternalUserIdClient.cs | 105 + .../Models/POBExternalUserIdClient.cs.meta | 11 + .../Android/Models/POBImpressionClient.cs | 133 ++ .../Models/POBImpressionClient.cs.meta | 11 + .../Android/Models/POBRequestClient.cs | 218 ++ .../Android/Models/POBRequestClient.cs.meta | 11 + .../Android/Models/POBRewardClient.cs | 96 + .../Android/Models/POBRewardClient.cs.meta | 11 + .../Android/Models/POBSegmentClient.cs | 90 + .../Android/Models/POBSegmentClient.cs.meta | 11 + .../Android/Models/POBUserInfoClient.cs | 242 ++ .../Android/Models/POBUserInfoClient.cs.meta | 11 + .../Platform/Android/OpenWrapSDKClient.cs | 318 +++ .../Android/OpenWrapSDKClient.cs.meta | 11 + OpenWrapSDK/Platform/Android/POBConstants.cs | 48 + .../Platform/Android/POBConstants.cs.meta | 11 + OpenWrapSDK/Platform/Android/Utils.meta | 8 + .../Platform/Android/Utils/POBAndroidUtils.cs | 444 ++++ .../Android/Utils/POBAndroidUtils.cs.meta | 11 + .../Android/Utils/POBEventsDispatcher.cs | 121 + .../Android/Utils/POBEventsDispatcher.cs.meta | 11 + OpenWrapSDK/Platform/Common.meta | 8 + OpenWrapSDK/Platform/Common/Interfaces.meta | 8 + .../Common/Interfaces/IPOBBannerViewClient.cs | 126 + .../Interfaces/IPOBBannerViewClient.cs.meta | 11 + .../Interfaces/IPOBDataProviderClient.cs | 81 + .../Interfaces/IPOBDataProviderClient.cs.meta | 11 + .../Interfaces/IPOBExternalUserIdClient.cs | 61 + .../IPOBExternalUserIdClient.cs.meta | 11 + .../Interfaces/IPOBInterstitialClient.cs | 117 + .../Interfaces/IPOBInterstitialClient.cs.meta | 11 + .../Common/Interfaces/IPOBRewardedAdClient.cs | 126 + .../Interfaces/IPOBRewardedAdClient.cs.meta | 15 + .../Common/Interfaces/IPOBSegmentClient.cs | 56 + .../Interfaces/IPOBSegmentClient.cs.meta | 11 + .../Common/Interfaces/IPOBUserInfoClient.cs | 116 + .../Interfaces/IPOBUserInfoClient.cs.meta | 11 + OpenWrapSDK/Platform/Common/Logger.meta | 8 + OpenWrapSDK/Platform/Common/Logger/POBLog.cs | 62 + .../Platform/Common/Logger/POBLog.cs.meta | 11 + OpenWrapSDK/Platform/Common/POBLogStrings.cs | 154 ++ .../Platform/Common/POBLogStrings.cs.meta | 11 + OpenWrapSDK/Platform/Common/Utils.meta | 8 + OpenWrapSDK/Platform/Common/Utils/POBUtils.cs | 41 + .../Platform/Common/Utils/POBUtils.cs.meta | 11 + OpenWrapSDK/Platform/iOS.meta | 8 + OpenWrapSDK/Platform/iOS/Ads.meta | 8 + .../Platform/iOS/Ads/POBBannerViewClient.cs | 378 +++ .../iOS/Ads/POBBannerViewClient.cs.meta | 11 + .../Platform/iOS/Ads/POBInterstitialClient.cs | 361 +++ .../iOS/Ads/POBInterstitialClient.cs.meta | 11 + .../Platform/iOS/Ads/POBRewardedAdClient.cs | 382 +++ .../iOS/Ads/POBRewardedAdClient.cs.meta | 15 + OpenWrapSDK/Platform/iOS/Models.meta | 8 + .../Platform/iOS/Models/POBBidClient.cs | 302 +++ .../Platform/iOS/Models/POBBidClient.cs.meta | 11 + .../iOS/Models/POBDataProviderClient.cs | 203 ++ .../iOS/Models/POBDataProviderClient.cs.meta | 11 + .../iOS/Models/POBExternalUserIdClient.cs | 182 ++ .../Models/POBExternalUserIdClient.cs.meta | 11 + .../iOS/Models/POBImpressionClient.cs | 148 ++ .../iOS/Models/POBImpressionClient.cs.meta | 11 + .../Platform/iOS/Models/POBRequestClient.cs | 212 ++ .../iOS/Models/POBRequestClient.cs.meta | 11 + .../Platform/iOS/Models/POBRewardClient.cs | 75 + .../iOS/Models/POBRewardClient.cs.meta | 11 + .../Platform/iOS/Models/POBSegmentClient.cs | 117 + .../iOS/Models/POBSegmentClient.cs.meta | 11 + .../Platform/iOS/Models/POBUserInfoClient.cs | 285 +++ .../iOS/Models/POBUserInfoClient.cs.meta | 11 + OpenWrapSDK/Platform/iOS/OpenWrapSDKClient.cs | 257 +++ .../Platform/iOS/OpenWrapSDKClient.cs.meta | 11 + OpenWrapSDK/Platform/iOS/Utils.meta | 8 + OpenWrapSDK/Platform/iOS/Utils/POBIOSUtils.cs | 54 + .../Platform/iOS/Utils/POBIOSUtils.cs.meta | 11 + OpenWrapSDK/Plugins.meta | 8 + OpenWrapSDK/Plugins/OpenWrapSDK.meta | 8 + OpenWrapSDK/Plugins/OpenWrapSDK/Android.meta | 8 + .../Android/openwrap-sdk-unity.aar | Bin 0 -> 32965 bytes .../Android/openwrap-sdk-unity.aar.meta | 32 + OpenWrapSDK/Plugins/OpenWrapSDK/iOS.meta | 8 + .../Plugins/OpenWrapSDK/iOS/Banner.meta | 8 + .../OpenWrapSDK/iOS/Banner/POBUBannerView.h | 124 + .../iOS/Banner/POBUBannerView.h.meta | 27 + .../OpenWrapSDK/iOS/Banner/POBUBannerView.m | 182 ++ .../iOS/Banner/POBUBannerView.m.meta | 37 + .../Plugins/OpenWrapSDK/iOS/Helper.meta | 8 + .../iOS/Helper/POBUAdsCacheManager.h | 57 + .../iOS/Helper/POBUAdsCacheManager.h.meta | 27 + .../iOS/Helper/POBUAdsCacheManager.m | 58 + .../iOS/Helper/POBUAdsCacheManager.m.meta | 37 + .../OpenWrapSDK/iOS/Helper/POBUUIUtil.h | 64 + .../OpenWrapSDK/iOS/Helper/POBUUIUtil.h.meta | 27 + .../OpenWrapSDK/iOS/Helper/POBUUIUtil.m | 122 + .../OpenWrapSDK/iOS/Helper/POBUUIUtil.m.meta | 37 + .../Plugins/OpenWrapSDK/iOS/Helper/POBUUtil.h | 63 + .../OpenWrapSDK/iOS/Helper/POBUUtil.h.meta | 27 + .../Plugins/OpenWrapSDK/iOS/Helper/POBUUtil.m | 89 + .../OpenWrapSDK/iOS/Helper/POBUUtil.m.meta | 37 + .../Plugins/OpenWrapSDK/iOS/Interstitial.meta | 8 + .../iOS/Interstitial/POBUInterstitial.h | 107 + .../iOS/Interstitial/POBUInterstitial.h.meta | 27 + .../iOS/Interstitial/POBUInterstitial.m | 127 + .../iOS/Interstitial/POBUInterstitial.m.meta | 37 + .../Plugins/OpenWrapSDK/iOS/Mediation.meta | 3 + .../iOS/Mediation/POBMAXUInterface.m | 85 + .../iOS/Mediation/POBMAXUInterface.m.meta | 37 + .../Plugins/OpenWrapSDK/iOS/POBUConstants.h | 71 + .../OpenWrapSDK/iOS/POBUConstants.h.meta | 27 + .../Plugins/OpenWrapSDK/iOS/POBUInterface.m | 516 +++++ .../OpenWrapSDK/iOS/POBUInterface.m.meta | 37 + .../OpenWrapSDK/iOS/POBUModelsInterface.m | 458 ++++ .../iOS/POBUModelsInterface.m.meta | 37 + .../Plugins/OpenWrapSDK/iOS/POBUTypes.h | 59 + .../Plugins/OpenWrapSDK/iOS/POBUTypes.h.meta | 27 + .../Plugins/OpenWrapSDK/iOS/Rewarded.meta | 8 + .../OpenWrapSDK/iOS/Rewarded/POBURewardedAd.h | 117 + .../iOS/Rewarded/POBURewardedAd.h.meta | 27 + .../OpenWrapSDK/iOS/Rewarded/POBURewardedAd.m | 142 ++ .../iOS/Rewarded/POBURewardedAd.m.meta | 37 + OpenWrapSDK/Public.meta | 8 + OpenWrapSDK/Public/Ads.meta | 8 + OpenWrapSDK/Public/Ads/POBBannerView.cs | 278 +++ OpenWrapSDK/Public/Ads/POBBannerView.cs.meta | 11 + OpenWrapSDK/Public/Ads/POBInterstitial.cs | 245 ++ .../Public/Ads/POBInterstitial.cs.meta | 11 + OpenWrapSDK/Public/Ads/POBRewardedAd.cs | 278 +++ OpenWrapSDK/Public/Ads/POBRewardedAd.cs.meta | 11 + OpenWrapSDK/Public/Enums.meta | 8 + OpenWrapSDK/Public/Enums/POBAdPosition.cs | 48 + .../Public/Enums/POBAdPosition.cs.meta | 11 + OpenWrapSDK/Public/Enums/POBBannerPosition.cs | 51 + .../Public/Enums/POBBannerPosition.cs.meta | 11 + OpenWrapSDK/Public/Enums/POBLocSource.cs | 35 + OpenWrapSDK/Public/Enums/POBLocSource.cs.meta | 11 + OpenWrapSDK/Public/Enums/POBSDKLogLevel.cs | 48 + .../Public/Enums/POBSDKLogLevel.cs.meta | 11 + OpenWrapSDK/Public/Interfaces.meta | 8 + OpenWrapSDK/Public/Interfaces/IPOBBid.cs | 127 + OpenWrapSDK/Public/Interfaces/IPOBBid.cs.meta | 11 + .../Public/Interfaces/IPOBImpression.cs | 85 + .../Public/Interfaces/IPOBImpression.cs.meta | 11 + OpenWrapSDK/Public/Interfaces/IPOBRequest.cs | 116 + .../Public/Interfaces/IPOBRequest.cs.meta | 11 + OpenWrapSDK/Public/Interfaces/IPOBReward.cs | 46 + .../Public/Interfaces/IPOBReward.cs.meta | 11 + OpenWrapSDK/Public/Models.meta | 8 + OpenWrapSDK/Public/Models/POBAdSize.cs | 102 + OpenWrapSDK/Public/Models/POBAdSize.cs.meta | 11 + .../Public/Models/POBApplicationInfo.cs | 69 + .../Public/Models/POBApplicationInfo.cs.meta | 11 + OpenWrapSDK/Public/Models/POBDataProvider.cs | 272 +++ .../Public/Models/POBDataProvider.cs.meta | 11 + .../Public/Models/POBErrorEventArgs.cs | 138 ++ .../Public/Models/POBErrorEventArgs.cs.meta | 11 + .../Public/Models/POBExternalUserId.cs | 121 + .../Public/Models/POBExternalUserId.cs.meta | 11 + .../Public/Models/POBRewardEventArgs.cs | 52 + .../Public/Models/POBRewardEventArgs.cs.meta | 11 + OpenWrapSDK/Public/Models/POBSegment.cs | 123 + OpenWrapSDK/Public/Models/POBSegment.cs.meta | 11 + OpenWrapSDK/Public/Models/POBUserInfo.cs | 334 +++ OpenWrapSDK/Public/Models/POBUserInfo.cs.meta | 11 + OpenWrapSDK/Public/POBOpenWrapSDK.cs | 377 +++ OpenWrapSDK/Public/POBOpenWrapSDK.cs.meta | 11 + PlayServicesResolver.meta | 8 + PlayServicesResolver/Editor.meta | 8 + .../play-services-resolver_v1.2.137.0.txt | 2 + ...play-services-resolver_v1.2.137.0.txt.meta | 12 + README.md | 31 + README.md.meta | 7 + package.json | 19 + package.json.meta | 7 + 627 files changed, 46921 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 Amazon.meta create mode 100644 Amazon/Amazon.asmdef create mode 100644 Amazon/Amazon.asmdef.meta create mode 100644 Amazon/Plugins.meta create mode 100644 Amazon/Plugins/iOS.meta create mode 100644 Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec create mode 100644 Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec.meta create mode 100644 Amazon/Plugins/iOS/AmazonBinding.m create mode 100644 Amazon/Plugins/iOS/AmazonBinding.m.meta create mode 100755 Amazon/Plugins/iOS/AmazonManager.h create mode 100644 Amazon/Plugins/iOS/AmazonManager.h.meta create mode 100644 Amazon/Plugins/iOS/AmazonManager.mm create mode 100644 Amazon/Plugins/iOS/AmazonManager.mm.meta create mode 100755 Amazon/Plugins/iOS/AmazonUnityCallback.h create mode 100644 Amazon/Plugins/iOS/AmazonUnityCallback.h.meta create mode 100644 Amazon/Plugins/iOS/AmazonUnityCallback.mm create mode 100644 Amazon/Plugins/iOS/AmazonUnityCallback.mm.meta create mode 100755 Amazon/Plugins/iOS/DTBBannerDelegate.h create mode 100644 Amazon/Plugins/iOS/DTBBannerDelegate.h.meta create mode 100644 Amazon/Plugins/iOS/DTBBannerDelegate.mm create mode 100644 Amazon/Plugins/iOS/DTBBannerDelegate.mm.meta create mode 100755 Amazon/Plugins/iOS/DTBInterstitialDelegate.h create mode 100644 Amazon/Plugins/iOS/DTBInterstitialDelegate.h.meta create mode 100644 Amazon/Plugins/iOS/DTBInterstitialDelegate.mm create mode 100644 Amazon/Plugins/iOS/DTBInterstitialDelegate.mm.meta create mode 100644 Amazon/Sample.meta create mode 100644 Amazon/Sample/APSMaxMediation.unity create mode 100644 Amazon/Sample/APSMaxMediation.unity.meta create mode 100644 Amazon/Sample/AmazonMaxDemo.cs create mode 100644 Amazon/Sample/AmazonMaxDemo.cs.meta create mode 100644 Amazon/Scripts.meta create mode 100644 Amazon/Scripts/Amazon.cs create mode 100644 Amazon/Scripts/Amazon.cs.meta create mode 100644 Amazon/Scripts/AmazonConstants.cs create mode 100644 Amazon/Scripts/AmazonConstants.cs.meta create mode 100644 Amazon/Scripts/Common.meta create mode 100644 Amazon/Scripts/Common/IAdInterstitial.cs create mode 100644 Amazon/Scripts/Common/IAdInterstitial.cs.meta create mode 100644 Amazon/Scripts/Common/IAdRequest.cs create mode 100644 Amazon/Scripts/Common/IAdRequest.cs.meta create mode 100644 Amazon/Scripts/Common/IAdSize.cs create mode 100644 Amazon/Scripts/Common/IAdSize.cs.meta create mode 100644 Amazon/Scripts/Common/IAdView.cs create mode 100644 Amazon/Scripts/Common/IAdView.cs.meta create mode 100644 Amazon/Scripts/Common/IFetchManager.cs create mode 100644 Amazon/Scripts/Common/IFetchManager.cs.meta create mode 100644 Amazon/Scripts/Common/ISlotGroup.cs create mode 100644 Amazon/Scripts/Common/ISlotGroup.cs.meta create mode 100644 Amazon/Scripts/Editor.meta create mode 100644 Amazon/Scripts/Editor/Amazon.Editor.asmdef create mode 100644 Amazon/Scripts/Editor/Amazon.Editor.asmdef.meta create mode 100644 Amazon/Scripts/Editor/AmazonAboutDialog.cs create mode 100644 Amazon/Scripts/Editor/AmazonAboutDialog.cs.meta create mode 100644 Amazon/Scripts/Editor/AmazonBuildScript.cs create mode 100644 Amazon/Scripts/Editor/AmazonBuildScript.cs.meta create mode 100644 Amazon/Scripts/Editor/AmazonCoroutineExtensions.cs create mode 100644 Amazon/Scripts/Editor/AmazonCoroutineExtensions.cs.meta create mode 100644 Amazon/Scripts/Editor/AmazonCoroutines.cs create mode 100644 Amazon/Scripts/Editor/AmazonCoroutines.cs.meta create mode 100644 Amazon/Scripts/Editor/AmazonDependencies.xml create mode 100644 Amazon/Scripts/Editor/AmazonDependencies.xml.meta create mode 100644 Amazon/Scripts/Editor/AmazonPostBuildiOS.cs create mode 100644 Amazon/Scripts/Editor/AmazonPostBuildiOS.cs.meta create mode 100644 Amazon/Scripts/Editor/AmazonSDKManager.cs create mode 100644 Amazon/Scripts/Editor/AmazonSDKManager.cs.meta create mode 100644 Amazon/Scripts/Editor/Tests.meta create mode 100644 Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs create mode 100644 Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs.meta create mode 100644 Amazon/Scripts/Editor/Tests/AmazonTest.cs create mode 100644 Amazon/Scripts/Editor/Tests/AmazonTest.cs.meta create mode 100644 Amazon/Scripts/Editor/Tests/AmazonUtilsTests.cs create mode 100644 Amazon/Scripts/Editor/Tests/AmazonUtilsTests.cs.meta create mode 100644 Amazon/Scripts/Internal.meta create mode 100644 Amazon/Scripts/Internal/APSAdDelegate.cs create mode 100644 Amazon/Scripts/Internal/APSAdDelegate.cs.meta create mode 100644 Amazon/Scripts/Internal/APSBannerAdRequest.cs create mode 100644 Amazon/Scripts/Internal/APSBannerAdRequest.cs.meta create mode 100644 Amazon/Scripts/Internal/APSInterstitialAdRequest.cs create mode 100644 Amazon/Scripts/Internal/APSInterstitialAdRequest.cs.meta create mode 100644 Amazon/Scripts/Internal/APSMediationUtils.cs create mode 100644 Amazon/Scripts/Internal/APSMediationUtils.cs.meta create mode 100644 Amazon/Scripts/Internal/APSVideoAdRequest.cs create mode 100644 Amazon/Scripts/Internal/APSVideoAdRequest.cs.meta create mode 100644 Amazon/Scripts/Internal/AdError.cs create mode 100644 Amazon/Scripts/Internal/AdError.cs.meta create mode 100644 Amazon/Scripts/Internal/AdInterstitial.cs create mode 100644 Amazon/Scripts/Internal/AdInterstitial.cs.meta create mode 100644 Amazon/Scripts/Internal/AdNetworkInfo.cs create mode 100644 Amazon/Scripts/Internal/AdNetworkInfo.cs.meta create mode 100644 Amazon/Scripts/Internal/AdRequest.cs create mode 100644 Amazon/Scripts/Internal/AdRequest.cs.meta create mode 100644 Amazon/Scripts/Internal/AdResponce.cs create mode 100644 Amazon/Scripts/Internal/AdResponce.cs.meta create mode 100644 Amazon/Scripts/Internal/AdResponse.cs create mode 100644 Amazon/Scripts/Internal/AdResponse.cs.meta create mode 100644 Amazon/Scripts/Internal/AdSize.cs create mode 100644 Amazon/Scripts/Internal/AdSize.cs.meta create mode 100644 Amazon/Scripts/Internal/AdView.cs create mode 100644 Amazon/Scripts/Internal/AdView.cs.meta create mode 100644 Amazon/Scripts/Internal/AmazonPackageConfig.cs create mode 100644 Amazon/Scripts/Internal/AmazonPackageConfig.cs.meta create mode 100644 Amazon/Scripts/Internal/AmazonUtils.cs create mode 100644 Amazon/Scripts/Internal/AmazonUtils.cs.meta create mode 100644 Amazon/Scripts/Internal/Android.meta create mode 100644 Amazon/Scripts/Internal/Android/AdRegistration.cs create mode 100644 Amazon/Scripts/Internal/Android/AdRegistration.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/AndroidAdInterstitial.cs create mode 100644 Amazon/Scripts/Internal/Android/AndroidAdInterstitial.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/AndroidAdResponce.cs create mode 100644 Amazon/Scripts/Internal/Android/AndroidAdResponce.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/AndroidAdResponse.cs create mode 100644 Amazon/Scripts/Internal/Android/AndroidAdResponse.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/AndroidAdView.cs create mode 100644 Amazon/Scripts/Internal/Android/AndroidAdView.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/AndroidPlatform.cs create mode 100644 Amazon/Scripts/Internal/Android/AndroidPlatform.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/DTBAdBannerListener.cs create mode 100644 Amazon/Scripts/Internal/Android/DTBAdBannerListener.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/DTBAdInterstitialListener.cs create mode 100644 Amazon/Scripts/Internal/Android/DTBAdInterstitialListener.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/DTBAdRequest.cs create mode 100644 Amazon/Scripts/Internal/Android/DTBAdRequest.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/DTBAdSize.cs create mode 100644 Amazon/Scripts/Internal/Android/DTBAdSize.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/DTBCallback.cs create mode 100644 Amazon/Scripts/Internal/Android/DTBCallback.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/DTBFetchFactory.cs create mode 100644 Amazon/Scripts/Internal/Android/DTBFetchFactory.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/DTBFetchManager.cs create mode 100644 Amazon/Scripts/Internal/Android/DTBFetchManager.cs.meta create mode 100644 Amazon/Scripts/Internal/Android/DTBSlotGroup.cs create mode 100644 Amazon/Scripts/Internal/Android/DTBSlotGroup.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS.meta create mode 100644 Amazon/Scripts/Internal/IOS/DTBAdBannerDispatcher.cs create mode 100644 Amazon/Scripts/Internal/IOS/DTBAdBannerDispatcher.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/DTBAdInterstitialDispatcher.cs create mode 100644 Amazon/Scripts/Internal/IOS/DTBAdInterstitialDispatcher.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/DTBAdRequest.cs create mode 100644 Amazon/Scripts/Internal/IOS/DTBAdRequest.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/DTBAdSize.cs create mode 100644 Amazon/Scripts/Internal/IOS/DTBAdSize.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/DTBCallback.cs create mode 100644 Amazon/Scripts/Internal/IOS/DTBCallback.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/DTBFetchManager.cs create mode 100644 Amazon/Scripts/Internal/IOS/DTBFetchManager.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs create mode 100644 Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/Externs.cs create mode 100644 Amazon/Scripts/Internal/IOS/Externs.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/IOSAdInterstitial.cs create mode 100644 Amazon/Scripts/Internal/IOS/IOSAdInterstitial.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/IOSAdResponce.cs create mode 100644 Amazon/Scripts/Internal/IOS/IOSAdResponce.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/IOSAdResponse.cs create mode 100644 Amazon/Scripts/Internal/IOS/IOSAdResponse.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/IOSAdView.cs create mode 100644 Amazon/Scripts/Internal/IOS/IOSAdView.cs.meta create mode 100644 Amazon/Scripts/Internal/IOS/IOSPlatform.cs create mode 100644 Amazon/Scripts/Internal/IOS/IOSPlatform.cs.meta create mode 100644 Amazon/Scripts/Internal/MiniJSON.cs create mode 100644 Amazon/Scripts/Internal/MiniJSON.cs.meta create mode 100644 Amazon/Scripts/Internal/PlatformApi.cs create mode 100644 Amazon/Scripts/Internal/PlatformApi.cs.meta create mode 100644 Amazon/Scripts/Internal/SlotGroup.cs create mode 100644 Amazon/Scripts/Internal/SlotGroup.cs.meta create mode 100644 Amazon/Scripts/Mediations.meta create mode 100644 Amazon/Scripts/Mediations/AppLovinMediation.meta create mode 100644 Amazon/Scripts/Mediations/AppLovinMediation/Editor.meta create mode 100644 Amazon/Scripts/Mediations/AppLovinMediation/Editor/APSAppLovinPackageConfig.cs create mode 100644 Amazon/Scripts/Mediations/AppLovinMediation/Editor/APSAppLovinPackageConfig.cs.meta create mode 100644 Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml create mode 100644 Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml.meta create mode 100644 Editor.meta create mode 100644 Editor/CodeMods.meta create mode 100644 Editor/CodeMods/AmazonMod.cs create mode 100644 Editor/CodeMods/AmazonMod.cs.meta create mode 100644 Editor/CodeMods/ApplovinMod.cs create mode 100644 Editor/CodeMods/ApplovinMod.cs.meta create mode 100644 Editor/CodeMods/GuruMaxCodeFixer.cs create mode 100644 Editor/CodeMods/GuruMaxCodeFixer.cs.meta create mode 100644 Editor/CodeMods/GuruModifier.cs create mode 100644 Editor/CodeMods/GuruModifier.cs.meta create mode 100644 Editor/CodeMods/PubmaticMod.cs create mode 100644 Editor/CodeMods/PubmaticMod.cs.meta create mode 100644 Editor/EasyGUILayout.cs create mode 100644 Editor/EasyGUILayout.cs.meta create mode 100644 Editor/EditorExtention.cs create mode 100644 Editor/EditorExtention.cs.meta create mode 100644 Editor/GuruEditorMax.asmdef create mode 100644 Editor/GuruEditorMax.asmdef.meta create mode 100644 Editor/GuruEditorMax.meta create mode 100644 Editor/GuruEditorMax/GuruMaxIntegrationManager.cs create mode 100644 Editor/GuruEditorMax/GuruMaxIntegrationManager.cs.meta create mode 100644 Editor/GuruEditorMax/GuruMaxMenuItems.cs create mode 100644 Editor/GuruEditorMax/GuruMaxMenuItems.cs.meta create mode 100644 Editor/GuruEditorMax/GuruMaxSdkAPI.cs create mode 100644 Editor/GuruEditorMax/GuruMaxSdkAPI.cs.meta create mode 100644 Editor/IFileIO.cs create mode 100644 Editor/IFileIO.cs.meta create mode 100644 Editor/Test.meta create mode 100644 Editor/Test/GuruMaxTest.cs create mode 100644 Editor/Test/GuruMaxTest.cs.meta create mode 100644 GuruMax.asmdef create mode 100644 GuruMax.asmdef.meta create mode 100644 MaxSdk.meta create mode 100644 MaxSdk/AppLovin.meta create mode 100644 MaxSdk/AppLovin/Editor.meta create mode 100644 MaxSdk/AppLovin/Editor/Dependencies.xml create mode 100644 MaxSdk/AppLovin/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/AppLovin/Plugins.meta create mode 100644 MaxSdk/AppLovin/Plugins/Android.meta create mode 100644 MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar create mode 100644 MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta create mode 100644 MaxSdk/AppLovin/Plugins/iOS.meta create mode 100644 MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h create mode 100644 MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta create mode 100644 MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m create mode 100644 MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta create mode 100644 MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm create mode 100644 MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta create mode 100644 MaxSdk/MaxSdk.asmdef create mode 100644 MaxSdk/MaxSdk.asmdef.meta create mode 100644 MaxSdk/Mediation.meta create mode 100644 MaxSdk/Mediation/BidMachine.meta create mode 100644 MaxSdk/Mediation/BidMachine/Editor.meta create mode 100644 MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/ByteDance.meta create mode 100644 MaxSdk/Mediation/ByteDance/Editor.meta create mode 100644 MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/Chartboost.meta create mode 100644 MaxSdk/Mediation/Chartboost/Editor.meta create mode 100644 MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/Facebook.meta create mode 100644 MaxSdk/Mediation/Facebook/Editor.meta create mode 100644 MaxSdk/Mediation/Facebook/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Facebook/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/Fyber.meta create mode 100644 MaxSdk/Mediation/Fyber/Editor.meta create mode 100644 MaxSdk/Mediation/Fyber/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Fyber/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/Google.meta create mode 100644 MaxSdk/Mediation/Google/Editor.meta create mode 100644 MaxSdk/Mediation/Google/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Google/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/GoogleAdManager.meta create mode 100644 MaxSdk/Mediation/GoogleAdManager/Editor.meta create mode 100644 MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/HyprMX.meta create mode 100644 MaxSdk/Mediation/HyprMX/Editor.meta create mode 100644 MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/InMobi.meta create mode 100644 MaxSdk/Mediation/InMobi/Editor.meta create mode 100644 MaxSdk/Mediation/InMobi/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/InMobi/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/IronSource.meta create mode 100644 MaxSdk/Mediation/IronSource/Editor.meta create mode 100644 MaxSdk/Mediation/IronSource/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/IronSource/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/MediationAdapters.txt create mode 100644 MaxSdk/Mediation/MediationAdapters.txt.meta create mode 100644 MaxSdk/Mediation/Mintegral.meta create mode 100644 MaxSdk/Mediation/Mintegral/Editor.meta create mode 100644 MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/MobileFuse.meta create mode 100644 MaxSdk/Mediation/MobileFuse/Editor.meta create mode 100644 MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/OguryPresage.meta create mode 100644 MaxSdk/Mediation/OguryPresage/Editor.meta create mode 100644 MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/Smaato.meta create mode 100644 MaxSdk/Mediation/Smaato/Editor.meta create mode 100644 MaxSdk/Mediation/Smaato/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Smaato/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/UnityAds.meta create mode 100644 MaxSdk/Mediation/UnityAds/Editor.meta create mode 100644 MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/Verve.meta create mode 100644 MaxSdk/Mediation/Verve/Editor.meta create mode 100644 MaxSdk/Mediation/Verve/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Verve/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/Vungle.meta create mode 100644 MaxSdk/Mediation/Vungle/Editor.meta create mode 100644 MaxSdk/Mediation/Vungle/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Vungle/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Mediation/Yandex.meta create mode 100644 MaxSdk/Mediation/Yandex/Editor.meta create mode 100644 MaxSdk/Mediation/Yandex/Editor/Dependencies.xml create mode 100644 MaxSdk/Mediation/Yandex/Editor/Dependencies.xml.meta create mode 100644 MaxSdk/Prefabs.meta create mode 100644 MaxSdk/Prefabs/BannerBottom.prefab create mode 100644 MaxSdk/Prefabs/BannerBottom.prefab.meta create mode 100644 MaxSdk/Prefabs/BannerTop.prefab create mode 100644 MaxSdk/Prefabs/BannerTop.prefab.meta create mode 100644 MaxSdk/Prefabs/Interstitial.prefab create mode 100644 MaxSdk/Prefabs/Interstitial.prefab.meta create mode 100644 MaxSdk/Prefabs/Rewarded.prefab create mode 100644 MaxSdk/Prefabs/Rewarded.prefab.meta create mode 100644 MaxSdk/README.md create mode 100644 MaxSdk/README.md.meta create mode 100644 MaxSdk/Resources.meta create mode 100644 MaxSdk/Resources/Images.meta create mode 100644 MaxSdk/Resources/Images/alert_icon.png create mode 100644 MaxSdk/Resources/Images/alert_icon.png.meta create mode 100755 MaxSdk/Resources/Images/uninstall_icon.png create mode 100644 MaxSdk/Resources/Images/uninstall_icon.png.meta create mode 100644 MaxSdk/Resources/Images/warning_icon.png create mode 100644 MaxSdk/Resources/Images/warning_icon.png.meta create mode 100644 MaxSdk/Scripts.meta create mode 100644 MaxSdk/Scripts/Editor.meta create mode 100644 MaxSdk/Scripts/Editor/MaxInitialization.cs create mode 100644 MaxSdk/Scripts/Editor/MaxInitialization.cs.meta create mode 100644 MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs create mode 100644 MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs.meta create mode 100644 MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs create mode 100644 MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs.meta create mode 100644 MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef create mode 100644 MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef.meta create mode 100644 MaxSdk/Scripts/IntegrationManager.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef create mode 100644 MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta create mode 100644 MaxSdk/Scripts/MaxEventSystemChecker.cs create mode 100644 MaxSdk/Scripts/MaxEventSystemChecker.cs.meta create mode 100644 MaxSdk/Scripts/MaxEvents.cs create mode 100644 MaxSdk/Scripts/MaxEvents.cs.meta create mode 100644 MaxSdk/Scripts/MaxSdk.Scripts.asmdef create mode 100644 MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta create mode 100644 MaxSdk/Scripts/MaxSdk.cs create mode 100644 MaxSdk/Scripts/MaxSdk.cs.meta create mode 100644 MaxSdk/Scripts/MaxSdkAndroid.cs create mode 100644 MaxSdk/Scripts/MaxSdkAndroid.cs.meta create mode 100644 MaxSdk/Scripts/MaxSdkBase.cs create mode 100644 MaxSdk/Scripts/MaxSdkBase.cs.meta create mode 100644 MaxSdk/Scripts/MaxSdkCallbacks.cs create mode 100644 MaxSdk/Scripts/MaxSdkCallbacks.cs.meta create mode 100644 MaxSdk/Scripts/MaxSdkLogger.cs create mode 100644 MaxSdk/Scripts/MaxSdkLogger.cs.meta create mode 100644 MaxSdk/Scripts/MaxSdkUnityEditor.cs create mode 100644 MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta create mode 100644 MaxSdk/Scripts/MaxSdkUtils.cs create mode 100644 MaxSdk/Scripts/MaxSdkUtils.cs.meta create mode 100644 MaxSdk/Scripts/MaxSdkiOS.cs create mode 100644 MaxSdk/Scripts/MaxSdkiOS.cs.meta create mode 100644 MaxSdk/Scripts/MaxTargetingData.cs create mode 100644 MaxSdk/Scripts/MaxTargetingData.cs.meta create mode 100644 MaxSdk/Scripts/MaxUserSegment.cs create mode 100644 MaxSdk/Scripts/MaxUserSegment.cs.meta create mode 100644 MaxSdk/Scripts/MaxUserServiceAndroid.cs create mode 100644 MaxSdk/Scripts/MaxUserServiceAndroid.cs.meta create mode 100644 MaxSdk/Scripts/MaxUserServiceUnityEditor.cs create mode 100644 MaxSdk/Scripts/MaxUserServiceUnityEditor.cs.meta create mode 100644 MaxSdk/Scripts/MaxUserServiceiOS.cs create mode 100644 MaxSdk/Scripts/MaxUserServiceiOS.cs.meta create mode 100644 MaxSdk/Scripts/MaxVariableServiceAndroid.cs create mode 100644 MaxSdk/Scripts/MaxVariableServiceAndroid.cs.meta create mode 100644 MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs create mode 100644 MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs.meta create mode 100644 MaxSdk/Scripts/MaxVariableServiceiOS.cs create mode 100644 MaxSdk/Scripts/MaxVariableServiceiOS.cs.meta create mode 100644 MaxSdk/Scripts/ThirdParty.meta create mode 100644 MaxSdk/Scripts/ThirdParty/MiniJSON.cs create mode 100644 MaxSdk/Scripts/ThirdParty/MiniJSON.cs.meta create mode 100644 MaxSdk/Version.md create mode 100644 MaxSdk/Version.md.meta create mode 100644 Moloco.meta create mode 100644 Moloco/Editor.meta create mode 100644 Moloco/Editor/ALMolocoAdapterDependencies.xml create mode 100644 Moloco/Editor/ALMolocoAdapterDependencies.xml.meta create mode 100644 Moloco/Moloco.asmdef create mode 100644 Moloco/Moloco.asmdef.meta create mode 100644 Moloco/Scripts.meta create mode 100644 Moloco/Scripts/Editor.meta create mode 100644 Moloco/Scripts/Editor/Moloco.Editor.asmdef create mode 100644 Moloco/Scripts/Editor/Moloco.Editor.asmdef.meta create mode 100644 Moloco/Scripts/Editor/MolocoPostProcessBuildiOS.cs create mode 100644 Moloco/Scripts/Editor/MolocoPostProcessBuildiOS.cs.meta create mode 100644 Moloco/Scripts/Editor/PodfileEditor.cs create mode 100644 Moloco/Scripts/Editor/PodfileEditor.cs.meta create mode 100644 OpenWrapSDK.meta create mode 100644 OpenWrapSDK/Editor.meta create mode 100644 OpenWrapSDK/Editor/OpenWrapSDK.Editor.asmdef create mode 100644 OpenWrapSDK/Editor/OpenWrapSDK.Editor.asmdef.meta create mode 100644 OpenWrapSDK/Editor/OpenWrapSDKDependencies.xml create mode 100644 OpenWrapSDK/Editor/OpenWrapSDKDependencies.xml.meta create mode 100644 OpenWrapSDK/Editor/OpenWrapSDKSKAdNetworkIDs.xml create mode 100644 OpenWrapSDK/Editor/OpenWrapSDKSKAdNetworkIDs.xml.meta create mode 100644 OpenWrapSDK/Editor/POBATTPostProcessBuild.cs create mode 100644 OpenWrapSDK/Editor/POBATTPostProcessBuild.cs.meta create mode 100644 OpenWrapSDK/Editor/POBPlistProcessor.cs create mode 100644 OpenWrapSDK/Editor/POBPlistProcessor.cs.meta create mode 100644 OpenWrapSDK/Editor/POBPostProcessBuildiOS.cs create mode 100644 OpenWrapSDK/Editor/POBPostProcessBuildiOS.cs.meta create mode 100644 OpenWrapSDK/Mediation.meta create mode 100644 OpenWrapSDK/Mediation/AppLovinMAX.meta create mode 100644 OpenWrapSDK/Mediation/AppLovinMAX/Editor.meta create mode 100644 OpenWrapSDK/Mediation/AppLovinMAX/Editor/ALOpenWrapMediationDependencies.xml create mode 100644 OpenWrapSDK/Mediation/AppLovinMAX/Editor/ALOpenWrapMediationDependencies.xml.meta create mode 100644 OpenWrapSDK/Mediation/AppLovinMAX/POBMAXConstants.cs create mode 100644 OpenWrapSDK/Mediation/AppLovinMAX/POBMAXConstants.cs.meta create mode 100644 OpenWrapSDK/Mediation/AppLovinMAX/POBMAXUtil.cs create mode 100644 OpenWrapSDK/Mediation/AppLovinMAX/POBMAXUtil.cs.meta create mode 100644 OpenWrapSDK/OpenWrapSDK.asmdef create mode 100644 OpenWrapSDK/OpenWrapSDK.asmdef.meta create mode 100644 OpenWrapSDK/Platform.meta create mode 100644 OpenWrapSDK/Platform/Android.meta create mode 100644 OpenWrapSDK/Platform/Android/Ads.meta create mode 100644 OpenWrapSDK/Platform/Android/Ads/POBBannerViewClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Ads/POBBannerViewClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Ads/POBInterstitialClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Ads/POBInterstitialClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Ads/POBRewardedAdClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Ads/POBRewardedAdClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Models.meta create mode 100644 OpenWrapSDK/Platform/Android/Models/POBBidClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Models/POBBidClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Models/POBDataProviderClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Models/POBDataProviderClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Models/POBExternalUserIdClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Models/POBExternalUserIdClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Models/POBImpressionClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Models/POBImpressionClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Models/POBRequestClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Models/POBRequestClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Models/POBRewardClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Models/POBRewardClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Models/POBSegmentClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Models/POBSegmentClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Models/POBUserInfoClient.cs create mode 100644 OpenWrapSDK/Platform/Android/Models/POBUserInfoClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/OpenWrapSDKClient.cs create mode 100644 OpenWrapSDK/Platform/Android/OpenWrapSDKClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/POBConstants.cs create mode 100644 OpenWrapSDK/Platform/Android/POBConstants.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Utils.meta create mode 100644 OpenWrapSDK/Platform/Android/Utils/POBAndroidUtils.cs create mode 100644 OpenWrapSDK/Platform/Android/Utils/POBAndroidUtils.cs.meta create mode 100644 OpenWrapSDK/Platform/Android/Utils/POBEventsDispatcher.cs create mode 100644 OpenWrapSDK/Platform/Android/Utils/POBEventsDispatcher.cs.meta create mode 100644 OpenWrapSDK/Platform/Common.meta create mode 100644 OpenWrapSDK/Platform/Common/Interfaces.meta create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBBannerViewClient.cs create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBBannerViewClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBDataProviderClient.cs create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBDataProviderClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBExternalUserIdClient.cs create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBExternalUserIdClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBInterstitialClient.cs create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBInterstitialClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBRewardedAdClient.cs create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBRewardedAdClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBSegmentClient.cs create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBSegmentClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBUserInfoClient.cs create mode 100644 OpenWrapSDK/Platform/Common/Interfaces/IPOBUserInfoClient.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/Logger.meta create mode 100644 OpenWrapSDK/Platform/Common/Logger/POBLog.cs create mode 100644 OpenWrapSDK/Platform/Common/Logger/POBLog.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/POBLogStrings.cs create mode 100644 OpenWrapSDK/Platform/Common/POBLogStrings.cs.meta create mode 100644 OpenWrapSDK/Platform/Common/Utils.meta create mode 100644 OpenWrapSDK/Platform/Common/Utils/POBUtils.cs create mode 100644 OpenWrapSDK/Platform/Common/Utils/POBUtils.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS.meta create mode 100644 OpenWrapSDK/Platform/iOS/Ads.meta create mode 100644 OpenWrapSDK/Platform/iOS/Ads/POBBannerViewClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Ads/POBBannerViewClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Ads/POBInterstitialClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Ads/POBInterstitialClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Ads/POBRewardedAdClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Ads/POBRewardedAdClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBBidClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBBidClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBDataProviderClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBDataProviderClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBExternalUserIdClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBExternalUserIdClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBImpressionClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBImpressionClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBRequestClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBRequestClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBRewardClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBRewardClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBSegmentClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBSegmentClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBUserInfoClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/Models/POBUserInfoClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/OpenWrapSDKClient.cs create mode 100644 OpenWrapSDK/Platform/iOS/OpenWrapSDKClient.cs.meta create mode 100644 OpenWrapSDK/Platform/iOS/Utils.meta create mode 100644 OpenWrapSDK/Platform/iOS/Utils/POBIOSUtils.cs create mode 100644 OpenWrapSDK/Platform/iOS/Utils/POBIOSUtils.cs.meta create mode 100644 OpenWrapSDK/Plugins.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/Android.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/Android/openwrap-sdk-unity.aar create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/Android/openwrap-sdk-unity.aar.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Banner.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Banner/POBUBannerView.h create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Banner/POBUBannerView.h.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Banner/POBUBannerView.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Banner/POBUBannerView.m.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUAdsCacheManager.h create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUAdsCacheManager.h.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUAdsCacheManager.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUAdsCacheManager.m.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUUIUtil.h create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUUIUtil.h.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUUIUtil.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUUIUtil.m.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUUtil.h create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUUtil.h.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUUtil.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Helper/POBUUtil.m.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Interstitial.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Interstitial/POBUInterstitial.h create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Interstitial/POBUInterstitial.h.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Interstitial/POBUInterstitial.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Interstitial/POBUInterstitial.m.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Mediation.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Mediation/POBMAXUInterface.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Mediation/POBMAXUInterface.m.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/POBUConstants.h create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/POBUConstants.h.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/POBUInterface.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/POBUInterface.m.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/POBUModelsInterface.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/POBUModelsInterface.m.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/POBUTypes.h create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/POBUTypes.h.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Rewarded.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Rewarded/POBURewardedAd.h create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Rewarded/POBURewardedAd.h.meta create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Rewarded/POBURewardedAd.m create mode 100644 OpenWrapSDK/Plugins/OpenWrapSDK/iOS/Rewarded/POBURewardedAd.m.meta create mode 100644 OpenWrapSDK/Public.meta create mode 100644 OpenWrapSDK/Public/Ads.meta create mode 100644 OpenWrapSDK/Public/Ads/POBBannerView.cs create mode 100644 OpenWrapSDK/Public/Ads/POBBannerView.cs.meta create mode 100644 OpenWrapSDK/Public/Ads/POBInterstitial.cs create mode 100644 OpenWrapSDK/Public/Ads/POBInterstitial.cs.meta create mode 100644 OpenWrapSDK/Public/Ads/POBRewardedAd.cs create mode 100644 OpenWrapSDK/Public/Ads/POBRewardedAd.cs.meta create mode 100644 OpenWrapSDK/Public/Enums.meta create mode 100644 OpenWrapSDK/Public/Enums/POBAdPosition.cs create mode 100644 OpenWrapSDK/Public/Enums/POBAdPosition.cs.meta create mode 100644 OpenWrapSDK/Public/Enums/POBBannerPosition.cs create mode 100644 OpenWrapSDK/Public/Enums/POBBannerPosition.cs.meta create mode 100644 OpenWrapSDK/Public/Enums/POBLocSource.cs create mode 100644 OpenWrapSDK/Public/Enums/POBLocSource.cs.meta create mode 100644 OpenWrapSDK/Public/Enums/POBSDKLogLevel.cs create mode 100644 OpenWrapSDK/Public/Enums/POBSDKLogLevel.cs.meta create mode 100644 OpenWrapSDK/Public/Interfaces.meta create mode 100644 OpenWrapSDK/Public/Interfaces/IPOBBid.cs create mode 100644 OpenWrapSDK/Public/Interfaces/IPOBBid.cs.meta create mode 100644 OpenWrapSDK/Public/Interfaces/IPOBImpression.cs create mode 100644 OpenWrapSDK/Public/Interfaces/IPOBImpression.cs.meta create mode 100644 OpenWrapSDK/Public/Interfaces/IPOBRequest.cs create mode 100644 OpenWrapSDK/Public/Interfaces/IPOBRequest.cs.meta create mode 100644 OpenWrapSDK/Public/Interfaces/IPOBReward.cs create mode 100644 OpenWrapSDK/Public/Interfaces/IPOBReward.cs.meta create mode 100644 OpenWrapSDK/Public/Models.meta create mode 100644 OpenWrapSDK/Public/Models/POBAdSize.cs create mode 100644 OpenWrapSDK/Public/Models/POBAdSize.cs.meta create mode 100644 OpenWrapSDK/Public/Models/POBApplicationInfo.cs create mode 100644 OpenWrapSDK/Public/Models/POBApplicationInfo.cs.meta create mode 100644 OpenWrapSDK/Public/Models/POBDataProvider.cs create mode 100644 OpenWrapSDK/Public/Models/POBDataProvider.cs.meta create mode 100644 OpenWrapSDK/Public/Models/POBErrorEventArgs.cs create mode 100644 OpenWrapSDK/Public/Models/POBErrorEventArgs.cs.meta create mode 100644 OpenWrapSDK/Public/Models/POBExternalUserId.cs create mode 100644 OpenWrapSDK/Public/Models/POBExternalUserId.cs.meta create mode 100644 OpenWrapSDK/Public/Models/POBRewardEventArgs.cs create mode 100644 OpenWrapSDK/Public/Models/POBRewardEventArgs.cs.meta create mode 100644 OpenWrapSDK/Public/Models/POBSegment.cs create mode 100644 OpenWrapSDK/Public/Models/POBSegment.cs.meta create mode 100644 OpenWrapSDK/Public/Models/POBUserInfo.cs create mode 100644 OpenWrapSDK/Public/Models/POBUserInfo.cs.meta create mode 100644 OpenWrapSDK/Public/POBOpenWrapSDK.cs create mode 100644 OpenWrapSDK/Public/POBOpenWrapSDK.cs.meta create mode 100644 PlayServicesResolver.meta create mode 100644 PlayServicesResolver/Editor.meta create mode 100755 PlayServicesResolver/Editor/play-services-resolver_v1.2.137.0.txt create mode 100644 PlayServicesResolver/Editor/play-services-resolver_v1.2.137.0.txt.meta create mode 100644 README.md create mode 100644 README.md.meta create mode 100644 package.json create mode 100644 package.json.meta diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6c2593 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Mac auto-generated system files +*.DS_Store* diff --git a/Amazon.meta b/Amazon.meta new file mode 100644 index 0000000..26d47c3 --- /dev/null +++ b/Amazon.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 474c0b17d00314c9d8b205e3c753661e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Amazon.asmdef b/Amazon/Amazon.asmdef new file mode 100644 index 0000000..04ce4ba --- /dev/null +++ b/Amazon/Amazon.asmdef @@ -0,0 +1,17 @@ +{ + "name": "Amazon", + "rootNamespace": "", + "references": [ + "MaxSdk", + "MaxSdk.Scripts" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Amazon/Amazon.asmdef.meta b/Amazon/Amazon.asmdef.meta new file mode 100644 index 0000000..21c5dc9 --- /dev/null +++ b/Amazon/Amazon.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6beff6c8cf8014e6084bc2f82cc4cef0 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins.meta b/Amazon/Plugins.meta new file mode 100644 index 0000000..9f247f9 --- /dev/null +++ b/Amazon/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c161f427aca604d4d81f018fddaae5d2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS.meta b/Amazon/Plugins/iOS.meta new file mode 100644 index 0000000..103e0d1 --- /dev/null +++ b/Amazon/Plugins/iOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fd97fc7641615462abc63e027208b9a2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec b/Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec new file mode 100644 index 0000000..c7e21c1 --- /dev/null +++ b/Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = 'Amazon-SDK-Plugin' + s.version = '5.12.1' + s.summary = 'Unity wrapper for APS iOS SDK' + s.homepage = 'https://github.com/amazon/amazon-unity-sdk' + s.license = { :type => 'Amazon', :file => 'APS_IOS_SDK-4.4.1/LICENSE.txt' } + s.author = { 'Amazon' => 'aps-github@amazon.com' } + s.ios.deployment_target = '12.5' + s.source = { :tag => "v#{s.version}" } + s.source_files = '*.{h,m,mm}' + + s.dependency 'AmazonPublisherServicesSDK' + s.pod_target_xcconfig = { + 'OTHER_CPLUSPLUSFLAGS' => '-fcxx-modules', + } +end diff --git a/Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec.meta b/Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec.meta new file mode 100644 index 0000000..2ab557c --- /dev/null +++ b/Amazon/Plugins/iOS/Amazon-SDK-Plugin.podspec.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ce7a667caa6f64752b219fe8edd61617 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/AmazonBinding.m b/Amazon/Plugins/iOS/AmazonBinding.m new file mode 100644 index 0000000..eb30853 --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonBinding.m @@ -0,0 +1,283 @@ +#import "AmazonManager.h" +#import "AmazonUnityCallback.h" +#import "DTBBannerDelegate.h" +#import "DTBInterstitialDelegate.h" + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - Helpers + +// Converts C style string to NSString +#define GetStringParam(_x_) ((_x_) != NULL ? [NSString stringWithUTF8String:_x_] : [NSString stringWithUTF8String:""]) +#define GetNullableStringParam(_x_) ((_x_) != NULL ? [NSString stringWithUTF8String:_x_] : nil) + +static char* amazonStringCopy(NSString* input) +{ + const char* string = [input UTF8String]; + return string ? strdup(string) : NULL; +} + +void _amazonInitialize(const char* appKey) +{ + [[AmazonManager sharedManager] initialize:GetStringParam(appKey)]; +} + +bool _amazonIsInitialized(){ + return [[AmazonManager sharedManager] isInitialized]; +} + +void _amazonSetUseGeoLocation(bool flag){ + [[AmazonManager sharedManager] setUseGeoLocation:flag]; +} + +bool _amazonGetUseGeoLocation(){ + return [[AmazonManager sharedManager] getUseGeoLocation]; +} + +void _amazonSetLogLevel(int logLevel){ + [[AmazonManager sharedManager] setLogLevel:logLevel]; +} + +bool _amazonGetLogLevel(){ + return [[AmazonManager sharedManager] getLogLevel]; +} + +void _amazonSetTestMode(bool flag){ + [[AmazonManager sharedManager] setTestMode:flag]; +} + +bool _amazonIsTestModeEnabled(){ + return [[AmazonManager sharedManager] isTestModeEnabled]; +} + +DTBAdSize* _createBannerAdSize(int width, int height, const char* uuid){ + return [[AmazonManager sharedManager] createBannerAdSize:width height:height uuid:GetStringParam(uuid)]; +} +DTBAdSize* _createVideoAdSize(int width, int height, const char* uuid){ + return [[AmazonManager sharedManager] createVideoAdSize:width height:height uuid:GetStringParam(uuid)]; +} + +DTBAdSize* _createInterstitialAdSize(const char* uuid){ + return [[AmazonManager sharedManager] createInterstitialAdSize:GetStringParam(uuid)]; +} +DTBAdLoader* _createAdLoader(){ + return [[AmazonManager sharedManager]createAdLoader]; +} + +void _setSizes(DTBAdLoader* adLoader, DTBAdSize* size){ + [[AmazonManager sharedManager]setSizes:adLoader size:size]; +} + +void _loadAd(DTBAdLoader* adLoader, AmazonUnityCallback* callback){ + [[AmazonManager sharedManager]loadAd:adLoader callback:callback]; +} +void _loadSmartBanner(DTBAdLoader* adLoader, AmazonUnityCallback* callback){ + [[AmazonManager sharedManager]loadSmartBanner:adLoader callback:callback]; +} +void _amazonSetMRAIDPolicy(int policy){ + [[AmazonManager sharedManager] setMRAIDPolicy:(DTBMRAIDPolicy)policy]; +} + +int _amazonGetMRAIDPolicy(){ + return [[AmazonManager sharedManager] getMRAIDPolicy]; +} + +void _amazonSetMRAIDSupportedVersions(const char* newVersion){ + [[AmazonManager sharedManager] setMRAIDSupportedVersions:GetStringParam(newVersion)]; +} + +void _amazonSetListeners(DTBAdCallbackClientRef* ptr, AmazonUnityCallback* callbackPtr, SuccessResponse onSuccessCallback, ErrorResponse onErrorCallback) { + [callbackPtr setListeners:ptr success:onSuccessCallback errorCallback:onErrorCallback]; +} + +void _amazonSetListenersWithInfo(DTBAdCallbackClientRef* ptr, AmazonUnityCallback* callbackPtr, SuccessResponse onSuccessCallback, ErrorResponseWithInfo onErrorCallbackWithInfo) { + [callbackPtr setListenersWithInfo:ptr success:onSuccessCallback errorCallbackWithInfo:onErrorCallbackWithInfo]; +} + +void _setBannerDelegate(DTBCallbackBannerRef* ptr, DTBBannerDelegate* callbackPtr, DTBAdDidLoadType adLoad, DTBAdFailedToLoadType adFailLoad, DTBBannerWillLeaveApplicationType leaveApp, DTBImpressionFiredType impFired) { + [callbackPtr setDelegate:ptr adLoad:adLoad adFailLoad:adFailLoad leaveApp:leaveApp impFired:impFired]; +} + +void _setInterstitialDelegate(DTBCallbackInterstitialRef* ptr, DTBInterstitialDelegate* callbackPtr, DTBInterstitialDidLoadType adLoad, DTBDidFailToLoadAdWithErrorCodeType adFailLoad, DTBInterstitialWillLeaveApplicationType leaveApp, DTBInterstitialImpressionFiredType impFired, DTBInterstitialDidPresentScreenType didOpen, DTBInterstitialDidDismissScreenType didDismiss) { + [callbackPtr setDelegate:ptr adLoad:adLoad adFailLoad:adFailLoad leaveApp:leaveApp impFired:impFired didOpen:didOpen didDismiss:didDismiss]; +} + +AmazonUnityCallback* _createCallback() { + return [[AmazonManager sharedManager] createCallback]; +} + +DTBBannerDelegate* _createBannerDelegate() { + return [[AmazonManager sharedManager] createBannerDelegate]; +} + +DTBInterstitialDelegate* _createInterstitialDelegate() { + return [[AmazonManager sharedManager] createInterstitialDelegate]; +} + +DTBFetchManager* _getFetchManager(int autoRefreshID, bool isSmartBanner){ + return [[AmazonManager sharedManager] getFetchManager:autoRefreshID isSmartBanner:isSmartBanner]; +} + +void _fetchManagerPop(DTBFetchManager* fetchManager){ + [[AmazonManager sharedManager] fetchManagerPop:fetchManager]; +} + +void _putCustomTarget(DTBAdLoader* adLoader, const char* key, const char* value){ + [[AmazonManager sharedManager] putCustomTarget:adLoader key:GetStringParam(key) value:GetStringParam(value)]; +} + +void _createFetchManager(DTBAdLoader* adLoader, bool isSmartBanner){ + [[AmazonManager sharedManager] createFetchManager:adLoader isSmartBanner:isSmartBanner]; +} + +void _startFetchManager(DTBFetchManager* fetchManager){ + [[AmazonManager sharedManager] startFetchManager:fetchManager]; +} + +void _stopFetchManager(DTBFetchManager* fetchManager){ + [[AmazonManager sharedManager] stopFetchManager:fetchManager]; +} + +bool _isEmptyFetchManager(DTBFetchManager* fetchManager){ + return [[AmazonManager sharedManager] isEmptyFetchManager:fetchManager]; +} + +void _destroyFetchManager(int autoRefreshID){ + [[AmazonManager sharedManager] destroyFetchManager:autoRefreshID]; +} + +void _setSlotGroup(DTBAdLoader* adLoader, const char* slotGroupName){ + [[AmazonManager sharedManager] setSlotGroup:adLoader slotGtoupName:GetStringParam(slotGroupName)]; +} + +DTBSlotGroup* _createSlotGroup(const char* slotGroupName){ + return [[AmazonManager sharedManager] createSlotGroup:GetStringParam(slotGroupName)]; +} + +void _addSlot(DTBSlotGroup* slot, DTBAdSize* size){ + [[AmazonManager sharedManager] addSlot:slot size:size]; +} + +void _addSlotGroup(DTBSlotGroup* slot){ + [[AmazonManager sharedManager] addSlotGroup:slot]; +} + +const char* _fetchMoPubKeywords(DTBAdResponse* response){ + return amazonStringCopy([[AmazonManager sharedManager] fetchMoPubKeywords:response]); +} + +const char* _fetchAmznSlots(DTBAdResponse* response){ + return amazonStringCopy([[AmazonManager sharedManager] fetchAmznSlots:response]); +} + +int _fetchAdHeight(DTBAdResponse* response){ + return [[AmazonManager sharedManager] fetchAdHeight:response]; +} + +int _fetchAdWidth(DTBAdResponse* response){ + return [[AmazonManager sharedManager] fetchAdWidth:response]; +} + +const char* _fetchMediationHints(DTBAdResponse* response, bool isSmartBanner){ + NSString* str = [[AmazonManager sharedManager] fetchMediationHints:response isSmart:isSmartBanner]; + return amazonStringCopy(str); +} + +void _setCMPFlavor (int cFlavor){ + [[AmazonManager sharedManager] setCMPFlavor:(DTBCMPFlavor)cFlavor]; +} + +void _setConsentStatus (int consentStatus){ + [[AmazonManager sharedManager] setConsentStatus:(DTBConsentStatus)consentStatus]; +} + +NSMutableArray* _createArray(){ + return [[AmazonManager sharedManager] createArray]; +} + +void _addToArray (NSMutableArray* dictionary, int item) { + [[AmazonManager sharedManager] addToArray:dictionary item:item]; +} + +void _setVendorList(NSMutableArray* dictionary){ + [[AmazonManager sharedManager] setVendorList:dictionary]; +} + +void _setAutoRefreshNoArgs(DTBAdLoader* adLoader){ + [[AmazonManager sharedManager] setAutoRefresh:adLoader]; +} + +void _setAutoRefresh(DTBAdLoader* adLoader, int secs){ + [[AmazonManager sharedManager] setAutoRefresh:adLoader secs:secs]; +} + +void _pauseAutoRefresh(DTBAdLoader* adLoader){ + [[AmazonManager sharedManager] pauseAutorefresh:adLoader]; +} + +void _stopAutoRefresh(DTBAdLoader* adLoader){ + [[AmazonManager sharedManager] stopAutoRefresh:adLoader]; +} + +void _resumeAutoRefresh(DTBAdLoader* adLoader){ + [[AmazonManager sharedManager] resumeAutoRefresh:adLoader]; +} + +void _setAPSPublisherExtendedIdFeatureEnabled(bool isEnabled) { + [[AmazonManager sharedManager] setAPSPublisherExtendedIdFeatureEnabled:isEnabled]; +} + +void _addCustomAttribute(const char *withKey, const void *value) { + [[AmazonManager sharedManager] addCustomAttribute:GetStringParam(withKey) value:GetStringParam(value)]; +} + +void _removeCustomAttribute(const char* forKey) { + [[AmazonManager sharedManager] removeCustomAttribute:GetStringParam(forKey)]; +} + +void _setAdNetworkInfo(int adNetworkId) { + DTBAdNetworkInfo *dtbAdNetworkInfo = [[DTBAdNetworkInfo alloc]initWithNetworkName:(DTBAdNetwork)adNetworkId]; + [[AmazonManager sharedManager] setAdNetworkInfo:dtbAdNetworkInfo]; +} + +void _setLocalExtras(const char *adUnitId, NSDictionary *localExtras) { + [DTBAds setLocalExtras:GetStringParam(adUnitId) localExtras:localExtras]; +} + +DTBAdBannerDispatcher* _createAdView(int width, int height, DTBBannerDelegate* delegate) { + CGRect rect = CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height); + return [[DTBAdBannerDispatcher alloc] initWithAdFrame:rect delegate:delegate]; +} + +DTBAdInterstitialDispatcher* _createAdInterstitial(DTBInterstitialDelegate* delegate) { + return [[DTBAdInterstitialDispatcher alloc] initWithDelegate:delegate]; +} + +void _fetchBannerAd(DTBAdBannerDispatcher* dispatcher, DTBAdResponse* adResponse) { + [dispatcher fetchBannerAdWithParameters:[adResponse mediationHints]]; +} + +void _fetchInterstitialAd(DTBAdInterstitialDispatcher* dispatcher, DTBAdResponse* adResponse) { + [dispatcher fetchAdWithParameters:[adResponse mediationHints]]; +} + +void _showInterstitial(DTBAdInterstitialDispatcher* dispatcher) { + [[AmazonManager sharedManager] showInterstitialAd:dispatcher]; +} + +NSDictionary* _getMediationHintsDict(DTBAdResponse* response, bool isSmartBanner){ + return [[AmazonManager sharedManager] getMediationHintsDict:response isSmart:isSmartBanner]; +} + +void _setRefreshFlag(DTBAdLoader* adLoader, bool flag) { + [adLoader setRefreshFlag:flag]; +} + +DTBAdLoader* _getAdLoaderFromResponse(DTBAdResponse* adResponse) { + return [adResponse getAdLoader]; +} + +DTBAdLoader* _getAdLoaderFromAdError(DTBAdErrorInfo* errorInfo) { + return [errorInfo getAdLoader]; +} + diff --git a/Amazon/Plugins/iOS/AmazonBinding.m.meta b/Amazon/Plugins/iOS/AmazonBinding.m.meta new file mode 100644 index 0000000..bd71100 --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonBinding.m.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: bc75c2542fbb6469798f0dc4baf0100e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/AmazonManager.h b/Amazon/Plugins/iOS/AmazonManager.h new file mode 100755 index 0000000..7735ac4 --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonManager.h @@ -0,0 +1,71 @@ +#import +#import + +#import +#import +#import +#import + +#import "AmazonUnityCallback.h" +#import "DTBBannerDelegate.h" +#import "DTBInterstitialDelegate.h" + +@interface AmazonManager: NSObject { } ++ (AmazonManager*)sharedManager; +- (void)initialize:(NSString*)keywords; +- (BOOL)isInitialized; +- (void)setUseGeoLocation:(bool)flag; +- (BOOL)getUseGeoLocation; +- (void)setLogLevel:(int)logLevel; +- (int)getLogLevel; +- (void)setTestMode:(bool)flag; +- (BOOL)isTestModeEnabled; +- (DTBAdSize*)createBannerAdSize:(int)width height:(int)height uuid:(NSString*)uuid; +- (DTBAdSize*)createVideoAdSize:(int)width height:(int)height uuid:(NSString*)uuid; +- (DTBAdSize*)createInterstitialAdSize:(NSString*)uuid; +- (DTBAdLoader*)createAdLoader; +- (void)setSizes:(DTBAdLoader*)adLoader size:(DTBAdSize*)size; +- (void)loadAd:(DTBAdLoader*)adLoader callback:(AmazonUnityCallback*)callback; +- (void)loadSmartBanner:(DTBAdLoader*)adLoader callback:(AmazonUnityCallback*)callback; +- (void)setMRAIDPolicy:(DTBMRAIDPolicy)policy; +- (int)getMRAIDPolicy; +- (void)setMRAIDSupportedVersions:(NSArray *)versions; +- (NSString*)jsonFromDict:(NSDictionary *)dict; +- (AmazonUnityCallback*)createCallback; +- (DTBBannerDelegate*)createBannerDelegate; +- (DTBInterstitialDelegate*)createInterstitialDelegate; +- (void)createFetchManager:(DTBAdLoader*)adLoader isSmartBanner:(BOOL)isSmartBanner; +- (DTBFetchManager*)getFetchManager:(int)slotType isSmartBanner:(BOOL)isSmartBanner; +-(void)fetchManagerPop:(DTBFetchManager*)fetchManager; +-(void)putCustomTarget:(DTBAdLoader*)adLoader key:(NSString*)key value:(NSString*)value; +-(void)startFetchManager:(DTBFetchManager*)fetchManager; +-(void)stopFetchManager:(DTBFetchManager*)fetchManager; +-(BOOL)isEmptyFetchManager:(DTBFetchManager*)fetchManager; +-(void)destroyFetchManager:(int)slotType; +-(void)setSlotGroup:(DTBAdLoader*)adLoader slotGtoupName:(NSString*)slotGtoupName; +-(DTBSlotGroup*)createSlotGroup:(NSString*)slotGroupName; +-(void)addSlot:(DTBSlotGroup*)slot size:(DTBAdSize*)size; +-(void)addSlotGroup:(DTBSlotGroup*)group; +-(NSString*)fetchMoPubKeywords:(DTBAdResponse*)response; +-(NSString*)fetchAmznSlots:(DTBAdResponse*)response; +-(int)fetchAdWidth:(DTBAdResponse*)response; +-(int)fetchAdHeight:(DTBAdResponse*)response; +-(NSString*)fetchMediationHints:(DTBAdResponse*)response isSmart:(BOOL)isSmart; +-(void)setCMPFlavor:(DTBCMPFlavor)cFlavor; +-(void)setConsentStatus:(DTBConsentStatus)consentStatus; +-(NSMutableArray*)createArray; +-(void)addToArray:(NSMutableArray*)dictionary item:(int)item; +-(void)setVendorList:(NSMutableArray*)dictionary; +-(void)setAutoRefresh:(DTBAdLoader*)adLoader; +-(void)setAutoRefresh:(DTBAdLoader*)adLoader secs:(int)secs; +-(void)pauseAutorefresh:(DTBAdLoader*)adLoader; +-(void)stopAutoRefresh:(DTBAdLoader*)adLoader; +-(void)resumeAutoRefresh:(DTBAdLoader*)adLoader; +-(void)setAPSPublisherExtendedIdFeatureEnabled:(BOOL)isEnabled; +-(void)addCustomAttribute:(NSString *)withKey value:(id)value; +-(void)removeCustomAttribute:(NSString *)forKey; +-(void)setAdNetworkInfo:(DTBAdNetworkInfo *)dtbAdNetworkInfo; +-(void)setLocalExtras:(NSString *)adUnitId localExtras:(NSDictionary *)localExtras; +-(NSDictionary *)getMediationHintsDict:(DTBAdResponse*)response isSmart:(BOOL)isSmart; +-(void)showInterstitialAd:(DTBAdInterstitialDispatcher*)dispatcher; +@end diff --git a/Amazon/Plugins/iOS/AmazonManager.h.meta b/Amazon/Plugins/iOS/AmazonManager.h.meta new file mode 100644 index 0000000..dd4b61d --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonManager.h.meta @@ -0,0 +1,89 @@ +fileFormatVersion: 2 +guid: 9d0a8448aa0c147e8a0225de1609f269 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/AmazonManager.mm b/Amazon/Plugins/iOS/AmazonManager.mm new file mode 100644 index 0000000..075dc1e --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonManager.mm @@ -0,0 +1,295 @@ +#import "AmazonManager.h" + +@implementation AmazonManager + +#pragma mark NSObject + ++ (AmazonManager*)sharedManager +{ + static AmazonManager* sharedManager = nil; + + if (!sharedManager) + sharedManager = [[AmazonManager alloc] init]; + + return sharedManager; +} + +- (void)initialize:(NSString*)keywords +{ + [[DTBAds sharedInstance] setAppKey: keywords]; +} + +- (BOOL)isInitialized +{ + return [[DTBAds sharedInstance] isReady]; +} + +- (void)setUseGeoLocation:(bool)flag +{ + [[DTBAds sharedInstance] setUseGeoLocation:flag]; +} + +- (BOOL)getUseGeoLocation +{ + return [[DTBAds sharedInstance] useGeoLocation]; +} + +- (void)setLogLevel:(int)logLevel +{ + DTBLogLevel level = (DTBLogLevel) logLevel; + [[DTBAds sharedInstance] setLogLevel:level]; +} + +- (int)getLogLevel +{ + return 0; +} + +- (void)setTestMode:(bool)flag +{ + [[DTBAds sharedInstance] setTestMode:flag]; +} + +- (BOOL)isTestModeEnabled +{ + return [[DTBAds sharedInstance] testMode]; +} + +- (DTBAdSize*)createBannerAdSize:(int)width height:(int)height uuid:(NSString*)uuid{ + return [[DTBAdSize alloc] initBannerAdSizeWithWidth:width height:height andSlotUUID:uuid]; +} + +- (DTBAdSize*)createVideoAdSize:(int)width height:(int)height uuid:(NSString*)uuid{ + return [[DTBAdSize alloc] initVideoAdSizeWithPlayerWidth:width height: height andSlotUUID: uuid];; +} + +- (DTBAdSize*)createInterstitialAdSize:(NSString*)uuid{ + return [[DTBAdSize alloc] initInterstitialAdSizeWithSlotUUID:uuid]; +} + +- (DTBAdLoader*)createAdLoader{ + return [DTBAdLoader new]; +} + +- (void)setSizes:(DTBAdLoader*)adLoader size:(DTBAdSize*)size{ + [adLoader setSizes:size, nil]; +} + +- (void)loadAd:(DTBAdLoader*)adLoader callback:(AmazonUnityCallback*)callback{ + [adLoader loadAd:callback]; +} + +- (void)loadSmartBanner:(DTBAdLoader*)adLoader callback:(AmazonUnityCallback*)callback{ + [adLoader loadSmartBanner:callback]; +} + +- (void)setMRAIDPolicy:(DTBMRAIDPolicy)policy +{ + [DTBAds sharedInstance].mraidPolicy = policy; +} + +- (int) getMRAIDPolicy{ + return [DTBAds sharedInstance].mraidPolicy; +} + +- (void)setMRAIDSupportedVersions:(NSString* _Nullable)versions +{ + [DTBAds sharedInstance].mraidCustomVersions = nil; +} + + +- (NSString *)jsonFromDict:(NSDictionary *)dict { + NSError *error; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict + options:0 + error:&error]; + if (!jsonData) { + NSLog(@"Error converting JSON from VCS response dict: %@", error); + return @""; + } else { + return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + } +} + +- (AmazonUnityCallback*)createCallback{ + AmazonUnityCallback* newCallback = [[AmazonUnityCallback alloc] init]; + return newCallback; +} + +- (DTBBannerDelegate*)createBannerDelegate{ + return [[DTBBannerDelegate alloc] init]; +} + +- (DTBInterstitialDelegate*)createInterstitialDelegate{ + return [[DTBInterstitialDelegate alloc] init]; +} + +- (void)createFetchManager:(DTBAdLoader*)adLoader isSmartBanner:(BOOL)isSmartBanner{ + NSError *error = [DTBFetchFactory.sharedInstance createFetchManagerForLoader:adLoader isSmartBanner:isSmartBanner]; + if(error == nil){ + NSLog(@"FetchManager created"); + } else { + NSLog(@"failed with error = %@", [error localizedDescription]); + } +} + +- (DTBFetchManager*)getFetchManager:(int)slotType isSmartBanner:(BOOL)isSmartBanner{ + if( !isSmartBanner ){ + return [[DTBFetchFactory sharedInstance] fetchManagerBySlotType:(DTBSlotType)slotType]; + }else { + return [[DTBFetchFactory sharedInstance] fetchManagerBySlotType:SLOT_SMART]; + } +} + +-(void)fetchManagerPop:(DTBFetchManager*)fetchManager{ + [fetchManager pop]; +} + +-(void)putCustomTarget:(DTBAdLoader*)adLoader key:(NSString*)key value:(NSString*)value{ + [adLoader putCustomTarget:value withKey:key]; +} + +-(void)startFetchManager:(DTBFetchManager*)fetchManager{ + [fetchManager start]; +} + +-(void)stopFetchManager:(DTBFetchManager*)fetchManager{ + [fetchManager stop]; +} + +-(BOOL)isEmptyFetchManager:(DTBFetchManager*)fetchManager{ + return [fetchManager isEmpty]; +} + +-(void)destroyFetchManager:(int)slotType{ + [[DTBFetchFactory sharedInstance] removeFetchManagerForSlotType:(DTBSlotType)slotType]; +} + +-(void)setSlotGroup:(DTBAdLoader*)adLoader slotGtoupName:(NSString*)slotGtoupName{ + [adLoader setSlotGroup:slotGtoupName]; +} + +-(DTBSlotGroup*)createSlotGroup:(NSString*)slotGroupName{ + DTBSlotGroup *group = [[DTBSlotGroup alloc] initWithName:slotGroupName]; + return group; +} + +-(void)addSlot:(DTBSlotGroup*)slot size:(DTBAdSize*)size{ + [slot addSize:size]; +} + +-(void)addSlotGroup:(DTBSlotGroup*)group{ + [DTBAds.sharedInstance addSlotGroup:group]; +} + +-(NSString*)fetchMoPubKeywords:(DTBAdResponse*)response { + return [response keywordsForMopub]; +} + +-(NSString*)fetchAmznSlots:(DTBAdResponse *)response { + return [response amznSlots]; +} + +-(int)fetchAdWidth:(DTBAdResponse *)response { + DTBAdSize *adSize = [response adSize]; + return adSize.width; +} + +-(int)fetchAdHeight:(DTBAdResponse *)response { + DTBAdSize *adSize = [response adSize]; + return adSize.height; +} + +-(NSString*)fetchMediationHints:(DTBAdResponse*)response isSmart:(BOOL)isSmart{ + NSError * err; + NSDictionary * hint = [response mediationHints:isSmart]; + NSMutableDictionary *mHint = [hint mutableCopy]; + NSDate* myDate = mHint[@"load_start"]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"dd-MM-yyyy"]; + NSString *stringDate = [dateFormatter stringFromDate:myDate]; + [mHint setValue:stringDate forKey:@"load_start"]; + NSData * jsonData = [NSJSONSerialization dataWithJSONObject:mHint options:0 error:&err]; + NSString * mediationHints = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + return mediationHints; +} + +-(void)setCMPFlavor:(DTBCMPFlavor)cFlavor { + [DTBAds.sharedInstance setCmpFlavor:cFlavor]; +} + +-(void)setConsentStatus:(DTBConsentStatus)consentStatus{ + [DTBAds.sharedInstance setConsentStatus:consentStatus]; +} + +-(NSMutableArray*)createArray{ + return [[NSMutableArray alloc] init]; +} + +-(void)addToArray:(NSMutableArray*)dictionary item:(int)item{ + NSNumber* num = [NSNumber numberWithInt:item]; + [dictionary addObject:num]; +} + +-(void)setVendorList:(NSMutableArray*)dictionary{ + [DTBAds.sharedInstance setVendorList:dictionary]; +} + +-(void)setAutoRefresh:(DTBAdLoader*)adLoader{ + [adLoader setAutoRefresh]; +} + +-(void)setAutoRefresh:(DTBAdLoader*)adLoader secs:(int)secs{ + [adLoader setAutoRefresh:secs]; +} + +-(void)pauseAutorefresh:(DTBAdLoader*)adLoader{ + [adLoader pauseAutorefresh]; +} + +-(void)stopAutoRefresh:(DTBAdLoader*)adLoader{ + [adLoader stop]; +} + +-(void)resumeAutoRefresh:(DTBAdLoader*)adLoader{ + [adLoader resumeAutorefresh]; +} + +-(void)setAPSPublisherExtendedIdFeatureEnabled:(BOOL)isEnabled { + [DTBAds.sharedInstance setAPSPublisherExtendedIdFeatureEnabled:isEnabled]; +} + +-(void)addCustomAttribute:(NSString *)withKey value:(id)value { + [DTBAds.sharedInstance addCustomAttribute:withKey value:value]; +} + +-(void)removeCustomAttribute:(NSString *)forKey { + [DTBAds.sharedInstance removeCustomAttribute:forKey]; +} + +-(void)setAdNetworkInfo:(DTBAdNetworkInfo *)dtbAdNetworkInfo { + [[DTBAds sharedInstance] setAdNetworkInfo:dtbAdNetworkInfo]; +} + +-(void)setLocalExtras:(NSString *)adUnitId localExtras:(NSDictionary *)localExtras { + [DTBAds setLocalExtras:adUnitId localExtras:localExtras]; +} + +-(NSDictionary *)getMediationHintsDict:(DTBAdResponse*)response isSmart:(BOOL)isSmart{ + return [response mediationHints:isSmart]; +} + +-(void)showInterstitialAd:(DTBAdInterstitialDispatcher*)dispatcher { + [dispatcher showFromController:[self unityRootViewController]]; +} + +-(UIViewController *)unityRootViewController { + id appDelegate = [UIApplication sharedApplication].delegate; + // @TODO Check whether the appDelegate implements rootViewController. Refer to CR-68240623 for discussions. + if ([appDelegate respondsToSelector:@selector(rootViewController)]) { + return [[[UIApplication sharedApplication].delegate window] rootViewController]; + } + return nil; +} + +@end diff --git a/Amazon/Plugins/iOS/AmazonManager.mm.meta b/Amazon/Plugins/iOS/AmazonManager.mm.meta new file mode 100644 index 0000000..41eacc2 --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonManager.mm.meta @@ -0,0 +1,110 @@ +fileFormatVersion: 2 +guid: 65a7bcd4e95cc47c88cd2b6280e00c17 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/AmazonUnityCallback.h b/Amazon/Plugins/iOS/AmazonUnityCallback.h new file mode 100755 index 0000000..c9ed974 --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonUnityCallback.h @@ -0,0 +1,20 @@ +#import +#import + +typedef const void *DTBAdCallbackClientRef; + +typedef void (*SuccessResponse) (DTBAdCallbackClientRef* callback, DTBAdResponse* dataPtr); +typedef void (*ErrorResponse) (DTBAdCallbackClientRef* callback, int errorCode); +typedef void (*ErrorResponseWithInfo) (DTBAdCallbackClientRef* callback, int errorCode, DTBAdErrorInfo* adErrorInfoPtr); + +@interface AmazonUnityCallback : NSObject { + SuccessResponse _successCallback; + ErrorResponse _errorCallback; + ErrorResponseWithInfo _errorCallbackWithInfo; + + DTBAdCallbackClientRef* _callbackClient; +} + +- (void)setListeners:(DTBAdCallbackClientRef*)client success:(SuccessResponse)success errorCallback:(ErrorResponse)error; +- (void)setListenersWithInfo:(DTBAdCallbackClientRef*)client success:(SuccessResponse)success errorCallbackWithInfo:(ErrorResponseWithInfo)errorCallbackWithInfo; +@end diff --git a/Amazon/Plugins/iOS/AmazonUnityCallback.h.meta b/Amazon/Plugins/iOS/AmazonUnityCallback.h.meta new file mode 100644 index 0000000..b0ae32f --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonUnityCallback.h.meta @@ -0,0 +1,105 @@ +fileFormatVersion: 2 +guid: 4ab68d8321afe4cca8177a404f816891 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/AmazonUnityCallback.mm b/Amazon/Plugins/iOS/AmazonUnityCallback.mm new file mode 100644 index 0000000..75ac6d2 --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonUnityCallback.mm @@ -0,0 +1,38 @@ +#import "AmazonUnityCallback.h" +#import "AmazonManager.h" + +@implementation AmazonUnityCallback +- (void)setListeners:(DTBAdCallbackClientRef*)client success:(SuccessResponse)success errorCallback:(ErrorResponse)error { + _callbackClient = client; + _successCallback = success; + _errorCallback = error; +} + +- (void)setListenersWithInfo:(DTBAdCallbackClientRef*)client success:(SuccessResponse)success errorCallbackWithInfo:(ErrorResponseWithInfo)errorCallbackWithInfo { + _callbackClient = client; + _successCallback = success; + _errorCallbackWithInfo = errorCallbackWithInfo; +} + + +#pragma mark - AmazonUnityCallback + +- (void)onFailure:(DTBAdError)error { + if (_errorCallback != nil) { + _errorCallback( _callbackClient, (int)error ); + } +} + +- (void)onFailure:(DTBAdError)error + dtbAdErrorInfo:(DTBAdErrorInfo *) dtbAdErrorInfo { + if (_errorCallbackWithInfo != nil) { + _errorCallbackWithInfo( _callbackClient, (int)error, dtbAdErrorInfo ); + } + } + +- (void)onSuccess:(DTBAdResponse *)adResponse { + if (_successCallback != nil) { + _successCallback( _callbackClient, adResponse ); + } +} +@end diff --git a/Amazon/Plugins/iOS/AmazonUnityCallback.mm.meta b/Amazon/Plugins/iOS/AmazonUnityCallback.mm.meta new file mode 100644 index 0000000..e2a421d --- /dev/null +++ b/Amazon/Plugins/iOS/AmazonUnityCallback.mm.meta @@ -0,0 +1,85 @@ +fileFormatVersion: 2 +guid: ab36449d445ac4544afe77c7c0539ec0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/DTBBannerDelegate.h b/Amazon/Plugins/iOS/DTBBannerDelegate.h new file mode 100755 index 0000000..f5fa6a1 --- /dev/null +++ b/Amazon/Plugins/iOS/DTBBannerDelegate.h @@ -0,0 +1,26 @@ +#import +#import + +typedef const void *DTBCallbackBannerRef; + +typedef void (*DTBAdDidLoadType) (DTBCallbackBannerRef* callback); +typedef void (*DTBAdFailedToLoadType) (DTBCallbackBannerRef* callback); +typedef void (*DTBBannerWillLeaveApplicationType) (DTBCallbackBannerRef* callback); +typedef void (*DTBImpressionFiredType) (DTBCallbackBannerRef* callback); + +@interface DTBBannerDelegate : NSObject +{ + DTBAdDidLoadType _adDidLoadDelegate; + DTBAdFailedToLoadType _adFailedToLoadDelegate; + DTBBannerWillLeaveApplicationType _bannerWillLeaveApplicationDelegate; + DTBImpressionFiredType _impressionFiredDelegate; + + DTBCallbackBannerRef* _callbackClient; +} + +- (void)setDelegate:(DTBCallbackBannerRef*)client + adLoad:(DTBAdDidLoadType)adLoad + adFailLoad:(DTBAdFailedToLoadType)adFailLoad + leaveApp:(DTBBannerWillLeaveApplicationType)leaveApp + impFired:(DTBImpressionFiredType)impFired; +@end diff --git a/Amazon/Plugins/iOS/DTBBannerDelegate.h.meta b/Amazon/Plugins/iOS/DTBBannerDelegate.h.meta new file mode 100644 index 0000000..64b2f50 --- /dev/null +++ b/Amazon/Plugins/iOS/DTBBannerDelegate.h.meta @@ -0,0 +1,80 @@ +fileFormatVersion: 2 +guid: a58dbc723902c4dd6a148f77e0845a3c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/DTBBannerDelegate.mm b/Amazon/Plugins/iOS/DTBBannerDelegate.mm new file mode 100644 index 0000000..1b37ba5 --- /dev/null +++ b/Amazon/Plugins/iOS/DTBBannerDelegate.mm @@ -0,0 +1,45 @@ +#import "DTBBannerDelegate.h" + +@implementation DTBBannerDelegate +- (void)setDelegate:(DTBCallbackBannerRef*)client + adLoad:(DTBAdDidLoadType)adLoad + adFailLoad:(DTBAdFailedToLoadType)adFailLoad + leaveApp:(DTBBannerWillLeaveApplicationType)leaveApp + impFired:(DTBImpressionFiredType)impFired +{ + _callbackClient = client; + _adDidLoadDelegate = adLoad; + _adFailedToLoadDelegate = adFailLoad; + _bannerWillLeaveApplicationDelegate = leaveApp; + _impressionFiredDelegate = impFired; + +} + + +#pragma mark - DTBBannerDelegate + +- (void)adDidLoad:(UIView * _Nonnull)adView { + if (_adDidLoadDelegate != nil) { + _adDidLoadDelegate(_callbackClient); + } +} + +- (void)adFailedToLoad:(UIView * _Nullable)banner errorCode:(NSInteger)errorCode { + if (_adFailedToLoadDelegate != nil) { + _adFailedToLoadDelegate(_callbackClient); + } +} + +- (void)bannerWillLeaveApplication:(UIView *)adView { + if (_bannerWillLeaveApplicationDelegate != nil) { + _bannerWillLeaveApplicationDelegate(_callbackClient); + } +} + +- (void)impressionFired { + if (_impressionFiredDelegate != nil) { + _impressionFiredDelegate(_callbackClient); + } +} + +@end diff --git a/Amazon/Plugins/iOS/DTBBannerDelegate.mm.meta b/Amazon/Plugins/iOS/DTBBannerDelegate.mm.meta new file mode 100644 index 0000000..b00cb27 --- /dev/null +++ b/Amazon/Plugins/iOS/DTBBannerDelegate.mm.meta @@ -0,0 +1,85 @@ +fileFormatVersion: 2 +guid: 64f2586d9fb3549848bbd34f6f8085d2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/DTBInterstitialDelegate.h b/Amazon/Plugins/iOS/DTBInterstitialDelegate.h new file mode 100755 index 0000000..3012fa3 --- /dev/null +++ b/Amazon/Plugins/iOS/DTBInterstitialDelegate.h @@ -0,0 +1,31 @@ +#import +#import + +typedef const void *DTBCallbackInterstitialRef; + +typedef void (*DTBInterstitialDidLoadType) (DTBCallbackInterstitialRef* callback); +typedef void (*DTBDidFailToLoadAdWithErrorCodeType) (DTBCallbackInterstitialRef* callback); +typedef void (*DTBInterstitialDidPresentScreenType) (DTBCallbackInterstitialRef* callback); +typedef void (*DTBInterstitialDidDismissScreenType) (DTBCallbackInterstitialRef* callback); +typedef void (*DTBInterstitialWillLeaveApplicationType) (DTBCallbackInterstitialRef* callback); +typedef void (*DTBInterstitialImpressionFiredType) (DTBCallbackInterstitialRef* callback); + +@interface DTBInterstitialDelegate : NSObject { + DTBInterstitialDidLoadType _didLoadDelegate; + DTBDidFailToLoadAdWithErrorCodeType _didFailToLoadDelegate; + DTBInterstitialDidPresentScreenType _didPresentScreenDelegate; + DTBInterstitialDidDismissScreenType _didDismissScreenDelegate; + DTBInterstitialWillLeaveApplicationType _leaveAppDelegate; + DTBInterstitialImpressionFiredType _impFiredDelegate; + + DTBCallbackInterstitialRef* _callbackClient; +} + +- (void)setDelegate:(DTBCallbackInterstitialRef*)client + adLoad:(DTBInterstitialDidLoadType)adLoad + adFailLoad:(DTBDidFailToLoadAdWithErrorCodeType)adFailLoad + leaveApp:(DTBInterstitialWillLeaveApplicationType)leaveApp + impFired:(DTBInterstitialImpressionFiredType)impFired + didOpen:(DTBInterstitialDidPresentScreenType)didOpen + didDismiss:(DTBInterstitialDidDismissScreenType)didDismiss; +@end diff --git a/Amazon/Plugins/iOS/DTBInterstitialDelegate.h.meta b/Amazon/Plugins/iOS/DTBInterstitialDelegate.h.meta new file mode 100644 index 0000000..e89a3e0 --- /dev/null +++ b/Amazon/Plugins/iOS/DTBInterstitialDelegate.h.meta @@ -0,0 +1,80 @@ +fileFormatVersion: 2 +guid: ec64dc94f39894ffba7e39a14f3b2102 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Plugins/iOS/DTBInterstitialDelegate.mm b/Amazon/Plugins/iOS/DTBInterstitialDelegate.mm new file mode 100644 index 0000000..ec940ef --- /dev/null +++ b/Amazon/Plugins/iOS/DTBInterstitialDelegate.mm @@ -0,0 +1,69 @@ +#import "DTBInterstitialDelegate.h" + +@implementation DTBInterstitialDelegate +- (void)setDelegate:(DTBCallbackInterstitialRef*)client + adLoad:(DTBInterstitialDidLoadType)adLoad + adFailLoad:(DTBDidFailToLoadAdWithErrorCodeType)adFailLoad + leaveApp:(DTBInterstitialWillLeaveApplicationType)leaveApp + impFired:(DTBInterstitialImpressionFiredType)impFired + didOpen:(DTBInterstitialDidPresentScreenType)didOpen + didDismiss:(DTBInterstitialDidDismissScreenType)didDismiss +{ + _callbackClient = client; + _didLoadDelegate = adLoad; + _didFailToLoadDelegate = adFailLoad; + _leaveAppDelegate = leaveApp; + _impFiredDelegate = impFired; + _didPresentScreenDelegate = didOpen; + _didDismissScreenDelegate = didDismiss; +} + + +#pragma mark - DTBInterstitialDelegate + +- (void)interstitialDidLoad:(DTBAdInterstitialDispatcher * _Nullable )interstitial { + if (_didLoadDelegate != nil) { + _didLoadDelegate(_callbackClient); + } +} + +- (void)interstitial:(DTBAdInterstitialDispatcher * _Nullable )interstitial + didFailToLoadAdWithErrorCode:(DTBAdErrorCode)errorCode { + if (_didFailToLoadDelegate != nil) { + _didFailToLoadDelegate(_callbackClient); + } +} + +- (void)interstitialWillPresentScreen:(DTBAdInterstitialDispatcher * _Nullable )interstitial { +} + +- (void)interstitialDidPresentScreen:(DTBAdInterstitialDispatcher * _Nullable )interstitial { + if (_didPresentScreenDelegate != nil) { + _didPresentScreenDelegate(_callbackClient); + } +} + +- (void)interstitialWillDismissScreen:(DTBAdInterstitialDispatcher * _Nullable )interstitial { +} + +- (void)interstitialDidDismissScreen:(DTBAdInterstitialDispatcher * _Nullable )interstitial { + if (_didDismissScreenDelegate != nil) { + _didDismissScreenDelegate(_callbackClient); + } +} + +- (void)interstitialWillLeaveApplication:(DTBAdInterstitialDispatcher * _Nullable )interstitial { + if (_leaveAppDelegate != nil) { + _leaveAppDelegate(_callbackClient); + } +} + +- (void)showFromRootViewController:(UIViewController *_Nonnull)controller { +} + +- (void)impressionFired { + if (_impFiredDelegate != nil) { + _impFiredDelegate(_callbackClient); + } +} +@end diff --git a/Amazon/Plugins/iOS/DTBInterstitialDelegate.mm.meta b/Amazon/Plugins/iOS/DTBInterstitialDelegate.mm.meta new file mode 100644 index 0000000..d22315a --- /dev/null +++ b/Amazon/Plugins/iOS/DTBInterstitialDelegate.mm.meta @@ -0,0 +1,85 @@ +fileFormatVersion: 2 +guid: 4f43b5dc42cf54011b96f66d261f2619 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Sample.meta b/Amazon/Sample.meta new file mode 100644 index 0000000..3c4176b --- /dev/null +++ b/Amazon/Sample.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6a17d7d5a68624567861d0e1822b24a9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Sample/APSMaxMediation.unity b/Amazon/Sample/APSMaxMediation.unity new file mode 100644 index 0000000..70c896f --- /dev/null +++ b/Amazon/Sample/APSMaxMediation.unity @@ -0,0 +1,1679 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 2 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &393870611 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 393870612} + - component: {fileID: 393870614} + - component: {fileID: 393870613} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &393870612 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393870611} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1889519549} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &393870613 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393870611} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Initialize +--- !u!222 &393870614 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 393870611} + m_CullTransparentMesh: 0 +--- !u!1 &491590227 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 491590228} + - component: {fileID: 491590230} + - component: {fileID: 491590229} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &491590228 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 491590227} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 620422002} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &491590229 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 491590227} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Request Banner +--- !u!222 &491590230 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 491590227} + m_CullTransparentMesh: 0 +--- !u!1 &499681494 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 499681495} + - component: {fileID: 499681497} + - component: {fileID: 499681496} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &499681495 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 499681494} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1477954961} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &499681496 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 499681494} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Is Initialized +--- !u!222 &499681497 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 499681494} + m_CullTransparentMesh: 0 +--- !u!1 &620422001 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 620422002} + - component: {fileID: 620422005} + - component: {fileID: 620422004} + - component: {fileID: 620422003} + m_Layer: 5 + m_Name: Request Banner + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &620422002 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 620422001} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 491590228} + m_Father: {fileID: 640056004} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -6} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &620422003 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 620422001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 620422004} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 946867261} + m_MethodName: RequestBanner + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &620422004 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 620422001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &620422005 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 620422001} + m_CullTransparentMesh: 0 +--- !u!1 &640056000 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 640056004} + - component: {fileID: 640056003} + - component: {fileID: 640056002} + - component: {fileID: 640056001} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &640056001 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 640056000} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &640056002 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 640056000} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 3 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &640056003 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 640056000} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 1 + m_Camera: {fileID: 1336878920} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &640056004 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 640056000} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 1889519549} + - {fileID: 820223061} + - {fileID: 620422002} + - {fileID: 735603278} + - {fileID: 739627434} + - {fileID: 1477954961} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &735603277 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 735603278} + - component: {fileID: 735603281} + - component: {fileID: 735603280} + - component: {fileID: 735603279} + m_Layer: 5 + m_Name: Request Rewarded Video + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &735603278 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 735603277} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1079672022} + m_Father: {fileID: 640056004} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0.00000011921, y: -51.53} + m_SizeDelta: {x: 183.60916, y: 26.980476} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &735603279 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 735603277} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 735603280} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 946867261} + m_MethodName: RequestRewardedVideo + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &735603280 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 735603277} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &735603281 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 735603277} + m_CullTransparentMesh: 0 +--- !u!1 &739627433 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 739627434} + - component: {fileID: 739627437} + - component: {fileID: 739627436} + - component: {fileID: 739627435} + m_Layer: 5 + m_Name: Request Interstitial Video + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &739627434 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 739627433} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1682398784} + m_Father: {fileID: 640056004} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -96.3} + m_SizeDelta: {x: 183.60913, y: 28.7574} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &739627435 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 739627433} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 739627436} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 946867261} + m_MethodName: RequestInterstitialVideo + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &739627436 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 739627433} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &739627437 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 739627433} + m_CullTransparentMesh: 0 +--- !u!1 &820223060 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 820223061} + - component: {fileID: 820223064} + - component: {fileID: 820223063} + - component: {fileID: 820223062} + m_Layer: 5 + m_Name: Request Interstitial + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &820223061 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 820223060} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1290993690} + m_Father: {fileID: 640056004} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 41.2} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &820223062 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 820223060} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 820223063} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 946867261} + m_MethodName: RequestInterstitial + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &820223063 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 820223060} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &820223064 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 820223060} + m_CullTransparentMesh: 0 +--- !u!1 &946867260 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 946867262} + - component: {fileID: 946867261} + m_Layer: 0 + m_Name: AmazonMaxDemo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &946867261 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 946867260} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 312c0b7796265224ca6bd13197a7d5d6, type: 3} + m_Name: + m_EditorClassIdentifier: + isInitializedBut: {fileID: 1477954962} +--- !u!4 &946867262 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 946867260} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 315.404, y: 1680.6172, z: -32.624996} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &975794182 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 975794185} + - component: {fileID: 975794184} + - component: {fileID: 975794183} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &975794183 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 975794182} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &975794184 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 975794182} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &975794185 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 975794182} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1079672021 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1079672022} + - component: {fileID: 1079672024} + - component: {fileID: 1079672023} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1079672022 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079672021} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 735603278} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1079672023 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079672021} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Request Rewarded Video +--- !u!222 &1079672024 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1079672021} + m_CullTransparentMesh: 0 +--- !u!1 &1290993689 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1290993690} + - component: {fileID: 1290993692} + - component: {fileID: 1290993691} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1290993690 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1290993689} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 820223061} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1290993691 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1290993689} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Request Interstitial +--- !u!222 &1290993692 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1290993689} + m_CullTransparentMesh: 0 +--- !u!1 &1336878919 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1336878922} + - component: {fileID: 1336878920} + - component: {fileID: 1336878921} + m_Layer: 0 + m_Name: Camera + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!20 &1336878920 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1336878919} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.38679248, g: 0.38679248, b: 0.38679248, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &1336878921 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1336878919} + m_Enabled: 1 +--- !u!4 &1336878922 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1336878919} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1477954960 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1477954961} + - component: {fileID: 1477954964} + - component: {fileID: 1477954963} + - component: {fileID: 1477954962} + m_Layer: 5 + m_Name: Is Initialized + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1477954961 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1477954960} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 499681495} + m_Father: {fileID: 640056004} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 93.5} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1477954962 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1477954960} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1477954963} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 946867261} + m_MethodName: IsInitialized + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1477954963 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1477954960} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1477954964 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1477954960} + m_CullTransparentMesh: 0 +--- !u!1 &1682398783 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1682398784} + - component: {fileID: 1682398786} + - component: {fileID: 1682398785} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1682398784 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1682398783} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 739627434} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1682398785 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1682398783} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Request Interstitial Video +--- !u!222 &1682398786 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1682398783} + m_CullTransparentMesh: 0 +--- !u!1 &1889519548 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1889519549} + - component: {fileID: 1889519552} + - component: {fileID: 1889519551} + - component: {fileID: 1889519550} + m_Layer: 5 + m_Name: Initialize + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1889519549 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1889519548} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 393870612} + m_Father: {fileID: 640056004} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 151} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1889519550 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1889519548} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1889519551} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 946867261} + m_MethodName: InitializeMax + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1889519550} + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1889519551 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1889519548} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1889519552 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1889519548} + m_CullTransparentMesh: 0 diff --git a/Amazon/Sample/APSMaxMediation.unity.meta b/Amazon/Sample/APSMaxMediation.unity.meta new file mode 100644 index 0000000..143fe30 --- /dev/null +++ b/Amazon/Sample/APSMaxMediation.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fb8e1477d33cb4076b8aa247ae7dd237 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Sample/AmazonMaxDemo.cs b/Amazon/Sample/AmazonMaxDemo.cs new file mode 100644 index 0000000..a2c8167 --- /dev/null +++ b/Amazon/Sample/AmazonMaxDemo.cs @@ -0,0 +1,297 @@ + +using System; +using AmazonAds; +using UnityEngine; +using System.Collections.Generic; + +public class AmazonMaxDemo : MonoBehaviour { + + private const string maxKey = "l-_TbRRFRIhI2bN388lTNzh0k_83nqhSLMkFs2ATgT_y4GPxCqSQOdiDV3WgHf01C4N9r53JvUp-N_65kdcdro"; +#if UNITY_ANDROID + private const string appId = "7873ab072f0647b8837748312c7b8b5a"; + + private const string maxBannerAdId = "989798cb31a0d25f"; + private const string maxInterstitialAdId = "7e3a01318c888038"; + private const string maxVideoAdId = "09d9041492d1d0d9"; + + private const string amazonBannerSlotId = "ed3b9f16-4497-4001-be7d-2e8ca679ee73"; //320x50 + private const string amzonInterstitialSlotId = "394133e6-27fe-477d-816b-4a00cdaa54b6"; + private const string amazonInterstitialVideoSlotId = "b9f9a2aa-72d8-4cb3-83db-949ebb53836f"; + private const string amazonRewardedVideoSlotId = "1ed9fa0b-3cf0-4326-8c35-c0e9ddcdb765"; +#else + private const string appId = "c5f20fe6e37146b08749d09bb2b6a4dd"; + + private const string maxBannerAdId = "d7dc4c6c1d6886fb"; + private const string maxInterstitialAdId = "928de5b2fa152dac"; + private const string maxVideoAdId = "57e0224b0c29607c"; + + private const string amazonBannerSlotId = "88e6293b-0bf0-43fc-947b-925babe7bf3f"; //320x50 + private const string amzonInterstitialSlotId = "424c37b6-38e0-4076-94e6-0933a6213496"; + private const string amazonInterstitialVideoSlotId = "671086df-06f2-4ee7-86f6-e578d10b3128"; + private const string amazonRewardedVideoSlotId = "08892e57-35ff-450c-8b35-4d261251f7c7"; +#endif + + public UnityEngine.UI.Button isInitializedBut; + private bool isAutoRefresh = true; + private bool isFirstInterstitialRequest = true; + private bool isFirstVideoInterstitialRequest = true; + private bool isFirstRewardedVideoRequest = true; + + private APSBannerAdRequest bannerAdRequest; + private APSInterstitialAdRequest interstitialAdRequest; + private APSVideoAdRequest interstitialVideoAdRequest; + private APSVideoAdRequest rewardedVideoAdRequest; + + public void InitializeMax () { + Amazon.Initialize(appId); + Amazon.EnableTesting(true); + Amazon.EnableLogging(true); + Amazon.UseGeoLocation(true); + Amazon.SetMRAIDPolicy(Amazon.MRAIDPolicy.CUSTOM); + Amazon.SetAdNetworkInfo(new AdNetworkInfo(DTBAdNetwork.MAX)); + Amazon.SetMRAIDSupportedVersions(new string[] { "1.0", "2.0", "3.0" }); + + MaxSdk.SetSdkKey(maxKey); + MaxSdk.InitializeSdk(); + MaxSdk.SetCreativeDebuggerEnabled(true); + MaxSdk.SetVerboseLogging(true); + + MaxSdkCallbacks.Banner.OnAdLoadedEvent += OnBannerAdLoadedEvent; + MaxSdkCallbacks.Banner.OnAdLoadFailedEvent += OnBannerAdLoadFailedEvent; + MaxSdkCallbacks.Banner.OnAdClickedEvent += OnBannerAdClickedEvent; + MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnBannerAdRevenuePaidEvent; + MaxSdkCallbacks.Banner.OnAdExpandedEvent += OnBannerAdExpandedEvent; + MaxSdkCallbacks.Banner.OnAdCollapsedEvent += OnBannerAdCollapsedEvent; + + MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += OnInterstitialLoadedEvent; + MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += OnInterstitialLoadFailedEvent; + MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent += OnInterstitialDisplayedEvent; + MaxSdkCallbacks.Interstitial.OnAdClickedEvent += OnInterstitialClickedEvent; + MaxSdkCallbacks.Interstitial.OnAdHiddenEvent += OnInterstitialHiddenEvent; + MaxSdkCallbacks.Interstitial.OnAdDisplayFailedEvent += OnInterstitialAdFailedToDisplayEvent; + + MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += OnRewardedAdLoadedEvent; + MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += OnRewardedAdFailedEvent; + MaxSdkCallbacks.Rewarded.OnAdDisplayFailedEvent += OnRewardedAdFailedToDisplayEvent; + MaxSdkCallbacks.Rewarded.OnAdDisplayedEvent += OnRewardedAdDisplayedEvent; + MaxSdkCallbacks.Rewarded.OnAdClickedEvent += OnRewardedAdClickedEvent; + MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += OnRewardedAdDismissedEvent; + MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent; + MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnRewardedAdRevenuePaidEvent; + } + + public void IsInitialized(){ + if (isInitializedBut == null ) return; + if( Amazon.IsInitialized() ) { + isInitializedBut.GetComponent().color = Color.green; + } else { + isInitializedBut.GetComponent().color = Color.red; + } + } + + public void RequestInterstitial () { + if (isFirstInterstitialRequest) { + isFirstInterstitialRequest = false; + interstitialAdRequest = new APSInterstitialAdRequest(amzonInterstitialSlotId); + + interstitialAdRequest.onSuccess += (adResponse) => + { + MaxSdk.SetInterstitialLocalExtraParameter(maxInterstitialAdId, "amazon_ad_response", adResponse.GetResponse()); + MaxSdk.LoadInterstitial(maxInterstitialAdId); + }; + interstitialAdRequest.onFailedWithError += (adError) => + { + MaxSdk.SetInterstitialLocalExtraParameter(maxInterstitialAdId, "amazon_ad_error", adError.GetAdError()); + MaxSdk.LoadInterstitial(maxInterstitialAdId); + }; + + interstitialAdRequest.LoadAd(); + } else { + MaxSdk.LoadInterstitial(maxInterstitialAdId); + } + } + + private void CreateMaxBannerAd() + { + MaxSdk.CreateBanner(maxBannerAdId, MaxSdkBase.BannerPosition.BottomCenter); + MaxSdk.SetBannerPlacement(maxBannerAdId, "MY_BANNER_PLACEMENT"); + } + + public void RequestBanner () { + const int width = 320; + const int height = 50; + + if (bannerAdRequest != null) bannerAdRequest.DestroyFetchManager(); + bannerAdRequest = new APSBannerAdRequest(width, height, amazonBannerSlotId); + bannerAdRequest.onFailedWithError += (adError) => + { + MaxSdk.SetBannerLocalExtraParameter(maxBannerAdId, "amazon_ad_error", adError.GetAdError()); + CreateMaxBannerAd(); + }; + bannerAdRequest.onSuccess += (adResponse) => + { + MaxSdk.SetBannerLocalExtraParameter(maxBannerAdId, "amazon_ad_response", adResponse.GetResponse()); + CreateMaxBannerAd(); + }; + bannerAdRequest.LoadAd(); + } + + public void RequestInterstitialVideo () { + if(isFirstVideoInterstitialRequest) { + isFirstVideoInterstitialRequest = false; + interstitialVideoAdRequest = new APSVideoAdRequest(320, 480, amazonInterstitialVideoSlotId); + + interstitialVideoAdRequest.onSuccess += (adResponse) => + { + MaxSdk.SetInterstitialLocalExtraParameter(maxInterstitialAdId, "amazon_ad_response", adResponse.GetResponse()); + MaxSdk.LoadInterstitial(maxInterstitialAdId); + }; + interstitialVideoAdRequest.onFailedWithError += (adError) => + { + MaxSdk.SetInterstitialLocalExtraParameter(maxInterstitialAdId, "amazon_ad_error", adError.GetAdError()); + MaxSdk.LoadInterstitial(maxInterstitialAdId); + }; + + interstitialVideoAdRequest.LoadAd(); + } else { + MaxSdk.LoadInterstitial(maxInterstitialAdId); + } + } + + public void RequestRewardedVideo () { + if (isFirstRewardedVideoRequest) { + isFirstRewardedVideoRequest = false; + rewardedVideoAdRequest = new APSVideoAdRequest(320, 480, amazonRewardedVideoSlotId); + + rewardedVideoAdRequest.onSuccess += (adResponse) => + { + MaxSdk.SetRewardedAdLocalExtraParameter(maxVideoAdId, "amazon_ad_response", adResponse.GetResponse()); + MaxSdk.LoadRewardedAd(maxVideoAdId); + }; + rewardedVideoAdRequest.onFailedWithError += (adError) => + { + MaxSdk.SetRewardedAdLocalExtraParameter(maxVideoAdId, "amazon_ad_error", adError.GetAdError()); + MaxSdk.LoadRewardedAd(maxVideoAdId); + }; + + rewardedVideoAdRequest.LoadAd(); + } else { + MaxSdk.LoadRewardedAd(maxVideoAdId); + } + } + + private void OnBannerAdLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + MaxSdk.ShowBanner(maxBannerAdId); + } + + private void OnBannerAdLoadFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo) + { + } + + private void OnBannerAdClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + } + + private void OnBannerAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + } + + private void OnBannerAdExpandedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + } + + private void OnBannerAdCollapsedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + } + + private void OnInterstitialLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("OnInterstitialLoadedEvent:" + MaxSdk.IsInterstitialReady(maxInterstitialAdId)); + if (MaxSdk.IsInterstitialReady(maxInterstitialAdId)) + { + MaxSdk.ShowInterstitial(maxInterstitialAdId); + } + } + + private void OnInterstitialLoadFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo) + { + Debug.Log("OnInterstitialLoadFailedEvent"); + } + + private void OnInterstitialDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("OnInterstitialDisplayedEvent"); + } + + private void OnInterstitialAdFailedToDisplayEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("OnInterstitialAdFailedToDisplayEvent"); + } + + private void OnInterstitialClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("OnInterstitialClickedEvent"); + } + + private void OnInterstitialHiddenEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("OnInterstitialHiddenEvent"); + } + + private void ShowRewardedAd() + { + Debug.Log("ShowRewardedAd:" + MaxSdk.IsRewardedAdReady(maxVideoAdId)); + if (MaxSdk.IsRewardedAdReady(maxVideoAdId)) + { + MaxSdk.ShowRewardedAd(maxVideoAdId); + } + } + + private void OnRewardedAdLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("OnRewardedAdLoadedEvent"); + ShowRewardedAd(); + } + + private void OnRewardedAdFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo) + { + Debug.Log("OnRewardedAdFailedEvent"); + + } + + private void OnRewardedAdFailedToDisplayEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo, MaxSdkBase.AdInfo adInfo) + { + // Rewarded ad failed to display. We recommend loading the next ad + Debug.Log("Rewarded ad failed to display with error code: " + errorInfo.Code); + //MaxSdk.LoadRewardedAd(maxVideoAdId); + } + + private void OnRewardedAdDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("Rewarded ad displayed"); + } + + private void OnRewardedAdClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("Rewarded ad clicked"); + } + + private void OnRewardedAdDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + // Rewarded ad is hidden. Pre-load the next ad + Debug.Log("Rewarded ad dismissed"); + //MaxSdk.LoadRewardedAd(RewardedAdUnitId); + } + + private void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward, MaxSdkBase.AdInfo adInfo) + { + // Rewarded ad was displayed and user should receive the reward + Debug.Log("HERE:Rewarded ad received reward"); + } + + private void OnRewardedAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log("OnRewardedAdRevenuePaidEvent"); + } +} \ No newline at end of file diff --git a/Amazon/Sample/AmazonMaxDemo.cs.meta b/Amazon/Sample/AmazonMaxDemo.cs.meta new file mode 100644 index 0000000..f63575d --- /dev/null +++ b/Amazon/Sample/AmazonMaxDemo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 34ed58385e8924837ad87a1f2966e16b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts.meta b/Amazon/Scripts.meta new file mode 100644 index 0000000..8e6418a --- /dev/null +++ b/Amazon/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 296ee3b3b262345f6bfe2f066958a91d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Amazon.cs b/Amazon/Scripts/Amazon.cs new file mode 100644 index 0000000..56a6544 --- /dev/null +++ b/Amazon/Scripts/Amazon.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds { + public class Amazon { + private static PlatformApi api; + + public delegate void OnFailureDelegate (string errorMsg); + public delegate void OnFailureWithErrorDelegate (AdError adError); + public delegate void OnSuccessDelegate (AdResponse response); + public delegate void OnApplicationPauseDelegate(bool pauseStatus); + public static OnApplicationPauseDelegate OnApplicationPause = (pauseStatus) => { }; + + public enum MRAIDPolicy { + AUTO_DETECT, + MOPUB, + DFP, + CUSTOM, + NONE + } + public enum ConsentStatus { + CONSENT_NOT_DEFINED, + EXPLICIT_YES, + EXPLICIT_NO, + UNKNOWN + } + + public enum CMPFlavor { + CMP_NOT_DEFINED, + GOOGLE_CMP, + MOPUB_CMP + } + + public static void Initialize (string key) { +#if UNITY_IOS + api = new AmazonAds.IOS.IOSPlatform (); +#elif UNITY_ANDROID + api = new AmazonAds.Android.AndroidPlatform (); +#endif + api.Initialization (key); + } + + public static void SetMRAIDPolicy (Amazon.MRAIDPolicy policy) { + api.SetMRAIDPolicy (policy); + } + + public static void SetCMPFlavor(Amazon.CMPFlavor cFlavor){ + api.SetCMPFlavor(cFlavor); + } + + public static void SetConsentStatus(Amazon.ConsentStatus consentStatus){ + api.SetConsentStatus(consentStatus); + } + + public static void SetVendorList(List vendorList){ + api.SetVendorList(vendorList); + } + + public static void AddSlotGroup (SlotGroup group) { + api.AddSlotGroup (group); + } + + public static MRAIDPolicy GetMRAIDPolicy () { + return api.GetMRAIDPolicy (); + } + + public static void SetMRAIDSupportedVersions (String[] versions) { + api.SetMRAIDSupportedVersions (versions); + } + + public static void EnableLogging (bool flag) { + api.EnableLogging (flag); + } + + public static void UseGeoLocation (bool isLocationEnabled) { + api.UseGeoLocation (isLocationEnabled); + } + + public static bool IsLocationEnabled () { + return api.IsLocationEnabled (); + } + + public static bool IsInitialized () { + return api.IsInitialized (); + } + + public static bool IsTestMode () { + return api.IsTestMode (); + } + + public static void EnableTesting (bool flag) { + api.EnableTesting (flag); + } + + public static void AddCustomAttribute(string withKey, string value) + { + api.AddCustomAttribute(withKey, value); + } + + public static void RemoveCustomAttribute(string forKey) + { + api.RemoveCustomAttr(forKey); + } + + public static void SetAdNetworkInfo(AdNetworkInfo adNetworkInfo) + { + api.SetAdNetworkInfo(adNetworkInfo); + } + +#if UNITY_IOS + public static void SetAPSPublisherExtendedIdFeatureEnabled(bool isEnabled) + { + api.SetAPSPublisherExtendedIdFeatureEnabled(isEnabled); + } + + public static void SetMediationLocalExtras(string adUnitId, AdResponse adResponse) + { + api.SetLocalExtras(adUnitId, adResponse); + } +#endif + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Amazon.cs.meta b/Amazon/Scripts/Amazon.cs.meta new file mode 100644 index 0000000..d0579ef --- /dev/null +++ b/Amazon/Scripts/Amazon.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d5987cccc71fa4c51877e7c22d2d5f56 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/AmazonConstants.cs b/Amazon/Scripts/AmazonConstants.cs new file mode 100644 index 0000000..8e29fee --- /dev/null +++ b/Amazon/Scripts/AmazonConstants.cs @@ -0,0 +1,30 @@ +using System; + +public static class AmazonConstants +{ + public const string VERSION = "1.4.3"; + public const string RELEASE_NOTES_URL = "https://ams.amazon.com/webpublisher/uam/docs/aps-mobile/resources"; //TODO : add Unity Release Notes link + + public const string titleAboutDialog = "About Amazon SDK"; + public const string labelSdkVersion = "Amazon SDK version " + AmazonConstants.VERSION; + public const string buttonReleaseNotes = "Release Notes"; + public const string labelReportIssues = "Report Issues: " + "Mobile-aps-support@amazon.com"; + + public const string aboutDialogOk = "OK"; + + public const string manifestURL = "https://mdtb-sdk-packages.s3-us-west-2.amazonaws.com/Unity/aps_unity.json"; + public const string helpLink = "https://ams.amazon.com/webpublisher/uam/docs/aps-mobile/resources"; + public const string docUrl = "https://ams.amazon.com/webpublisher/uam/docs/aps-mobile"; + + + internal const string unityPlayerClass = "com.unity3d.player.UnityPlayer"; + + // Android constant names + internal const string sdkUtilitiesClass = "com.amazon.device.ads.SDKUtilities"; + internal const string dtbAdViewClass = "com.amazon.device.ads.DTBAdView"; + internal const string dtbAdInterstitialClass = "com.amazon.device.ads.DTBAdInterstitial"; + internal const string dtbAdNetworkClass = "com.amazon.device.ads.DTBAdNetwork"; + internal const string dtbAdNetworkInfoClass = "com.amazon.device.ads.DTBAdNetworkInfo"; + +} + diff --git a/Amazon/Scripts/AmazonConstants.cs.meta b/Amazon/Scripts/AmazonConstants.cs.meta new file mode 100644 index 0000000..178d6b3 --- /dev/null +++ b/Amazon/Scripts/AmazonConstants.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4c36066dbdad415b978c38a01a2b675 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Common.meta b/Amazon/Scripts/Common.meta new file mode 100644 index 0000000..400da0c --- /dev/null +++ b/Amazon/Scripts/Common.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8c45974962ec542baad78d4c30cd0056 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Common/IAdInterstitial.cs b/Amazon/Scripts/Common/IAdInterstitial.cs new file mode 100644 index 0000000..a067e78 --- /dev/null +++ b/Amazon/Scripts/Common/IAdInterstitial.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace AmazonAds { + public abstract class IAdInterstitial { + public abstract void FetchAd (AdResponse adResponse); + public abstract void Show (); + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Common/IAdInterstitial.cs.meta b/Amazon/Scripts/Common/IAdInterstitial.cs.meta new file mode 100644 index 0000000..b43ecab --- /dev/null +++ b/Amazon/Scripts/Common/IAdInterstitial.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d4da15e7be3dc455d97abce962533892 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Common/IAdRequest.cs b/Amazon/Scripts/Common/IAdRequest.cs new file mode 100644 index 0000000..2aa4bcf --- /dev/null +++ b/Amazon/Scripts/Common/IAdRequest.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections; +using System.Runtime.InteropServices; +using UnityEngine; +namespace AmazonAds { + public abstract class IAdRequest { + protected int refreshTime = 60; + protected string autoRefreshID = "0"; //FetchManageerUniqueID + protected bool isAutoRefreshAdMob = false; + protected bool isAutoRefreshMoPub = false; + protected bool requestHasBeenUsed = false; + protected IFetchManager fetchManager; + + public abstract void PutCustomTarget (string key, string value); + public abstract void SetSizes (IAdSize sizes); + public abstract void SetSizes (IInterstitialAdSize sizes); + public abstract void SetSizes (IVideo sizes); + public abstract void SetSlotGroup (string slotGroupName); + public abstract void LoadAd (Amazon.OnFailureDelegate failure, Amazon.OnSuccessDelegate success); + public abstract void LoadAd (Amazon.OnFailureWithErrorDelegate failure, Amazon.OnSuccessDelegate success); + public abstract void LoadSmartBanner (Amazon.OnFailureDelegate failure, Amazon.OnSuccessDelegate success); + public abstract void LoadSmartBanner (Amazon.OnFailureWithErrorDelegate failure, Amazon.OnSuccessDelegate success); + public abstract void SetAutoRefreshAdMob (bool flag, bool isSmartBanner = false); + public abstract void SetAutoRefreshMoPub (bool flag); + public abstract void SetAutoRefreshMoPub (bool flag, int refreshTime); + public abstract void SetAutoRefresh(); + public abstract void SetAutoRefresh(int secs); + public abstract void ResumeAutoRefresh(); + public abstract void StopAutoRefresh(); + public abstract void PauseAutoRefresh(); + public bool IsAutoRefreshAdMob (){ return isAutoRefreshAdMob;} + public bool IsAutoRefreshMoPub (){ return isAutoRefreshMoPub;} + public string AutoRefreshID (){return autoRefreshID.ToString ();} + public abstract void DisposeAd (); + public abstract void CreateFetchManager (bool isSmartBanner = false); + public abstract void DestroyFetchManager (); + public abstract void StopFetchManager(); + public abstract void StartFetchManager(); + public abstract void SetRefreshFlag(bool flag); + + protected static class Schedule { + private class Runner : MonoBehaviour { } + private static Runner _backer; + private static Runner Backer { + get { + if (_backer == null) { + var go = new GameObject ("Scheduler"); + GameObject.DontDestroyOnLoad (go); + _backer = go.AddComponent (); + } + return _backer; + } + } + private static float expiration = 5f; + + public static void WaitForAdResponce (IFetchManager fetchManager, Amazon.OnFailureDelegate failure, Amazon.OnSuccessDelegate success) { + Schedule.Backer.StartCoroutine (WaitForAdResponceCoroutine (fetchManager, failure, success)); + } + + static IEnumerator WaitForAdResponceCoroutine (IFetchManager fetchManager, Amazon.OnFailureDelegate failure, Amazon.OnSuccessDelegate success) { + float timerExp = 0; + bool flagResp = true; + while (fetchManager.isEmpty()) { + timerExp += Time.deltaTime; + if (timerExp > expiration) { + flagResp = false; + failure ("no ads from fetchManager"); + break; + } + yield return null; + } + + if (flagResp) { + success( fetchManager.peek () ); + } + Schedule.Clear (); + } + + public static void Clear () { + GameObject.Destroy (Backer); + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Common/IAdRequest.cs.meta b/Amazon/Scripts/Common/IAdRequest.cs.meta new file mode 100644 index 0000000..5740c6e --- /dev/null +++ b/Amazon/Scripts/Common/IAdRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ba13283bbee174961b809f3b9e502094 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Common/IAdSize.cs b/Amazon/Scripts/Common/IAdSize.cs new file mode 100644 index 0000000..6eaeec2 --- /dev/null +++ b/Amazon/Scripts/Common/IAdSize.cs @@ -0,0 +1,9 @@ +namespace AmazonAds { + public interface IAdSize { + int GetWidth (); + int GetHeight (); + string GetSlotUUID (); + } + public interface IInterstitialAdSize { } + public interface IVideo { } +} \ No newline at end of file diff --git a/Amazon/Scripts/Common/IAdSize.cs.meta b/Amazon/Scripts/Common/IAdSize.cs.meta new file mode 100644 index 0000000..56bd287 --- /dev/null +++ b/Amazon/Scripts/Common/IAdSize.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 33e37a43420f84a408938af12117ff08 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Common/IAdView.cs b/Amazon/Scripts/Common/IAdView.cs new file mode 100644 index 0000000..2c9a617 --- /dev/null +++ b/Amazon/Scripts/Common/IAdView.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace AmazonAds { + public abstract class IAdView { + public abstract void FetchAd (AdResponse adResponse); + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Common/IAdView.cs.meta b/Amazon/Scripts/Common/IAdView.cs.meta new file mode 100644 index 0000000..3497cce --- /dev/null +++ b/Amazon/Scripts/Common/IAdView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: adeba99c4a0f04b54b8af9623665e2d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Common/IFetchManager.cs b/Amazon/Scripts/Common/IFetchManager.cs new file mode 100644 index 0000000..b92b1c5 --- /dev/null +++ b/Amazon/Scripts/Common/IFetchManager.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections; +using System.Runtime.InteropServices; +using UnityEngine; +namespace AmazonAds { + public interface IFetchManager { + void dispense (); + + void start (); + + void stop (); + + bool isEmpty (); + + AmazonAds.AdResponse peek (); + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Common/IFetchManager.cs.meta b/Amazon/Scripts/Common/IFetchManager.cs.meta new file mode 100644 index 0000000..38b4b40 --- /dev/null +++ b/Amazon/Scripts/Common/IFetchManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dec92b206e59e400c8706ec073e326d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Common/ISlotGroup.cs b/Amazon/Scripts/Common/ISlotGroup.cs new file mode 100644 index 0000000..34a56af --- /dev/null +++ b/Amazon/Scripts/Common/ISlotGroup.cs @@ -0,0 +1,8 @@ +namespace AmazonAds{ + public interface ISlotGroup + { + void AddSlot(int width, int height, string uid); + void AddSlot(AdSize size); + } +} + diff --git a/Amazon/Scripts/Common/ISlotGroup.cs.meta b/Amazon/Scripts/Common/ISlotGroup.cs.meta new file mode 100644 index 0000000..b11a657 --- /dev/null +++ b/Amazon/Scripts/Common/ISlotGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b1f29380367c47c6a1c112ddc47ad84 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor.meta b/Amazon/Scripts/Editor.meta new file mode 100644 index 0000000..bc42966 --- /dev/null +++ b/Amazon/Scripts/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 60916135eefd74087bcd8ca80bd94ddc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/Amazon.Editor.asmdef b/Amazon/Scripts/Editor/Amazon.Editor.asmdef new file mode 100644 index 0000000..eb4b4ba --- /dev/null +++ b/Amazon/Scripts/Editor/Amazon.Editor.asmdef @@ -0,0 +1,17 @@ +{ + "name": "Amazon.Editor", + "references": [ + "Amazon" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Amazon/Scripts/Editor/Amazon.Editor.asmdef.meta b/Amazon/Scripts/Editor/Amazon.Editor.asmdef.meta new file mode 100644 index 0000000..ce8fb75 --- /dev/null +++ b/Amazon/Scripts/Editor/Amazon.Editor.asmdef.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 59f42bdf21710439a90f93e01e1f8984 +timeCreated: 1700190285 \ No newline at end of file diff --git a/Amazon/Scripts/Editor/AmazonAboutDialog.cs b/Amazon/Scripts/Editor/AmazonAboutDialog.cs new file mode 100644 index 0000000..24f0daf --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonAboutDialog.cs @@ -0,0 +1,21 @@ +using UnityEditor; +using UnityEngine; +using AmazonAds; +public class AmazonAboutDialog : ScriptableWizard { + public static void ShowDialog () { + DisplayWizard (AmazonConstants.titleAboutDialog, AmazonConstants.aboutDialogOk); + } + + protected override bool DrawWizardGUI () { + EditorGUILayout.LabelField (AmazonConstants.labelSdkVersion); + + EditorGUILayout.Space (); + if (GUILayout.Button (AmazonConstants.buttonReleaseNotes)) + Application.OpenURL (AmazonConstants.RELEASE_NOTES_URL); + EditorGUILayout.LabelField ("\n"); + EditorGUILayout.LabelField (AmazonConstants.labelReportIssues); + return false; + } + + private void OnWizardCreate () { } +} \ No newline at end of file diff --git a/Amazon/Scripts/Editor/AmazonAboutDialog.cs.meta b/Amazon/Scripts/Editor/AmazonAboutDialog.cs.meta new file mode 100644 index 0000000..6ff607b --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonAboutDialog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 431a6434bfc0a47e8a2c936e434c3d3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/AmazonBuildScript.cs b/Amazon/Scripts/Editor/AmazonBuildScript.cs new file mode 100644 index 0000000..a27cfd2 --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonBuildScript.cs @@ -0,0 +1,104 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Linq; +using UnityEditor.Callbacks; + +public class AmazonBuildScript +{ + public static string DEFAULT_APK_NAME = "APSUnityTestApp.apk"; + public static string DEFAULT_IOS_BUILD_DIR = "Builds/iOS"; + + public static void BuildIos() + { + string[] scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(); + EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.iOS, BuildTarget.iOS); + string outputFileName = GetArg("-output", DEFAULT_IOS_BUILD_DIR); + BuildPipeline.BuildPlayer(scenes, outputFileName, BuildTarget.iOS, BuildOptions.Development); + } + + public static void BuildAndroid() + { + string[] scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(); + EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android); + string outputFileName = GetArg("-output", DEFAULT_APK_NAME); + BuildPipeline.BuildPlayer(scenes, outputFileName, BuildTarget.Android, BuildOptions.Development); + EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.iOS, BuildTarget.iOS); + } + + public static void SwitchToIos() + { + EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.iOS, BuildTarget.iOS); + } + + private static string GetArg(string name, string defaultVal) + { + var args = System.Environment.GetCommandLineArgs(); + for (int i = 0; i < args.Length; i++) + { + if (args[i] == name && args.Length > i + 1) + { + return args[i + 1]; + } + } + return defaultVal; + } + + public static void BuildExternalAndroid() + { + string[] envvars = new string[] + { + "ANDROID_KEYSTORE_NAME", "ANDROID_KEYSTORE_PASSWORD", "ANDROID_KEYALIAS_NAME", "ANDROID_KEYALIAS_PASSWORD", "ANDROID_SDK_ROOT" + }; + if (EnvironmentVariablesMissing(envvars)) + { + Environment.ExitCode = -1; + return; // note, we can not use Environment.Exit(-1) - the buildprocess will just hang afterwards + } + + //Available Playersettings: https://docs.unity3d.com/ScriptReference/PlayerSettings.Android.html + + //set the internal apk version to the current unix timestamp, so this increases with every build + PlayerSettings.Android.bundleVersionCode = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; + + //set the other settings from environment variables + PlayerSettings.Android.keystoreName = Environment.GetEnvironmentVariable("ANDROID_KEYSTORE_NAME"); + PlayerSettings.Android.keystorePass = Environment.GetEnvironmentVariable("ANDROID_KEYSTORE_PASSWORD"); + PlayerSettings.Android.keyaliasName = Environment.GetEnvironmentVariable("ANDROID_KEYALIAS_NAME"); + PlayerSettings.Android.keyaliasPass = Environment.GetEnvironmentVariable("ANDROID_KEYALIAS_PASSWORD"); + + EditorPrefs.SetString("AndroidSdkRoot", Environment.GetEnvironmentVariable("ANDROID_SDK_ROOT")); + + //Get the apk file to be built from the command line argument + string outputapk = Environment.GetCommandLineArgs().Last(); + BuildPipeline.BuildPlayer(GetScenePaths(), outputapk, BuildTarget.Android, BuildOptions.None); + } + + static string[] GetScenePaths() + { + string[] scenes = new string[EditorBuildSettings.scenes.Length]; + for (int i = 0; i < scenes.Length; i++) + { + scenes[i] = EditorBuildSettings.scenes[i].path; + } + return scenes; + } + + static bool EnvironmentVariablesMissing(string[] envvars) + { + string value; + bool missing = false; + foreach (string envvar in envvars) + { + value = Environment.GetEnvironmentVariable(envvar); + if (value == null) + { + Console.Write("BUILD ERROR: Required Environment Variable is not set: "); + Console.WriteLine(envvar); + missing = true; + } + } + + return missing; + } +} diff --git a/Amazon/Scripts/Editor/AmazonBuildScript.cs.meta b/Amazon/Scripts/Editor/AmazonBuildScript.cs.meta new file mode 100644 index 0000000..8fe0170 --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonBuildScript.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c1378b372e98d4b56a16725bf370ae6c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/AmazonCoroutineExtensions.cs b/Amazon/Scripts/Editor/AmazonCoroutineExtensions.cs new file mode 100644 index 0000000..e0d6aee --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonCoroutineExtensions.cs @@ -0,0 +1,51 @@ +/* +Copyright (c) 2017 Marijn Zwemmer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +using System.Collections; +using UnityEditor; +namespace AmazonInternal.ThirdParty { + public static class AmazonCoroutineExtensions { + public static AmazonCoroutines.AmazonCoroutine StartCoroutine (this EditorWindow thisRef, IEnumerator coroutine) { + return AmazonCoroutines.StartCoroutine (coroutine, thisRef); + } + + public static AmazonCoroutines.AmazonCoroutine StartCoroutine (this EditorWindow thisRef, string methodName) { + return AmazonCoroutines.StartCoroutine (methodName, thisRef); + } + + public static AmazonCoroutines.AmazonCoroutine StartCoroutine (this EditorWindow thisRef, string methodName, object value) { + return AmazonCoroutines.StartCoroutine (methodName, value, thisRef); + } + + public static void StopCoroutine (this EditorWindow thisRef, IEnumerator coroutine) { + AmazonCoroutines.StopCoroutine (coroutine, thisRef); + } + + public static void StopCoroutine (this EditorWindow thisRef, string methodName) { + AmazonCoroutines.StopCoroutine (methodName, thisRef); + } + + public static void StopAllCoroutines (this EditorWindow thisRef) { + AmazonCoroutines.StopAllCoroutines (thisRef); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Editor/AmazonCoroutineExtensions.cs.meta b/Amazon/Scripts/Editor/AmazonCoroutineExtensions.cs.meta new file mode 100644 index 0000000..e05f050 --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonCoroutineExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aae61b43441904bbcbf7f24ff05e20d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/AmazonCoroutines.cs b/Amazon/Scripts/Editor/AmazonCoroutines.cs new file mode 100644 index 0000000..4815e2a --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonCoroutines.cs @@ -0,0 +1,351 @@ +/* +Copyright (c) 2017 Marijn Zwemmer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace AmazonInternal.ThirdParty { + public class AmazonCoroutines { + public class AmazonCoroutine { + public ICoroutineYield currentYield = new YieldDefault (); + public IEnumerator routine; + public string routineUniqueHash; + public string ownerUniqueHash; + public string MethodName = ""; + + public int ownerHash; + public string ownerType; + + public bool finished = false; + + public AmazonCoroutine (IEnumerator routine, int ownerHash, string ownerType) { + this.routine = routine; + this.ownerHash = ownerHash; + this.ownerType = ownerType; + ownerUniqueHash = ownerHash + "_" + ownerType; + + if (routine != null) { + string[] split = routine.ToString ().Split ('<', '>'); + if (split.Length == 3) { + this.MethodName = split[1]; + } + } + + routineUniqueHash = ownerHash + "_" + ownerType + "_" + MethodName; + } + + public AmazonCoroutine (string methodName, int ownerHash, string ownerType) { + MethodName = methodName; + this.ownerHash = ownerHash; + this.ownerType = ownerType; + ownerUniqueHash = ownerHash + "_" + ownerType; + routineUniqueHash = ownerHash + "_" + ownerType + "_" + MethodName; + } + } + + public interface ICoroutineYield { + bool IsDone (float deltaTime); + } + + struct YieldDefault : ICoroutineYield { + public bool IsDone (float deltaTime) { + return true; + } + } + + struct YieldWaitForSeconds : ICoroutineYield { + public float timeLeft; + + public bool IsDone (float deltaTime) { + timeLeft -= deltaTime; + return timeLeft < 0; + } + } + + struct YieldCustomYieldInstruction : ICoroutineYield { + public CustomYieldInstruction customYield; + + public bool IsDone (float deltaTime) { + return !customYield.keepWaiting; + } + } + + struct YieldWWW : ICoroutineYield { + public WWW Www; + + public bool IsDone (float deltaTime) { + return Www.isDone; + } + } + + struct YieldAsync : ICoroutineYield { + public AsyncOperation asyncOperation; + + public bool IsDone (float deltaTime) { + return asyncOperation.isDone; + } + } + + struct YieldNestedCoroutine : ICoroutineYield { + public AmazonCoroutine coroutine; + + public bool IsDone (float deltaTime) { + return coroutine.finished; + } + } + + static AmazonCoroutines instance = null; + + Dictionary> coroutineDict = new Dictionary> (); + List> tempCoroutineList = new List> (); + + Dictionary> coroutineOwnerDict = + new Dictionary> (); + + DateTime previousTimeSinceStartup; + + /// Starts a coroutine. + /// The coroutine to start. + /// Reference to the instance of the class containing the method. + public static AmazonCoroutine StartCoroutine (IEnumerator routine, object thisReference) { + CreateInstanceIfNeeded (); + return instance.GoStartCoroutine (routine, thisReference); + } + + /// Starts a coroutine. + /// The name of the coroutine method to start. + /// Reference to the instance of the class containing the method. + public static AmazonCoroutine StartCoroutine (string methodName, object thisReference) { + return StartCoroutine (methodName, null, thisReference); + } + + /// Starts a coroutine. + /// The name of the coroutine method to start. + /// The parameter to pass to the coroutine. + /// Reference to the instance of the class containing the method. + public static AmazonCoroutine StartCoroutine (string methodName, object value, object thisReference) { + MethodInfo methodInfo = thisReference.GetType () + .GetMethod (methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + if (methodInfo == null) { + Debug.LogError ("Coroutine '" + methodName + "' couldn't be started, the method doesn't exist!"); + } + object returnValue; + + if (value == null) { + returnValue = methodInfo.Invoke (thisReference, null); + } else { + returnValue = methodInfo.Invoke (thisReference, new object[] { value }); + } + + if (returnValue is IEnumerator) { + CreateInstanceIfNeeded (); + return instance.GoStartCoroutine ((IEnumerator) returnValue, thisReference); + } else { + Debug.LogError ("Coroutine '" + methodName + "' couldn't be started, the method doesn't return an IEnumerator!"); + } + + return null; + } + + /// Stops all coroutines being the routine running on the passed instance. + /// The coroutine to stop. + /// Reference to the instance of the class containing the method. + public static void StopCoroutine (IEnumerator routine, object thisReference) { + CreateInstanceIfNeeded (); + instance.GoStopCoroutine (routine, thisReference); + } + + /// + /// Stops all coroutines named methodName running on the passed instance. + /// The name of the coroutine method to stop. + /// Reference to the instance of the class containing the method. + public static void StopCoroutine (string methodName, object thisReference) { + CreateInstanceIfNeeded (); + instance.GoStopCoroutine (methodName, thisReference); + } + + /// + /// Stops all coroutines running on the passed instance. + /// Reference to the instance of the class containing the method. + public static void StopAllCoroutines (object thisReference) { + CreateInstanceIfNeeded (); + instance.GoStopAllCoroutines (thisReference); + } + + static void CreateInstanceIfNeeded () { + if (instance == null) { + instance = new AmazonCoroutines (); + instance.Initialize (); + } + } + + void Initialize () { + previousTimeSinceStartup = DateTime.Now; + EditorApplication.update += OnUpdate; + } + + void GoStopCoroutine (IEnumerator routine, object thisReference) { + GoStopActualRoutine (CreateCoroutine (routine, thisReference)); + } + + void GoStopCoroutine (string methodName, object thisReference) { + GoStopActualRoutine (CreateCoroutineFromString (methodName, thisReference)); + } + + void GoStopActualRoutine (AmazonCoroutine routine) { + if (coroutineDict.ContainsKey (routine.routineUniqueHash)) { + coroutineOwnerDict[routine.ownerUniqueHash].Remove (routine.routineUniqueHash); + coroutineDict.Remove (routine.routineUniqueHash); + } + } + + void GoStopAllCoroutines (object thisReference) { + AmazonCoroutine coroutine = CreateCoroutine (null, thisReference); + if (coroutineOwnerDict.ContainsKey (coroutine.ownerUniqueHash)) { + foreach (var couple in coroutineOwnerDict[coroutine.ownerUniqueHash]) { + coroutineDict.Remove (couple.Value.routineUniqueHash); + } + coroutineOwnerDict.Remove (coroutine.ownerUniqueHash); + } + } + + AmazonCoroutine GoStartCoroutine (IEnumerator routine, object thisReference) { + if (routine == null) { + Debug.LogException (new Exception ("IEnumerator is null!"), null); + } + AmazonCoroutine coroutine = CreateCoroutine (routine, thisReference); + GoStartCoroutine (coroutine); + return coroutine; + } + + void GoStartCoroutine (AmazonCoroutine coroutine) { + if (!coroutineDict.ContainsKey (coroutine.routineUniqueHash)) { + List newCoroutineList = new List (); + coroutineDict.Add (coroutine.routineUniqueHash, newCoroutineList); + } + coroutineDict[coroutine.routineUniqueHash].Add (coroutine); + + if (!coroutineOwnerDict.ContainsKey (coroutine.ownerUniqueHash)) { + Dictionary newCoroutineDict = new Dictionary (); + coroutineOwnerDict.Add (coroutine.ownerUniqueHash, newCoroutineDict); + } + + // If the method from the same owner has been stored before, it doesn't have to be stored anymore, + // One reference is enough in order for "StopAllCoroutines" to work + if (!coroutineOwnerDict[coroutine.ownerUniqueHash].ContainsKey (coroutine.routineUniqueHash)) { + coroutineOwnerDict[coroutine.ownerUniqueHash].Add (coroutine.routineUniqueHash, coroutine); + } + + MoveNext (coroutine); + } + + AmazonCoroutine CreateCoroutine (IEnumerator routine, object thisReference) { + return new AmazonCoroutine (routine, thisReference.GetHashCode (), thisReference.GetType ().ToString ()); + } + + AmazonCoroutine CreateCoroutineFromString (string methodName, object thisReference) { + return new AmazonCoroutine (methodName, thisReference.GetHashCode (), thisReference.GetType ().ToString ()); + } + + void OnUpdate () { + float deltaTime = (float) (DateTime.Now.Subtract (previousTimeSinceStartup).TotalMilliseconds / 1000.0f); + + previousTimeSinceStartup = DateTime.Now; + if (coroutineDict.Count == 0) { + return; + } + + tempCoroutineList.Clear (); + foreach (var pair in coroutineDict) + tempCoroutineList.Add (pair.Value); + + for (var i = tempCoroutineList.Count - 1; i >= 0; i--) { + List coroutines = tempCoroutineList[i]; + + for (int j = coroutines.Count - 1; j >= 0; j--) { + AmazonCoroutine coroutine = coroutines[j]; + + if (!coroutine.currentYield.IsDone (deltaTime)) { + continue; + } + + if (!MoveNext (coroutine)) { + coroutines.RemoveAt (j); + coroutine.currentYield = null; + coroutine.finished = true; + } + + if (coroutines.Count == 0) { + coroutineDict.Remove (coroutine.ownerUniqueHash); + } + } + } + } + + static bool MoveNext (AmazonCoroutine coroutine) { + if (coroutine.routine.MoveNext ()) { + return Process (coroutine); + } + + return false; + } + + // returns false if no next, returns true if OK + static bool Process (AmazonCoroutine coroutine) { + object current = coroutine.routine.Current; + if (current == null) { + coroutine.currentYield = new YieldDefault (); + } else if (current is WaitForSeconds) { + float seconds = float.Parse (GetInstanceField (typeof (WaitForSeconds), current, "m_Seconds").ToString ()); + coroutine.currentYield = new YieldWaitForSeconds () { timeLeft = seconds }; + } else if (current is CustomYieldInstruction) { + coroutine.currentYield = new YieldCustomYieldInstruction () { + customYield = current as CustomYieldInstruction + }; + } else if (current is WWW) { + coroutine.currentYield = new YieldWWW { Www = (WWW) current }; + } else if (current is WaitForFixedUpdate || current is WaitForEndOfFrame) { + coroutine.currentYield = new YieldDefault (); + } else if (current is AsyncOperation) { + coroutine.currentYield = new YieldAsync { asyncOperation = (AsyncOperation) current }; + } else if (current is AmazonCoroutine) { + coroutine.currentYield = new YieldNestedCoroutine { coroutine = (AmazonCoroutine) current }; + } else { + Debug.LogException ( + new Exception ("<" + coroutine.MethodName + "> yielded an unknown or unsupported type! (" + current.GetType () + ")"), + null); + coroutine.currentYield = new YieldDefault (); + } + return true; + } + + static object GetInstanceField (Type type, object instance, string fieldName) { + BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; + FieldInfo field = type.GetField (fieldName, bindFlags); + return field.GetValue (instance); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Editor/AmazonCoroutines.cs.meta b/Amazon/Scripts/Editor/AmazonCoroutines.cs.meta new file mode 100644 index 0000000..0e52197 --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonCoroutines.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dcee96832dc4141299f36d8b10b10467 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/AmazonDependencies.xml b/Amazon/Scripts/Editor/AmazonDependencies.xml new file mode 100644 index 0000000..979a6f6 --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonDependencies.xml @@ -0,0 +1,16 @@ + + + + + + + + https://aws.oss.sonatype.org/content/repositories/releases/ + + + + + + + + \ No newline at end of file diff --git a/Amazon/Scripts/Editor/AmazonDependencies.xml.meta b/Amazon/Scripts/Editor/AmazonDependencies.xml.meta new file mode 100644 index 0000000..ad2f0f9 --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonDependencies.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c9bc3db2384e74f03ae6d3b496e9fdc9 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/AmazonPostBuildiOS.cs b/Amazon/Scripts/Editor/AmazonPostBuildiOS.cs new file mode 100644 index 0000000..be5be2b --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonPostBuildiOS.cs @@ -0,0 +1,54 @@ +#if UNITY_IOS +using System.IO; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEditor.iOS.Xcode; +using UnityEngine; +namespace AmazonInternal.Editor.Postbuild { + public static class AmazonPostBuildiOS { + [PostProcessBuild( 45 )] + public static void OnPostprocessBuild(BuildTarget buildTarget, string path) + { + if (buildTarget != BuildTarget.iOS) + return; + + string pbxProjectPath = PBXProject.GetPBXProjectPath(path); + PBXProject project = new PBXProject(); + + project.ReadFromFile(pbxProjectPath); + +#if UNITY_2019_3_OR_NEWER + string targetGuid = project.GetUnityFrameworkTargetGuid(); +#else + string targetGuid = project.TargetGuidByName(PBXProject.GetUnityTargetName()); +#endif + project.SetBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "$(inherited)"); + project.SetBuildProperty(targetGuid, "CLANG_ENABLE_MODULES", "YES"); + project.AddBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks"); + + project.WriteToFile(pbxProjectPath); + +#if UNITY_2019_3_OR_NEWER + if (buildTarget == BuildTarget.iOS) + { + bool iPhoneExist = false; + using (StreamReader sr = new StreamReader(path + "/Podfile")) + { + string contents = sr.ReadToEnd(); + if (contents.Contains("Unity-iPhone")) + { + iPhoneExist = true; + } + } + if ( !iPhoneExist ){ + using (StreamWriter sw = File.AppendText(path + "/Podfile")) + { + sw.WriteLine("\ntarget 'Unity-iPhone' do\nend"); + } + } + } +#endif + } + } +} +#endif \ No newline at end of file diff --git a/Amazon/Scripts/Editor/AmazonPostBuildiOS.cs.meta b/Amazon/Scripts/Editor/AmazonPostBuildiOS.cs.meta new file mode 100644 index 0000000..52e2e0e --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonPostBuildiOS.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7474cff9dfc144e89f4e7696b4b8d9c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/AmazonSDKManager.cs b/Amazon/Scripts/Editor/AmazonSDKManager.cs new file mode 100644 index 0000000..2de5da2 --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonSDKManager.cs @@ -0,0 +1,400 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using AmazonInternal.ThirdParty; +using UnityEditor; +using UnityEditor.PackageManager; +using UnityEditor.PackageManager.Requests; +using UnityEngine; +using UnityEngine.Networking; +public class AmazonSDKManager : EditorWindow { + static string AmazonSdkVersion; + static AddRequest Request; + + static void AddEditorCoroutine () { + // Add a package to the Project + Request = Client.Add ("com.unity.editorcoroutine"); + EditorApplication.update += Progress; + } + + static void Progress () { + if (Request.IsCompleted) { + if (Request.Status == StatusCode.Success) + Debug.Log ("Installed: " + Request.Result.packageId); + else if (Request.Status >= StatusCode.Failure) + Debug.Log (Request.Error.message); + + EditorApplication.update -= Progress; + } + } + +// [MenuItem ("Amazon/About Amazon SDK", false, 0)] + public static void About () { + AmazonAboutDialog.ShowDialog (); + } + +// [MenuItem ("Amazon/Documentation...", false, 1)] + public static void Documentation () { + Application.OpenURL (AmazonConstants.docUrl); + } + +// [MenuItem ("Amazon/Manage SDKs...", false, 4)] + public static void SdkManagerProd () { + AmazonSDKManager.ShowSDKManager (); + } + + private const string downloadDir = "Assets/Amazon"; + + private struct SdkInfo { + public string Name; + public string Key; + public string Url; + public string LatestVersion; + public string CurrentVersion; + public string Filename; + + public bool FromJson (string name, Dictionary dict) { + if (string.IsNullOrEmpty (name) || dict == null) + return false; + + object obj; + Key = name; + if (dict.TryGetValue ("name", out obj)) + Name = obj as string; + if (dict.TryGetValue ("link", out obj)) + Url = obj as string; + if (dict.TryGetValue ("version", out obj)) + LatestVersion = obj as string; + if (!string.IsNullOrEmpty (Url)) { + var uri = new Uri (Url); + var path = uri.IsAbsoluteUri ? uri.AbsolutePath : uri.LocalPath; + Filename = Path.GetFileName (path); + } + return true; + } + + public bool FromConfig(AmazonPackageConfig config) + { + if (config == null || string.IsNullOrEmpty(config.Name) || !string.IsNullOrEmpty(Key) && Key != config.Name) + return false; + CurrentVersion = config.Version; + return true; + } + } + + // Version and download info for the SDK and network mediation adapters. + private static SdkInfo amazonSdkInfo; + private static readonly SortedDictionary sdkInfo = new SortedDictionary (); + + // Async download operations tracked here. + private AmazonCoroutines.AmazonCoroutine coroutine; + private UnityWebRequest downloader; + private string activity; + + // Custom style for LabelFields. (Don't make static or the dialog doesn't recover well from Unity compiling + // a new or changed editor script.) + private GUIStyle labelStyle; + private GUIStyle labelStyleArea; + private GUIStyle labelStyleLink; + private GUIStyle headerStyle; + private readonly GUILayoutOption fieldWidth = GUILayout.Width (60); + + private Vector2 scrollPos; + + public static void ShowSDKManager () { + var win = GetWindow (true); + win.titleContent = new GUIContent ("Amazon SDK Manager"); + win.Focus (); + } + + void Awake () { + labelStyle = new GUIStyle (EditorStyles.label) { + fontSize = 14, + fontStyle = FontStyle.Bold + }; + labelStyleArea = new GUIStyle (EditorStyles.label) { + wordWrap = true + }; + labelStyleLink = new GUIStyle (EditorStyles.label) { + normal = { textColor = Color.blue }, + active = { textColor = Color.white }, + }; + headerStyle = new GUIStyle (EditorStyles.label) { + fontSize = 12, + fontStyle = FontStyle.Bold, + fixedHeight = 18 + }; + CancelOperation (); + } + + void OnEnable () { + coroutine = this.StartCoroutine (GetSDKVersions ()); + } + + void OnDisable () { + CancelOperation (); + } + + public void deleteUnwantedFiles() + { + String[] filesToDel = + { + "Assets/Amazon/Scripts/Internal/AdResponce.cs", + "Assets/Amazon/Scripts/Internal/AdResponce.cs.meta", + "Assets/Amazon/Scripts/Internal/IOS/IOSAdResponce.cs", + "Assets/Amazon/Scripts/Internal/IOS/IOSAdResponce.cs.meta", + "Assets/Amazon/Scripts/Internal/Android/AndroidAdResponce.cs", + "Assets/Amazon/Scripts/Internal/Android/AndroidAdResponce.cs.meta", + "Assets/Amazon/Plugins/Android/aps-sdk.aar", + "Assets/Amazon/Plugins/Android/aps-sdk.aar.meta", + "Assets/Amazon/Scripts/Mediations/AdMobMediation/Plugins/Android/aps-admob-adapter.aar", + "Assets/Amazon/Scripts/Mediations/AdMobMediation/Plugins/Android/aps-admob-adapter.aar.meta", + "Assets/Amazon/Scripts/Mediations/APSConnectionUtil", + "Assets/Amazon/Scripts/Mediations/APSConnectionUtil.meta", + "Assets/Amazon/Scripts/Mediations/MoPubMediation", + "Assets/Amazon/Scripts/Mediations/MoPubMediation.meta", + "Assets/APSConnectionUtil", + "Assets/APSConnectionUtil.meta", + "Assets/Amazon/Sample/AmazonMoPubDemo.cs", + "Assets/Amazon/Sample/AmazonMoPubDemo.cs.meta", + "Assets/Amazon/Sample/APSMoPubMediation.unity", + "Assets/Amazon/Sample/APSMoPubMediation.unity.meta" + }; + + foreach (String fileToDel in filesToDel) + { + if (Directory.Exists(fileToDel)) + { + Directory.Delete(fileToDel, true); + } else if (File.Exists(fileToDel)) + { + File.Delete(fileToDel); + } + + } + } + + private IEnumerator GetSDKVersions () { + // Wait one frame so that we don't try to show the progress bar in the middle of OnGUI(). + yield return null; + + activity = "Downloading SDK version manifest..."; + + UnityWebRequest www = new UnityWebRequest (AmazonConstants.manifestURL) { + downloadHandler = new DownloadHandlerBuffer (), + timeout = 10, // seconds + }; + yield return www.SendWebRequest (); + + if (!string.IsNullOrEmpty (www.error)) { + Debug.LogError (www.error); + EditorUtility.DisplayDialog ( + "SDK Manager Service", + "The services we need are not accessible. Please consider integrating manually.\n\n" + + "For instructions, see " + AmazonConstants.helpLink, + "OK"); + } + + var json = www.downloadHandler.text; + if (string.IsNullOrEmpty (json)) { + json = "{}"; + Debug.LogError ("Unable to retrieve SDK version manifest. Showing installed SDKs only."); + } + www.Dispose (); + + // Got the file. Now extract info on latest SDKs available. + amazonSdkInfo = new SdkInfo (); + sdkInfo.Clear (); + var dict = Json.Deserialize (json) as Dictionary; + if (dict != null) { + object obj; + if (dict.TryGetValue ("sdk", out obj)) { + amazonSdkInfo.FromJson ("sdk", obj as Dictionary); + amazonSdkInfo.CurrentVersion = AmazonConstants.VERSION; + } + if (dict.TryGetValue ("adapters", out obj)){ + var info = new SdkInfo (); + foreach (var item in obj as Dictionary) { + if (info.FromJson (item.Key, item.Value as Dictionary)) + sdkInfo[info.Key] = info; + } + + } + } + + var baseType = typeof(AmazonPackageConfig); + var configs = from t in Assembly.GetExecutingAssembly().GetTypes() + where t.IsSubclassOf(baseType) && !t.IsAbstract + select Activator.CreateInstance(t) as AmazonPackageConfig; + foreach (var config in configs) { + SdkInfo info; + sdkInfo.TryGetValue(config.Name, out info); + if (info.FromConfig(config) && info.Key != null) + sdkInfo[info.Key] = info; + } + coroutine = null; + + deleteUnwantedFiles(); + Repaint (); + } + + void OnGUI () { + // Is any async job in progress? + var stillWorking = coroutine != null || downloader != null; + + GUILayout.Space (5); + EditorGUILayout.LabelField ("Amazon SDKs", labelStyle, GUILayout.Height (20)); + using (new EditorGUILayout.VerticalScope("box")) { + SdkHeaders(); + SdkRow(amazonSdkInfo); + } + + if (sdkInfo.Count > 0) { + GUILayout.Space (5); + EditorGUILayout.LabelField ("Mediated Networks", labelStyle, GUILayout.Height (20)); + using (new EditorGUILayout.VerticalScope ("box")) + using (var s = new EditorGUILayout.ScrollViewScope (scrollPos, false, false)) { + scrollPos = s.scrollPosition; + SdkHeaders (); + foreach (var item in sdkInfo) + SdkRow (item.Value); + } + } + + // Indicate async operation in progress. + using (new EditorGUILayout.HorizontalScope (GUILayout.ExpandWidth (false))) + EditorGUILayout.LabelField (stillWorking ? activity : " "); + + using (new EditorGUILayout.HorizontalScope ()) { + GUILayout.Space (10); + if (!stillWorking) { + if (GUILayout.Button ("Done", fieldWidth)) + Close (); + } else { + if (GUILayout.Button ("Cancel", fieldWidth)) + CancelOperation (); + } + if (GUILayout.Button ("Help", fieldWidth)) + Application.OpenURL (AmazonConstants.helpLink); + } + } + + private void SdkHeaders () { + using (new EditorGUILayout.HorizontalScope (GUILayout.ExpandWidth (false))) { + GUILayout.Space (10); + EditorGUILayout.LabelField ("Package", headerStyle); + GUILayout.Button ("Version", headerStyle); + GUILayout.Space (3); + GUILayout.Button ("Action", headerStyle, fieldWidth); + GUILayout.Button (" ", headerStyle, GUILayout.Width (1)); + GUILayout.Space (5); + } + GUILayout.Space (4); + } + + private void SdkRow (SdkInfo info, Func customButton = null) { + var lat = info.LatestVersion; + var cur = info.CurrentVersion; + var isInst = !string.IsNullOrEmpty (cur); + var canInst = !string.IsNullOrEmpty (lat) && (!isInst || AmazonUtils.CompareVersions (cur, lat) < 0); + // Is any async job in progress? + var stillWorking = coroutine != null || downloader != null; + + string tooltip = string.Empty; + if (isInst && (AmazonUtils.CompareVersions (cur, lat) != 0)) + tooltip += "\n Installed: " + cur; + if (!string.IsNullOrEmpty (tooltip)) + tooltip = info.Name + "\n Package: " + (lat ?? "n/a") + tooltip; + + GUILayout.Space (4); + using (new EditorGUILayout.HorizontalScope (GUILayout.ExpandWidth (false))) { + GUILayout.Space (10); + EditorGUILayout.LabelField (new GUIContent { text = info.Name, tooltip = tooltip }); + GUILayout.Button (new GUIContent { + text = lat ?? "--", + tooltip = tooltip + }, canInst ? EditorStyles.boldLabel : EditorStyles.label); + GUILayout.Space (3); + if (customButton == null || !customButton (canInst)) { + GUI.enabled = !stillWorking && (canInst); + if (GUILayout.Button (new GUIContent { + text = isInst ? "Upgrade" : "Install", + tooltip = tooltip + }, fieldWidth)) + this.StartCoroutine (DownloadSDK (info)); + GUI.enabled = true; + } + // Need to fill space so that the Install/Upgrade buttons all line up nicely. + GUILayout.Button (" ", EditorStyles.label, GUILayout.Width (17)); + GUILayout.Space (5); + } + GUILayout.Space (4); + } + + private void CancelOperation () { + // Stop any async action taking place. + + if (downloader != null) { + downloader.Abort (); // The coroutine should resume and clean up. + return; + } + + if (coroutine != null) + this.StopCoroutine (coroutine.routine); + coroutine = null; + downloader = null; + } + + private IEnumerator DownloadSDK (SdkInfo info) { + var path = Path.Combine (downloadDir, info.Filename); + + activity = string.Format ("Downloading {0}...", info.Filename); + Debug.Log (activity); + + // Start the async download job. + downloader = new UnityWebRequest (info.Url) { + downloadHandler = new DownloadHandlerFile (path), + timeout = 60, // seconds + }; + downloader.SendWebRequest (); + + // Pause until download done/cancelled/fails, keeping progress bar up to date. + while (!downloader.isDone) { + yield return null; + var progress = Mathf.FloorToInt (downloader.downloadProgress * 100); + if (EditorUtility.DisplayCancelableProgressBar ("Amazon SDK Manager", activity, progress)) + downloader.Abort (); + } + EditorUtility.ClearProgressBar (); + + if (string.IsNullOrEmpty (downloader.error)) + AssetDatabase.ImportPackage (path, true); // OK, got the file, so let the user import it if they want. + else { + var error = downloader.error; + if (downloader.isNetworkError) { + if (error.EndsWith ("destination host")) + error += ": " + info.Url; + } else if (downloader.isHttpError) { + switch (downloader.responseCode) { + case 404: + var file = Path.GetFileName (new Uri (info.Url).LocalPath); + error = string.Format ("File {0} not found on server.", file); + break; + default: + error = downloader.responseCode + "\n" + error; + break; + } + } + + Debug.LogError (error); + } + + // Reset async state so the GUI is operational again. + downloader.Dispose (); + downloader = null; + coroutine = null; + } +} diff --git a/Amazon/Scripts/Editor/AmazonSDKManager.cs.meta b/Amazon/Scripts/Editor/AmazonSDKManager.cs.meta new file mode 100644 index 0000000..ad401dd --- /dev/null +++ b/Amazon/Scripts/Editor/AmazonSDKManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9436cb85e61464fbb8e7434090ec1af2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/Tests.meta b/Amazon/Scripts/Editor/Tests.meta new file mode 100644 index 0000000..86157cb --- /dev/null +++ b/Amazon/Scripts/Editor/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e64d0b097e7e04e59b22cd2d61ff42a5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs b/Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs new file mode 100644 index 0000000..adc473f --- /dev/null +++ b/Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs @@ -0,0 +1,41 @@ +using System; +using NUnit.Framework; +using UnityEngine; + +// ReSharper disable Unity.IncorrectMonoBehaviourInstantiation + +namespace Tests +{ + + public class AmazonSDKTests : AmazonTest + { + [Test] + public void EmitAdLoadedEventShouldTriggerOnAdLoadedEvent() + { + TestEmitAdLoadedEvent(new AmazonAds.Android.AndroidAdResponse()); + } + + + private static void TestEmitAdLoadedEvent(AmazonAds.AdResponse response) + { + const string successMessage = "OnAdLoadedEvent triggered."; + AmazonAds.Amazon.OnSuccessDelegate successHandler = (_response) => { + Assert.That(_response, Is.EqualTo(response)); + Debug.Log(successMessage); + }; + + const string failureMessage = "OnAdFailedEvent triggered."; + AmazonAds.Amazon.OnFailureDelegate failureHandler = (_error) => { + Debug.Log(failureMessage); + }; + + + try { + successHandler.Invoke(response); + failureHandler.Invoke("123"); + } finally { + + } + } + } +} diff --git a/Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs.meta b/Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs.meta new file mode 100644 index 0000000..88df821 --- /dev/null +++ b/Amazon/Scripts/Editor/Tests/AmazonSDKTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b00fb31f302f4b26a43151fd12cffbc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/Tests/AmazonTest.cs b/Amazon/Scripts/Editor/Tests/AmazonTest.cs new file mode 100644 index 0000000..33e3466 --- /dev/null +++ b/Amazon/Scripts/Editor/Tests/AmazonTest.cs @@ -0,0 +1,14 @@ +using UnityEngine; +using UnityEngine.TestTools; + +public class AmazonTest +{ + public static class LogAssert + { + public static void Expect(LogType logType, string message) + { + UnityEngine.TestTools.LogAssert.Expect(logType, message); + Debug.LogFormat("The previous {0} log was expected.", logType); + } + } +} diff --git a/Amazon/Scripts/Editor/Tests/AmazonTest.cs.meta b/Amazon/Scripts/Editor/Tests/AmazonTest.cs.meta new file mode 100644 index 0000000..372fa7c --- /dev/null +++ b/Amazon/Scripts/Editor/Tests/AmazonTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fe3a64de565fa4daa9ac26c80cdb1f6e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Editor/Tests/AmazonUtilsTests.cs b/Amazon/Scripts/Editor/Tests/AmazonUtilsTests.cs new file mode 100644 index 0000000..9ef1da0 --- /dev/null +++ b/Amazon/Scripts/Editor/Tests/AmazonUtilsTests.cs @@ -0,0 +1,102 @@ +using NUnit.Framework; +using UnityEngine; + +namespace Tests +{ + public class AmazonUtilsTests : AmazonTest + { + [Test] + public void CompareVersionsWithFirstSmaller() + { + Assert.That(AmazonUtils.CompareVersions("0", "1"), Is.EqualTo(-1)); + Assert.That(AmazonUtils.CompareVersions("0.9", "1.0"), Is.EqualTo(-1)); + Assert.That(AmazonUtils.CompareVersions("0.9.99", "1.0.0"), Is.EqualTo(-1)); + Assert.That(AmazonUtils.CompareVersions("0.9.99", "0.10.0"), Is.EqualTo(-1)); + Assert.That(AmazonUtils.CompareVersions("0.9.99", "0.9.100"), Is.EqualTo(-1)); + } + + [Test] + public void CompareVersionsWithFirstGreater() + { + Assert.That(AmazonUtils.CompareVersions("1", "0"), Is.EqualTo(1)); + Assert.That(AmazonUtils.CompareVersions("1.0", "0.9"), Is.EqualTo(1)); + Assert.That(AmazonUtils.CompareVersions("1.0.0", "0.9.99"), Is.EqualTo(1)); + Assert.That(AmazonUtils.CompareVersions("0.10.0", "0.9.99"), Is.EqualTo(1)); + Assert.That(AmazonUtils.CompareVersions("0.9.100", "0.9.99"), Is.EqualTo(1)); + } + + [Test] + public void CompareVersionsWithEqual() + { + Assert.That(AmazonUtils.CompareVersions("1", "1"), Is.EqualTo(0)); + Assert.That(AmazonUtils.CompareVersions("1.0", "1.0"), Is.EqualTo(0)); + Assert.That(AmazonUtils.CompareVersions("1.0.0", "1.0.0"), Is.EqualTo(0)); + } + + [Test] + public void CompareVersionsWithEmptyValues() + { + Assert.That(AmazonUtils.CompareVersions("", ""), Is.EqualTo(0)); + Assert.That(AmazonUtils.CompareVersions("", "1"), Is.EqualTo(-1)); + Assert.That(AmazonUtils.CompareVersions("1", ""), Is.EqualTo(1)); + Assert.That(AmazonUtils.CompareVersions(null, null), Is.EqualTo(0)); + Assert.That(AmazonUtils.CompareVersions(null, "1"), Is.EqualTo(-1)); + Assert.That(AmazonUtils.CompareVersions("1", null), Is.EqualTo(1)); + } + + [Test] + public void DecodeArgsWithNullShouldErrorAndYieldEmptyList() + { + var res = AmazonUtils.DecodeArgs(null, 0); + + LogAssert.Expect(LogType.Error, "Invalid JSON data: "); + Assert.That(res, Is.Not.Null); + Assert.That(res.Length, Is.EqualTo(0)); + } + + [Test] + public void DecodeArgsWithInvalidShouldErrorAndYieldEmptyList() + { + var res = AmazonUtils.DecodeArgs("{\"a\"]", 0); + + LogAssert.Expect(LogType.Error, "Invalid JSON data: {\"a\"]"); + Assert.That(res, Is.Not.Null); + Assert.That(res.Length, Is.EqualTo(0)); + } + + [Test] + public void DecodeArgsWithValueShouldYieldListWithValue() + { + var res = AmazonUtils.DecodeArgs("[\"a\"]", 0); + + Assert.That(res, Is.Not.Null); + Assert.That(res.Length, Is.EqualTo(1)); + Assert.That(res[0], Is.EqualTo("a")); + } + + [Test] + public void DecodeArgsWithoutMinimumValuesShouldErrorAndYieldListWithDesiredLength() + { + var res = AmazonUtils.DecodeArgs("[\"a\", \"b\"]", 3); + + LogAssert.Expect(LogType.Error, "Missing one or more values: [\"a\", \"b\"] (expected 3)"); + Assert.That(res, Is.Not.Null); + Assert.That(res.Length, Is.EqualTo(3)); + Assert.That(res[0], Is.EqualTo("a")); + Assert.That(res[1], Is.EqualTo("b")); + Assert.That(res[2], Is.EqualTo("")); + } + + [Test] + public void DecodeArgsWithExpectedValuesShouldYieldListWithDesiredValues() + { + var res = AmazonUtils.DecodeArgs("[\"a\", \"b\", \"c\"]", 3); + + Assert.That(res, Is.Not.Null); + Assert.That(res.Length, Is.EqualTo(3)); + Assert.That(res[0], Is.EqualTo("a")); + Assert.That(res[1], Is.EqualTo("b")); + Assert.That(res[2], Is.EqualTo("c")); + } + } +} diff --git a/Amazon/Scripts/Editor/Tests/AmazonUtilsTests.cs.meta b/Amazon/Scripts/Editor/Tests/AmazonUtilsTests.cs.meta new file mode 100644 index 0000000..de0683f --- /dev/null +++ b/Amazon/Scripts/Editor/Tests/AmazonUtilsTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e4a38f41a15b0444380ccd4a74a12ac2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal.meta b/Amazon/Scripts/Internal.meta new file mode 100644 index 0000000..105edc6 --- /dev/null +++ b/Amazon/Scripts/Internal.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3eac84282b79049f0bbadc32296d7b29 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/APSAdDelegate.cs b/Amazon/Scripts/Internal/APSAdDelegate.cs new file mode 100644 index 0000000..a2d960f --- /dev/null +++ b/Amazon/Scripts/Internal/APSAdDelegate.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; + +namespace AmazonAds { + public class APSAdDelegate { + public delegate void OnAdLoaded (); + public delegate void OnAdFailed (); + public delegate void OnAdClicked (); + public delegate void OnAdOpen (); + public delegate void OnAdClosed (); + public delegate void OnImpressionFired (); + public delegate void OnVideoCompleted (); + + public OnAdLoaded onAdLoaded = OnAdLoadedImpl; + public OnAdFailed onAdFailed = OnAdFailedImpl; + public OnAdClicked onAdClicked = OnAdClickedImpl; + public OnAdOpen onAdOpen = OnAdOpenImpl; + public OnAdClosed onAdClosed = OnAdClosedImpl; + public OnImpressionFired onImpressionFired = OnImpressionFiredImpl; + public OnVideoCompleted onVideoCompleted = OnVideoCompletedImpl; + + public APSAdDelegate () { + + } + + private static void OnAdLoadedImpl () { } + private static void OnAdFailedImpl () { } + private static void OnAdClickedImpl () { } + private static void OnAdOpenImpl () { } + private static void OnAdClosedImpl () { } + private static void OnImpressionFiredImpl () { } + private static void OnVideoCompletedImpl () { } + } +} diff --git a/Amazon/Scripts/Internal/APSAdDelegate.cs.meta b/Amazon/Scripts/Internal/APSAdDelegate.cs.meta new file mode 100644 index 0000000..e2c3bdb --- /dev/null +++ b/Amazon/Scripts/Internal/APSAdDelegate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d06f90422ce794d848656240f4d00aae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/APSBannerAdRequest.cs b/Amazon/Scripts/Internal/APSBannerAdRequest.cs new file mode 100644 index 0000000..2499c4c --- /dev/null +++ b/Amazon/Scripts/Internal/APSBannerAdRequest.cs @@ -0,0 +1,88 @@ +namespace AmazonAds { + public class APSBannerAdRequest : AdRequest { + + public APSBannerAdRequest () : base() { + Amazon.OnApplicationPause += OnApplicationPause; + } + + public APSBannerAdRequest (string slotGroupName) : base() { + Amazon.OnApplicationPause += OnApplicationPause; + client.SetSlotGroup (slotGroupName); + } + + public APSBannerAdRequest (int width, int height, string uid) : base() { + Amazon.OnApplicationPause += OnApplicationPause; + AdSize size = new AdSize (width, height, uid); + client.SetSizes (size.GetInstance ()); + } + + public APSBannerAdRequest (AdSize size) { + Amazon.OnApplicationPause += OnApplicationPause; + client.SetSizes (size.GetInstance ()); + } + + public void LoadSmartBanner () { + if (onSuccess != null && onFailed != null) { + client.LoadSmartBanner (onFailed, onSuccess); + } else if (onSuccess != null && onFailedWithError != null) { + client.LoadSmartBanner (onFailedWithError, onSuccess); + } + } + + public void SetSizes (int width, int height, string uid) { + AdSize size = new AdSize (width, height, uid); + SetSizes (size); + } + + public void SetSizes (AdSize size) { + client.SetSizes (size.GetInstance ()); + } + + public void SetSlotGroup (string slotGroupName) { + client.SetSlotGroup (slotGroupName); + } + + public void SetAutoRefreshAdMob (bool flag, bool isSmartBanner = false) { + client.SetAutoRefreshAdMob (flag, isSmartBanner); + } + + public void SetAutoRefreshMoPub (bool flag, int refreshTime) { + client.SetAutoRefreshMoPub (flag, refreshTime); + } + + public void DisposeAd () { + client.DisposeAd (); + } + + public void IsAutoRefreshAdMob () { + client.IsAutoRefreshAdMob (); + } + + public void IsAutoRefreshMoPub () { + client.IsAutoRefreshMoPub (); + } + public string AutoRefreshID () { + return client.AutoRefreshID (); + } + + public void CreateFetchManager (bool isSmartBanner = false) { + client.CreateFetchManager (isSmartBanner); + } + + public void DestroyFetchManager () { + client.DestroyFetchManager (); + } + + public void OnApplicationPause (bool isPaused) { + if (isPaused) { + if( client.IsAutoRefreshAdMob() ){ + client.StopFetchManager(); + } + } else { + if( client.IsAutoRefreshAdMob() ){ + client.StartFetchManager(); + } + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/APSBannerAdRequest.cs.meta b/Amazon/Scripts/Internal/APSBannerAdRequest.cs.meta new file mode 100644 index 0000000..a0d7ff0 --- /dev/null +++ b/Amazon/Scripts/Internal/APSBannerAdRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 62abdd252c1aa49beb917ca0a7b4d3b3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/APSInterstitialAdRequest.cs b/Amazon/Scripts/Internal/APSInterstitialAdRequest.cs new file mode 100644 index 0000000..de87e9e --- /dev/null +++ b/Amazon/Scripts/Internal/APSInterstitialAdRequest.cs @@ -0,0 +1,8 @@ +namespace AmazonAds { + public class APSInterstitialAdRequest : AdRequest { + public APSInterstitialAdRequest (string uid) { + AdSize.InterstitialAdSize size = new AdSize.InterstitialAdSize (uid); + client.SetSizes (size.GetInstance ()); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/APSInterstitialAdRequest.cs.meta b/Amazon/Scripts/Internal/APSInterstitialAdRequest.cs.meta new file mode 100644 index 0000000..95fc792 --- /dev/null +++ b/Amazon/Scripts/Internal/APSInterstitialAdRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a60589c70736841a6b26fa39087d8e98 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/APSMediationUtils.cs b/Amazon/Scripts/Internal/APSMediationUtils.cs new file mode 100644 index 0000000..4ef747a --- /dev/null +++ b/Amazon/Scripts/Internal/APSMediationUtils.cs @@ -0,0 +1,41 @@ +using System; +using UnityEngine; + +namespace AmazonAds { + public class APSMediationUtils + { + public static string APS_IRON_SOURCE_NETWORK_KEY = "APS"; + + public static string GetInterstitialNetworkData(string amazonSlotId, string bidInfo, string pricePoint) + { + APSIronSourceNetworkBaseInputData ironSourceInputData = new APSIronSourceNetworkBaseInputData(); + ironSourceInputData.bidInfo = bidInfo; + ironSourceInputData.pricePointEncoded = pricePoint; + ironSourceInputData.uuid = amazonSlotId; + + APSIronSourceInterstitialNetworkData networkData = new APSIronSourceInterstitialNetworkData(); + networkData.interstitial = ironSourceInputData; + + string jsonData = "{ \"interstitial\" :" + JsonUtility.ToJson(ironSourceInputData) + "}"; + return jsonData; + + //return JsonUtility.ToJson(networkData); + } + + public class APSIronSourceNetworkBaseInputData + { + public string bidInfo; + public string pricePointEncoded; + public string uuid; + } + + public class APSIronSourceInterstitialNetworkData + { + public APSIronSourceNetworkBaseInputData interstitial; + } + + private APSMediationUtils() + { + } + } +} diff --git a/Amazon/Scripts/Internal/APSMediationUtils.cs.meta b/Amazon/Scripts/Internal/APSMediationUtils.cs.meta new file mode 100644 index 0000000..e90afa5 --- /dev/null +++ b/Amazon/Scripts/Internal/APSMediationUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9a84a300e9084005845d7561b5941de +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/APSVideoAdRequest.cs b/Amazon/Scripts/Internal/APSVideoAdRequest.cs new file mode 100644 index 0000000..69bebcb --- /dev/null +++ b/Amazon/Scripts/Internal/APSVideoAdRequest.cs @@ -0,0 +1,8 @@ +namespace AmazonAds { + public class APSVideoAdRequest : AdRequest { + public APSVideoAdRequest (int width, int height, string uid) { + AdSize.Video size = new AdSize.Video (width, height, uid); + client.SetSizes (size.GetInstance ()); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/APSVideoAdRequest.cs.meta b/Amazon/Scripts/Internal/APSVideoAdRequest.cs.meta new file mode 100644 index 0000000..6891e4f --- /dev/null +++ b/Amazon/Scripts/Internal/APSVideoAdRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f887445d62a094bdcaeba6843c76de52 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AdError.cs b/Amazon/Scripts/Internal/AdError.cs new file mode 100644 index 0000000..2787b9d --- /dev/null +++ b/Amazon/Scripts/Internal/AdError.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds { + public class AdError { + private int errorCode; + private String errorMessage; + private AdRequest adLoader; + private AndroidJavaObject adError; + private IntPtr adErrorPtr; + + public AdError(int code, String message) { + errorCode = code; + errorMessage = message; + } + + public int GetCode () { + return errorCode; + } + + public String GetMessage() { + return errorMessage; + } + + public AdRequest GetAdLoader() { + return adLoader; + } + +#if UNITY_ANDROID + public AndroidJavaObject GetAdError() { + return adError; + } +#else + public IntPtr GetAdError() + { + return adErrorPtr; + } +#endif + + public IntPtr GetInstance() { + return adErrorPtr; + } + + internal void SetAdLoader(AdRequest adRequest) { + adLoader = adRequest; + } + + internal void SetAdError(AndroidJavaObject error) { + adError = error; + } + + internal void SetInstance(IntPtr inPtr) { + adErrorPtr = inPtr; + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AdError.cs.meta b/Amazon/Scripts/Internal/AdError.cs.meta new file mode 100644 index 0000000..870b541 --- /dev/null +++ b/Amazon/Scripts/Internal/AdError.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 56cbe6c6e32004910b2c76cefbf4e0c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AdInterstitial.cs b/Amazon/Scripts/Internal/AdInterstitial.cs new file mode 100644 index 0000000..33485d8 --- /dev/null +++ b/Amazon/Scripts/Internal/AdInterstitial.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +namespace AmazonAds { + public class AdInterstitial { + internal IAdInterstitial adInterstital; + + public AdInterstitial (APSAdDelegate delegates) { + #if UNITY_ANDROID + adInterstital = new Android.AndroidAdInterstitial(delegates); + #elif UNITY_IOS + adInterstital = new IOS.IOSAdInterstitial(delegates); + #else + //Other platforms not supported + #endif + } + + public void FetchAd (AdResponse adResponse) { + adInterstital.FetchAd(adResponse); + } + + public void Show () { + adInterstital.Show(); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AdInterstitial.cs.meta b/Amazon/Scripts/Internal/AdInterstitial.cs.meta new file mode 100644 index 0000000..de5b71b --- /dev/null +++ b/Amazon/Scripts/Internal/AdInterstitial.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6b4a1dc9a6eb4aac89ddfeb50a829a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AdNetworkInfo.cs b/Amazon/Scripts/Internal/AdNetworkInfo.cs new file mode 100644 index 0000000..574f126 --- /dev/null +++ b/Amazon/Scripts/Internal/AdNetworkInfo.cs @@ -0,0 +1,30 @@ +using System; + +namespace AmazonAds { + public enum DTBAdNetwork { + GOOGLE_AD_MANAGER, + MOPUB_AD_SERVER, + ADMOB, + AD_GENERATION, + IRON_SOURCE, + MAX, + NIMBUS, + OTHER + } + + public class AdNetworkInfo { + private DTBAdNetwork adNetwork; + + public AdNetworkInfo(DTBAdNetwork dtbAdNetwork) { + adNetwork = dtbAdNetwork; + } + + public String getAdNetworkName() { + return adNetwork.ToString(); + } + + internal DTBAdNetwork getAdNetwork() { + return adNetwork; + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AdNetworkInfo.cs.meta b/Amazon/Scripts/Internal/AdNetworkInfo.cs.meta new file mode 100644 index 0000000..95b41e8 --- /dev/null +++ b/Amazon/Scripts/Internal/AdNetworkInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86929efe844004ce4a245fed201d6f9b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AdRequest.cs b/Amazon/Scripts/Internal/AdRequest.cs new file mode 100644 index 0000000..3e340a1 --- /dev/null +++ b/Amazon/Scripts/Internal/AdRequest.cs @@ -0,0 +1,59 @@ +using UnityEngine; +namespace AmazonAds { + public class AdRequest { + internal IAdRequest client; + public Amazon.OnFailureDelegate onFailed; + public Amazon.OnFailureWithErrorDelegate onFailedWithError; + public Amazon.OnSuccessDelegate onSuccess; + + public AdRequest () { +#if UNITY_ANDROID + client = new Android.DTBAdRequest (); +#elif UNITY_IOS + client = new IOS.DTBAdRequest (); +#else + //Other platforms not supported +#endif + } + + public AdRequest (IAdRequest adRequest) { + client = adRequest; + } + + public void PutCustomTarget (string key, string value) { + client.PutCustomTarget (key, value); + } + + public void SetRefreshFlag (bool flag) { + client.SetRefreshFlag(flag); + } + + public void SetAutoRefresh() { + client.SetAutoRefresh(); + } + + public void SetAutoRefresh(int secs) { + client.SetAutoRefresh(secs); + } + + public void ResumeAutoRefresh() { + client.ResumeAutoRefresh(); + } + + public void StopAutoRefresh() { + client.StopAutoRefresh(); + } + + public void PauseAutoRefresh() { + client.PauseAutoRefresh(); + } + + public void LoadAd () { + if (onSuccess != null && onFailed != null) { + client.LoadAd (onFailed, onSuccess); + } else if (onSuccess != null && onFailedWithError != null) { + client.LoadAd (onFailedWithError, onSuccess); + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AdRequest.cs.meta b/Amazon/Scripts/Internal/AdRequest.cs.meta new file mode 100644 index 0000000..9dd12d2 --- /dev/null +++ b/Amazon/Scripts/Internal/AdRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 470ce0a8c403f4531ac94b5ebe2ea5f4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AdResponce.cs b/Amazon/Scripts/Internal/AdResponce.cs new file mode 100644 index 0000000..c02e32c --- /dev/null +++ b/Amazon/Scripts/Internal/AdResponce.cs @@ -0,0 +1,4 @@ +namespace AmazonAds { + public abstract class AdResponseObsolete { + } +} diff --git a/Amazon/Scripts/Internal/AdResponce.cs.meta b/Amazon/Scripts/Internal/AdResponce.cs.meta new file mode 100644 index 0000000..928912a --- /dev/null +++ b/Amazon/Scripts/Internal/AdResponce.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07d84938416874bbb97e941098b24279 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AdResponse.cs b/Amazon/Scripts/Internal/AdResponse.cs new file mode 100644 index 0000000..782a30c --- /dev/null +++ b/Amazon/Scripts/Internal/AdResponse.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds { + public abstract class AdResponse { + public abstract String GetMoPubKeywords (); + public abstract IntPtr GetInstance(); + public abstract Dictionary GetRendering (bool isSmartBanner = false, string fetchLabel = null); + public abstract AdRequest GetAdLoader(); + public abstract String GetBidInfo(); + public abstract String GetPricePoint(); + public abstract int GetWidth(); + public abstract int GetHeight(); + public abstract String GetMediationHints(bool isSmartBanner = false); + internal abstract void SetAdLoader(AdRequest adRequest); + + public abstract IntPtr GetIosResponseObject(); + public abstract AndroidJavaObject GetAndroidResponseObject(); + +#if UNITY_ANDROID + public abstract AndroidJavaObject GetResponse(); +#else + public abstract IntPtr GetResponse(); +#endif + + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AdResponse.cs.meta b/Amazon/Scripts/Internal/AdResponse.cs.meta new file mode 100644 index 0000000..8003906 --- /dev/null +++ b/Amazon/Scripts/Internal/AdResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 80115d4cd111a4902804a0557a637367 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AdSize.cs b/Amazon/Scripts/Internal/AdSize.cs new file mode 100644 index 0000000..8572694 --- /dev/null +++ b/Amazon/Scripts/Internal/AdSize.cs @@ -0,0 +1,47 @@ +using System; + +namespace AmazonAds { + public class AdSize { + IAdSize client; + public AdSize (int width, int height, String slotUID) { +#if UNITY_ANDROID + client = new Android.DTBAdSize (width, height, slotUID); +#elif UNITY_IOS + client = new IOS.DTBAdSize (width, height, slotUID); +#endif + } + public IAdSize GetInstance () { + return client; + } + + public class InterstitialAdSize { + IInterstitialAdSize client; + public InterstitialAdSize (String slotUID) { +#if UNITY_ANDROID + client = new Android.DTBAdSize.DTBInterstitialAdSize (slotUID); +#elif UNITY_IOS + client = new IOS.DTBAdSize.DTBInterstitialAdSize (slotUID); +#endif + } + + public IInterstitialAdSize GetInstance () { + return client; + } + } + + public class Video { + IVideo client; + public Video (int playerWidth, int playerHeight, String slotUUID) { +#if UNITY_ANDROID + client = new Android.DTBAdSize.DTBVideo (playerWidth, playerHeight, slotUUID); +#elif UNITY_IOS + client = new IOS.DTBAdSize.DTBVideo (playerWidth, playerHeight, slotUUID); +#endif + } + + public IVideo GetInstance () { + return client; + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AdSize.cs.meta b/Amazon/Scripts/Internal/AdSize.cs.meta new file mode 100644 index 0000000..3ac671a --- /dev/null +++ b/Amazon/Scripts/Internal/AdSize.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6669e9284e4b5497fb351ae7bcb28436 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AdView.cs b/Amazon/Scripts/Internal/AdView.cs new file mode 100644 index 0000000..fbf3c39 --- /dev/null +++ b/Amazon/Scripts/Internal/AdView.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace AmazonAds { + public class AdView { + internal IAdView adView; + + public AdView (AdSize adSize, APSAdDelegate delegates) { + #if UNITY_ANDROID + adView = new Android.AndroidAdView(delegates); + #elif UNITY_IOS + adView = new IOS.IOSAdView(adSize, delegates); + #else + //Other platforms not supported + #endif + } + + public void fetchAd (AdResponse adResponse) { + adView.FetchAd(adResponse); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AdView.cs.meta b/Amazon/Scripts/Internal/AdView.cs.meta new file mode 100644 index 0000000..575a4d3 --- /dev/null +++ b/Amazon/Scripts/Internal/AdView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae0729fd51c4548638665a625582c64e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AmazonPackageConfig.cs b/Amazon/Scripts/Internal/AmazonPackageConfig.cs new file mode 100644 index 0000000..7b288fb --- /dev/null +++ b/Amazon/Scripts/Internal/AmazonPackageConfig.cs @@ -0,0 +1,4 @@ +public abstract class AmazonPackageConfig { + public abstract string Name { get; } + public abstract string Version { get; } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AmazonPackageConfig.cs.meta b/Amazon/Scripts/Internal/AmazonPackageConfig.cs.meta new file mode 100644 index 0000000..29bd54c --- /dev/null +++ b/Amazon/Scripts/Internal/AmazonPackageConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c289908250a174f72824418c6968e5f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/AmazonUtils.cs b/Amazon/Scripts/Internal/AmazonUtils.cs new file mode 100644 index 0000000..6ce8934 --- /dev/null +++ b/Amazon/Scripts/Internal/AmazonUtils.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using AmazonInternal.ThirdParty; +using UnityEngine; +public class AmazonUtils { + + /// + /// Compares two versions to see which is greater. + /// + /// Version to compare against second param + /// Version to compare against first param + /// -1 if the first version is smaller, 1 if the first version is greater, 0 if they are equal + public static int CompareVersions (string a, string b) { + var versionA = VersionStringToInts (a); + var versionB = VersionStringToInts (b); + for (var i = 0; i < Mathf.Max (versionA.Length, versionB.Length); i++) { + if (VersionPiece (versionA, i) < VersionPiece (versionB, i)) + return -1; + if (VersionPiece (versionA, i) > VersionPiece (versionB, i)) + return 1; + } + + return 0; + } + + private static int VersionPiece (IList versionInts, int pieceIndex) { + return pieceIndex < versionInts.Count ? versionInts[pieceIndex] : 0; + } + + private static int[] VersionStringToInts (string version) { + if( version == null ) + return new int[] { 0,0,0 }; + int piece; + string[] split = version.Split ('.'); + return split.Select (v => int.TryParse (v, NumberStyles.Any, CultureInfo.InvariantCulture, out piece) ? piece : 0).ToArray (); + } + + public static Uri UrlFromString (string url) { + if (string.IsNullOrEmpty (url)) return null; + try { + return new Uri (url); + } catch { + Debug.LogError ("Invalid URL: " + url); + return null; + } + } + + public static string EncodeArgs (params string[] args) { + return Json.Serialize (args); + } + + // Will return a non-null array of strings with at least 'min' non-null string values at the front. + public static string[] DecodeArgs (string argsJson, int min) { + var err = false; + var args = Json.Deserialize (argsJson) as List; + if (args == null) { + Debug.LogError ("Invalid JSON data: " + argsJson); + args = new List (); + err = true; + } + if (args.Count < min) { + if (!err) // Don't double up the error messages for invalid JSON + Debug.LogError ("Missing one or more values: " + argsJson + " (expected " + min + ")"); + while (args.Count < min) + args.Add (""); + } + return args.Select (v => v.ToString ()).ToArray (); + } + + public static string InvariantCultureToString (object obj) { + return string.Format (CultureInfo.InvariantCulture, "{0}", obj); + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/AmazonUtils.cs.meta b/Amazon/Scripts/Internal/AmazonUtils.cs.meta new file mode 100644 index 0000000..2d7d7c4 --- /dev/null +++ b/Amazon/Scripts/Internal/AmazonUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8472e80d0d208414880cdcf4c8b6889f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android.meta b/Amazon/Scripts/Internal/Android.meta new file mode 100644 index 0000000..eafc62e --- /dev/null +++ b/Amazon/Scripts/Internal/Android.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b3522bb34b494fbfac3a4d58f6de400 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/AdRegistration.cs b/Amazon/Scripts/Internal/Android/AdRegistration.cs new file mode 100644 index 0000000..1f65d82 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AdRegistration.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds.Android { + public class AdRegistration { + private static readonly AndroidJavaClass adRegistrationClass = new AndroidJavaClass ("com.amazon.device.ads.AdRegistration"); + private AndroidJavaObject adRegistration = null; + + + + public void AddProvider (AndroidJavaObject provider) { // AdProvider params + adRegistration.CallStatic ("AddProvider", provider); + } + + public AndroidJavaObject GetEventDistributer () { // return EventDistributor + return adRegistration.CallStatic ("getEventDistributer"); + } + + public HashSet GtAdProviders () { // return AdProvider + return adRegistration.CallStatic> ("getProprietaryProviderKeys"); + } + + public List GetProprietaryProviderKeys () { + return adRegistration.CallStatic> ("getProprietaryProviderKeys"); + } + + public String GetAppKey () { + return adRegistration.CallStatic ("getAppKey"); + } + + public bool IsInitialized () { + return adRegistration.CallStatic ("isInitialized"); + } + + public AndroidJavaObject GetInstance (String appKey) { + AndroidJavaClass playerClass = new AndroidJavaClass (AmazonConstants.unityPlayerClass); + AndroidJavaObject currentActivityObject = playerClass.GetStatic ("currentActivity"); + object[] adRegParams = new object[2]; + adRegParams[0] = appKey; + adRegParams[1] = currentActivityObject; + adRegistration = adRegistrationClass.CallStatic + ("getInstance", adRegParams); + + return adRegistration; + } + + public void SetMRAIDPolicy (Amazon.MRAIDPolicy policy) { + AndroidJavaClass mraidEnum = new AndroidJavaClass ("com.amazon.device.ads.MRAIDPolicy"); + AndroidJavaObject curMraid = mraidEnum.CallStatic ("valueOf", policy.ToString ()); + adRegistration.CallStatic ("setMRAIDPolicy", curMraid); + } + + public Amazon.MRAIDPolicy GetMRAIDPolicy () { // returns MRAIDPolicy + AndroidJavaObject mraid = adRegistration.CallStatic ("getMRAIDPolicy"); + int codeInt = mraid.Call ("ordinal"); + Amazon.MRAIDPolicy code = (Amazon.MRAIDPolicy) codeInt; + return code; + } + + public void SetMRAIDSupportedVersions (String[] versions) { + adRegistration.CallStatic ("setMRAIDSupportedVersions", versions); + } + + public void EnableLogging (bool enable) { + adRegistration.CallStatic ("enableLogging", enable); + } + + public void EnableLogging (bool enable, AndroidJavaObject logLevel) { // DTBLogLevel logLevel + adRegistration.CallStatic ("enableLogging", enable, logLevel); + } + + public void EnableTesting (bool isTesting) { + adRegistration.CallStatic ("enableTesting", isTesting); + } + + public bool IsTestMode () { + return adRegistration.CallStatic ("isTestMode"); + } + + public void UseGeoLocation (bool isLocationEnabled) { + adRegistration.CallStatic ("useGeoLocation", isLocationEnabled); + } + + public bool IsLocationEnabled () { + return adRegistration.CallStatic ("іsLocationEnabled"); + } + + public String GetVersion () { + return adRegistration.CallStatic ("getVersion"); + } + + public void SetServerlessMarkers (String[] markers) { + adRegistration.CallStatic ("setServerlessMarkers", markers); + + } + public void AddSlotGroup (SlotGroup sg) { // param SlotGroup sg + adRegistration.CallStatic ("addSlotGroup", sg.dTBSlot); + } + + public AndroidJavaObject GetSlotGroup (String name) { // return SlotGroup + return adRegistration.CallStatic ("getSlotGroup", name); + } + + public bool IsConsentStatusUnknown () { + return adRegistration.CallStatic ("isConsentStatusUnknown"); + } + + public void SetVendorList (List vendorList) { + adRegistration.CallStatic ("setVendorList", vendorList); + } + + public void SetConsentStatus (Amazon.ConsentStatus consentStatus) { + AndroidJavaClass consEnum = new AndroidJavaClass ("com.amazon.device.ads.AdRegistration$ConsentStatus"); + AndroidJavaObject curcons = consEnum.CallStatic ("valueOf", consentStatus.ToString ()); + adRegistration.CallStatic ("setConsentStatus", curcons); + } + + public void SetCMPFlavor (Amazon.CMPFlavor cFlavor) { + AndroidJavaClass flavEnum = new AndroidJavaClass ("com.amazon.device.ads.AdRegistration$CMPFlavor"); + AndroidJavaObject curFlav = flavEnum.CallStatic ("valueOf", cFlavor.ToString ()); + adRegistration.CallStatic ("setCMPFlavor", curFlav); + } + + public void ResetNonIAB () { + adRegistration.CallStatic ("resetNonIAB"); + } + + public class SlotGroup { + private readonly AndroidJavaClass slotGroup = new AndroidJavaClass ("com.amazon.device.ads.AdRegistration$SlotGroup"); + public AndroidJavaObject dTBSlot = null; + + public SlotGroup () { + dTBSlot = new AndroidJavaObject ("com.amazon.device.ads.AdRegistration$SlotGroup"); + } + + public SlotGroup (string name) { + dTBSlot = new AndroidJavaObject ("com.amazon.device.ads.AdRegistration$SlotGroup", name); + } + + public void AddSlot (IAdSize size) { + dTBSlot.Call ("addSlot", ((DTBAdSize) size).GetInstance ()); + } + } + + public void AddCustomAttribute (string withKey, string value) { + adRegistration.CallStatic ("addCustomAttribute", withKey, value); + } + + public void RemoveCustomAttr (string forKey) { + adRegistration.CallStatic ("removeCustomAttribute", forKey); + } + + public void SetAdNetworkInfo (string adNetworkName) { + AndroidJavaClass adNetworkEnum = new AndroidJavaClass (AmazonConstants.dtbAdNetworkClass); + AndroidJavaObject adNetworkObj = adNetworkEnum.CallStatic ("valueOf", adNetworkName); + AndroidJavaObject dtbAdNetworkInfo = new AndroidJavaObject (AmazonConstants.dtbAdNetworkInfoClass, adNetworkObj); + adRegistration.CallStatic ("setAdNetworkInfo", dtbAdNetworkInfo); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/AdRegistration.cs.meta b/Amazon/Scripts/Internal/Android/AdRegistration.cs.meta new file mode 100644 index 0000000..0dd61fd --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AdRegistration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 211753c343932487aaf8fa3e3f23a237 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/AndroidAdInterstitial.cs b/Amazon/Scripts/Internal/Android/AndroidAdInterstitial.cs new file mode 100644 index 0000000..8939514 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidAdInterstitial.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds.Android { + public class AndroidAdInterstitial : IAdInterstitial { + private AndroidJavaObject dtbAdInterstitial = null; + private static readonly AndroidJavaClass SDKUtilitiesClass = new AndroidJavaClass(AmazonConstants.sdkUtilitiesClass); + + public AndroidAdInterstitial (APSAdDelegate delegates) { + UnityEngine.AndroidJavaClass playerClass = new UnityEngine.AndroidJavaClass(AmazonConstants.unityPlayerClass); + UnityEngine.AndroidJavaObject currentActivityObject = playerClass.GetStatic ("currentActivity"); + + DTBAdInterstitialListener adInterstitialListener = new DTBAdInterstitialListener(); + adInterstitialListener.adDelegate = delegates; + dtbAdInterstitial = new AndroidJavaObject(AmazonConstants.dtbAdInterstitialClass, currentActivityObject, adInterstitialListener); + } + + public override void FetchAd (AdResponse adResponse) { + if (dtbAdInterstitial != null) { + AndroidJavaObject response = adResponse.GetAndroidResponseObject(); + string bidInfo = SDKUtilitiesClass.CallStatic("getBidInfo", response); + dtbAdInterstitial.Call("fetchAd", bidInfo); + } + } + + public override void Show () { + if (dtbAdInterstitial != null) { + dtbAdInterstitial.Call("show"); + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/AndroidAdInterstitial.cs.meta b/Amazon/Scripts/Internal/Android/AndroidAdInterstitial.cs.meta new file mode 100644 index 0000000..ae80685 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidAdInterstitial.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec1e99cd2191f4570bda447b3e0b031b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/AndroidAdResponce.cs b/Amazon/Scripts/Internal/Android/AndroidAdResponce.cs new file mode 100644 index 0000000..ef1a130 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidAdResponce.cs @@ -0,0 +1,4 @@ +namespace AmazonAds.Android { + public class AndroidAdResponceObsolete { + } +} diff --git a/Amazon/Scripts/Internal/Android/AndroidAdResponce.cs.meta b/Amazon/Scripts/Internal/Android/AndroidAdResponce.cs.meta new file mode 100644 index 0000000..6b35c90 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidAdResponce.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b59d5cd7e7903495f8d952a28060400d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/AndroidAdResponse.cs b/Amazon/Scripts/Internal/Android/AndroidAdResponse.cs new file mode 100644 index 0000000..1dbdf08 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidAdResponse.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds.Android { + public class AndroidAdResponse : AdResponse { + private AndroidJavaObject response; + private AdRequest adLoader; + + private static readonly AndroidJavaClass sdkUtilitiesClass = new AndroidJavaClass("com.amazon.device.ads.SDKUtilities"); + + public AndroidAdResponse( ) { } + public AndroidAdResponse(AndroidJavaObject newResponse) { + response = newResponse; + } + + public override IntPtr GetInstance() + { + throw new NotImplementedException(); + } + + public override string GetBidInfo() + { + return sdkUtilitiesClass.CallStatic("getBidInfo", response); + } + + public override IntPtr GetIosResponseObject() + { + throw new NotImplementedException(); + } + + public override AndroidJavaObject GetAndroidResponseObject() + { + return response; + } + + public override string GetPricePoint() + { + return sdkUtilitiesClass.CallStatic("getPricePoint", response); + } + + public override string GetMediationHints(bool isSmartBanner = false) + { + throw new NotImplementedException(); + } + + public override int GetHeight() + { + return sdkUtilitiesClass.CallStatic("getHeight", response); + } + + public override int GetWidth() + { + return sdkUtilitiesClass.CallStatic("getWidth", response); + } + +#if UNITY_ANDROID + public override AndroidJavaObject GetResponse() + { + return response; + } +#else + public override IntPtr GetResponse() + { + throw new NotImplementedException(); + } +#endif + + public override String GetMoPubKeywords () { + return response.Call ("getMoPubKeywords"); + } + + public override Dictionary GetRendering (bool isSmartBanner = false, string fetchLabel = null) { + Dictionary map = new Dictionary (); + if( response != null){ + AndroidJavaObject bundle = response.Call ("getRenderingBundle", isSmartBanner, fetchLabel); + + map.Add ("bid_html_template", bundle.Call ("getString", "bid_html_template")); + map.Add ("event_server_parameter", bundle.Call ("getString", "event_server_parameter")); + map.Add ("amazon_ad_info", bundle.Call ("getString", "amazon_ad_info")); + map.Add ("bid_identifier", bundle.Call ("getString", "bid_identifier")); + map.Add ("hostname_identifier", bundle.Call ("getString", "hostname_identifier")); + map.Add ("start_load_time", bundle.Call ("getLong", "start_load_time").ToString ()); + if (isSmartBanner) { + map.Add ("expected_width", bundle.Call ("getInt", "expected_width").ToString ()); + map.Add ("expected_height", bundle.Call ("getInt", "expected_height").ToString ()); + } + if (bundle.Call ("containsKey", "amazon_request_queue")) + map.Add ("amazon_request_queue", bundle.Call ("getString", "amazon_request_queue")); + } else { + map.Add("isAutoRefresh","1"); + } + return map; + } + + public override AdRequest GetAdLoader() { + return adLoader; + } + + internal override void SetAdLoader(AdRequest adRequest) { + adLoader = adRequest; + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/AndroidAdResponse.cs.meta b/Amazon/Scripts/Internal/Android/AndroidAdResponse.cs.meta new file mode 100644 index 0000000..911a717 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidAdResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ea64b8dd761b64dc48d3963f41d7c964 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/AndroidAdView.cs b/Amazon/Scripts/Internal/Android/AndroidAdView.cs new file mode 100644 index 0000000..d067f9b --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidAdView.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds.Android { + public class AndroidAdView : IAdView { + private AndroidJavaObject dtbAdView = null; + private static readonly AndroidJavaClass SDKUtilitiesClass = new AndroidJavaClass(AmazonConstants.sdkUtilitiesClass); + + public AndroidAdView (APSAdDelegate delegates) { + UnityEngine.AndroidJavaClass playerClass = new UnityEngine.AndroidJavaClass(AmazonConstants.unityPlayerClass); + UnityEngine.AndroidJavaObject currentActivityObject = playerClass.GetStatic ("currentActivity"); + + DTBAdBannerListener adBannerListener = new DTBAdBannerListener(); + adBannerListener.adDelegate = delegates; + dtbAdView = new AndroidJavaObject(AmazonConstants.dtbAdViewClass, currentActivityObject, adBannerListener); + } + + public override void FetchAd (AdResponse adResponse) { + if (dtbAdView != null) { + AndroidJavaObject response = adResponse.GetAndroidResponseObject(); + string bidInfo = SDKUtilitiesClass.CallStatic("getBidInfo", response); + dtbAdView.Call("fetchAd", bidInfo); + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/AndroidAdView.cs.meta b/Amazon/Scripts/Internal/Android/AndroidAdView.cs.meta new file mode 100644 index 0000000..3beb77e --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidAdView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d65a0f0dd42564508aa82269ce06336f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/AndroidPlatform.cs b/Amazon/Scripts/Internal/Android/AndroidPlatform.cs new file mode 100644 index 0000000..739b5ba --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidPlatform.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System; + +namespace AmazonAds.Android { + public class AndroidPlatform : PlatformApi { + public AdRegistration adRegistration; + public override void Initialization (string key) { + adRegistration = new AdRegistration (); + adRegistration.GetInstance (key); + } + + public override bool IsInitialized () { + return adRegistration.IsInitialized (); + } + + public override bool IsTestMode () { + return adRegistration.IsTestMode (); + } + + public override void EnableTesting (bool flag) { + adRegistration.EnableTesting (flag); + } + + public override void AddSlotGroup(SlotGroup group){ + adRegistration.AddSlotGroup (((DTBSlotGroup)group.GetInstance()).GetInstance()); + } + + public override void SetMRAIDPolicy (Amazon.MRAIDPolicy policy) { + adRegistration.SetMRAIDPolicy (policy); + } + + public override Amazon.MRAIDPolicy GetMRAIDPolicy () { + return adRegistration.GetMRAIDPolicy (); + } + + public override void SetMRAIDSupportedVersions (string[] versions) { + adRegistration.SetMRAIDSupportedVersions (versions); + } + + public override void UseGeoLocation (bool isLocationEnabled) { + adRegistration.UseGeoLocation (isLocationEnabled); + } + + public override bool IsLocationEnabled () { + return adRegistration.IsLocationEnabled (); + } + + public override void EnableLogging (bool flag) { + adRegistration.EnableLogging (flag); + } + + public override void SetCMPFlavor(Amazon.CMPFlavor cFlavor) + { + adRegistration.SetCMPFlavor(cFlavor); + } + + public override void SetConsentStatus(Amazon.ConsentStatus consentStatus) + { + adRegistration.SetConsentStatus(consentStatus); + } + + public override void SetVendorList(List vendorList) + { + adRegistration.SetVendorList(vendorList); + } + + public override void AddCustomAttribute(string withKey, string value) + { + adRegistration.AddCustomAttribute(withKey, value); + } + + public override void RemoveCustomAttr(string forKey) + { + adRegistration.RemoveCustomAttr(forKey); + } + + public override void SetAdNetworkInfo(AdNetworkInfo adNetworkInfo) + { + adRegistration.SetAdNetworkInfo(adNetworkInfo.getAdNetworkName()); + } + +#if UNITY_IOS + public override void SetAPSPublisherExtendedIdFeatureEnabled(bool isEnabled) + { + throw new System.NotImplementedException(); + } + + public override void SetLocalExtras(string adUnitId, AmazonAds.AdResponse adResponse) + { + throw new System.NotImplementedException(); + } +#endif + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/AndroidPlatform.cs.meta b/Amazon/Scripts/Internal/Android/AndroidPlatform.cs.meta new file mode 100644 index 0000000..cc1b0f0 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/AndroidPlatform.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5b2de7cfcde534331acecd109d027803 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/DTBAdBannerListener.cs b/Amazon/Scripts/Internal/Android/DTBAdBannerListener.cs new file mode 100644 index 0000000..03d2590 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBAdBannerListener.cs @@ -0,0 +1,50 @@ +using System; +using UnityEngine; + +namespace AmazonAds.Android { + public class DTBAdBannerListener : AndroidJavaProxy { + public DTBAdBannerListener () : base ("com.amazon.device.ads.DTBAdBannerListener") { } + + public APSAdDelegate adDelegate; + + private void onAdLoaded (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdLoaded(); + } + } + + private void onAdFailed (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdFailed(); + } + } + + private void onAdClicked (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdClicked(); + } + } + + private void onAdOpen (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdOpen(); + } + } + + private void onAdClosed (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdClosed(); + } + } + + private void onImpressionFired (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onImpressionFired(); + } + } + + private void onAdLeftApplication (AndroidJavaObject paramObject) { + + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/DTBAdBannerListener.cs.meta b/Amazon/Scripts/Internal/Android/DTBAdBannerListener.cs.meta new file mode 100644 index 0000000..81ce259 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBAdBannerListener.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 38ecf85701e30431f9c29008f398e51b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/DTBAdInterstitialListener.cs b/Amazon/Scripts/Internal/Android/DTBAdInterstitialListener.cs new file mode 100644 index 0000000..7dc3e2d --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBAdInterstitialListener.cs @@ -0,0 +1,56 @@ +using System; +using UnityEngine; + +namespace AmazonAds.Android { + public class DTBAdInterstitialListener : AndroidJavaProxy { + public DTBAdInterstitialListener () : base ("com.amazon.device.ads.DTBAdInterstitialListener") { } + + public APSAdDelegate adDelegate; + + private void onAdLoaded (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdLoaded(); + } + } + + private void onAdFailed (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdFailed(); + } + } + + private void onAdClicked (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdClicked(); + } + } + + private void onAdOpen (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdOpen(); + } + } + + private void onAdClosed (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onAdClosed(); + } + } + + private void onImpressionFired (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onImpressionFired(); + } + } + + private void onAdLeftApplication (AndroidJavaObject paramObject) { + + } + + private void onVideoCompleted (AndroidJavaObject paramObject) { + if (adDelegate != null) { + adDelegate.onVideoCompleted(); + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/DTBAdInterstitialListener.cs.meta b/Amazon/Scripts/Internal/Android/DTBAdInterstitialListener.cs.meta new file mode 100644 index 0000000..769558a --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBAdInterstitialListener.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a7709955494bd4212a25ccc336841875 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/DTBAdRequest.cs b/Amazon/Scripts/Internal/Android/DTBAdRequest.cs new file mode 100644 index 0000000..d277728 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBAdRequest.cs @@ -0,0 +1,215 @@ +using System.Collections; +using UnityEngine; + +namespace AmazonAds.Android { + public class DTBAdRequest : IAdRequest { + private AndroidJavaObject dTBAdRequest = null; + private string _slotGroupName = null; + private IAdSize _bannerAdSize = null; + private IInterstitialAdSize _interstitialAdSize = null; + private IVideo _videoAdSize = null; + + public DTBAdRequest () { + UnityEngine.AndroidJavaClass playerClass = new UnityEngine.AndroidJavaClass ("com.unity3d.player.UnityPlayer"); + UnityEngine.AndroidJavaObject currentActivityObject = playerClass.GetStatic ("currentActivity"); + dTBAdRequest = new AndroidJavaObject ("com.amazon.device.ads.DTBAdRequest", currentActivityObject); + } + + public DTBAdRequest (AndroidJavaObject dtbRequest) { + dTBAdRequest = dtbRequest; + } + + public override void PutCustomTarget (string key, string value) { + dTBAdRequest.Call ("putCustomTarget", key, value); + } + + public override void SetSizes (IAdSize sizes) { + _bannerAdSize = sizes; + DTBAdSize size = (DTBAdSize) sizes; + autoRefreshID = "Banner_" + sizes.GetWidth () + "_" + sizes.GetHeight () + "_" + sizes.GetSlotUUID (); + AndroidJavaClass arrayClass = new AndroidJavaClass( "java.lang.reflect.Array" ); + AndroidJavaObject arrayObject = arrayClass.CallStatic< AndroidJavaObject >( "newInstance", new AndroidJavaClass( "com.amazon.device.ads.DTBAdSize" ), 1 ); + arrayClass.CallStatic( "set", arrayObject, 0, ((DTBAdSize) sizes).GetInstance () ); + var ar = new object[] { arrayObject }; + dTBAdRequest.Call ("setSizes", ar); + } + + public override void SetSizes (IInterstitialAdSize sizes) { + _interstitialAdSize = sizes; + AndroidJavaClass arrayClass = new AndroidJavaClass( "java.lang.reflect.Array" ); + AndroidJavaObject arrayObject = arrayClass.CallStatic< AndroidJavaObject >( "newInstance", new AndroidJavaClass( "com.amazon.device.ads.DTBAdSize" ), 1 ); + arrayClass.CallStatic( "set", arrayObject, 0, ((DTBAdSize.DTBInterstitialAdSize) sizes).GetInstance () ); + var ar = new object[] { arrayObject }; + dTBAdRequest.Call ("setSizes", ar); + } + + public override void SetSizes (IVideo sizes) { + _videoAdSize = sizes; + AndroidJavaClass arrayClass = new AndroidJavaClass( "java.lang.reflect.Array" ); + AndroidJavaObject arrayObject = arrayClass.CallStatic< AndroidJavaObject >( "newInstance", new AndroidJavaClass( "com.amazon.device.ads.DTBAdSize" ), 1 ); + arrayClass.CallStatic( "set", arrayObject, 0, ((DTBAdSize.DTBVideo) sizes).GetInstance () ); + var ar = new object[] { arrayObject }; + dTBAdRequest.Call ("setSizes", ar); + } + + public override void SetSlotGroup (string slotGroupName) { + _slotGroupName = slotGroupName; + autoRefreshID = "Banner_" + slotGroupName; + dTBAdRequest.Call ("setSlotGroup", slotGroupName); + } + + public IAdSize GetBannerAdSizes () { + return _bannerAdSize; + } + + public IInterstitialAdSize GetInterstitialSizes () { + return _interstitialAdSize; + } + + public IVideo GetVideoSizes () { + return _videoAdSize; + } + + public string GetSlotGroup () { + return _slotGroupName; + } + + public override void LoadAd (Amazon.OnFailureDelegate failure, Amazon.OnSuccessDelegate success) { + if (IsAutoRefreshAdMob ()) { + Schedule.WaitForAdResponce (fetchManager, failure, success); + return; + } + + DTBCallback callback = createLoadAdCallback(success); + callback.onFailureCallback = failure; + + dTBAdRequest.Call ("loadAd", callback); + requestHasBeenUsed = true; + } + + public override void LoadSmartBanner (Amazon.OnFailureDelegate failure, Amazon.OnSuccessDelegate success) { + if (IsAutoRefreshAdMob ()) { + Schedule.WaitForAdResponce (fetchManager, failure, success); + return; + } + + DTBCallback callback = createLoadAdCallback(success); + callback.onFailureCallback = failure; + + dTBAdRequest.Call ("loadSmartBanner", callback); + requestHasBeenUsed = true; + } + + public override void LoadAd (Amazon.OnFailureWithErrorDelegate failure, Amazon.OnSuccessDelegate success) { + DTBCallback callback = createLoadAdCallback(success); + callback.onFailureWithErrorCallback = failure; + + dTBAdRequest.Call ("loadAd", callback); + requestHasBeenUsed = true; + } + + public override void LoadSmartBanner (Amazon.OnFailureWithErrorDelegate failure, Amazon.OnSuccessDelegate success) { + DTBCallback callback = createLoadAdCallback(success); + callback.onFailureWithErrorCallback = failure; + + dTBAdRequest.Call ("loadSmartBanner", callback); + requestHasBeenUsed = true; + } + + private DTBCallback createLoadAdCallback(Amazon.OnSuccessDelegate success) { + DTBCallback callback = new DTBCallback (); + callback.onSuccessCallback = success; + + return callback; + } + + public AndroidJavaObject GetClient () { + return dTBAdRequest; + } + + public override void SetAutoRefresh() { + dTBAdRequest.Call("setAutoRefresh"); + } + + public override void SetAutoRefresh(int secs) { + dTBAdRequest.Call("setAutoRefresh", secs); + } + + public override void ResumeAutoRefresh() { + dTBAdRequest.Call("resumeAutoRefresh"); + } + + public override void StopAutoRefresh() { + dTBAdRequest.Call("stop"); + } + + public override void PauseAutoRefresh() { + dTBAdRequest.Call("pauseAutoRefresh"); + } + + public override void SetAutoRefreshMoPub (bool flag){ + SetAutoRefreshMoPub(flag, refreshTime); + } + + public override void SetAutoRefreshMoPub (bool flag, int refreshTime) { + isAutoRefreshMoPub = flag; + this.refreshTime = refreshTime; + if(flag){ + if( requestHasBeenUsed ){ + ResumeAutoRefresh(); + } else { + SetAutoRefresh(refreshTime); + } + } else { + PauseAutoRefresh(); + } + } + + public override void SetAutoRefreshAdMob (bool flag, bool isSmartBanner = false) { + isAutoRefreshAdMob = flag; + if (flag) { + CreateFetchManager (isSmartBanner); + StartFetchManager (); + } else { + StopFetchManager (); + } + } + + public override void SetRefreshFlag (bool flag) { + dTBAdRequest.Call("setRefreshFlag", flag); + } + + public override void DisposeAd () { + if (fetchManager != null) { + fetchManager.dispense (); + } else { + Debug.LogWarning ("FetchManager not Init. Please turn on auto-refresh."); + } + } + + public override void StartFetchManager () { + if (fetchManager != null){ + fetchManager.start (); + } + } + + public override void StopFetchManager () { + if (fetchManager != null){ + fetchManager.stop (); + } + } + + public override void CreateFetchManager (bool isSmartBanner = false) { + if (fetchManager == null) { + fetchManager = DTBFetchFactory.GetInstance ().createFetchManager (autoRefreshID, dTBAdRequest, isSmartBanner); + } + } + + public override void DestroyFetchManager () { + if (fetchManager != null) { + DTBFetchFactory.GetInstance ().removeFetchManager (autoRefreshID); + fetchManager = null; + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/DTBAdRequest.cs.meta b/Amazon/Scripts/Internal/Android/DTBAdRequest.cs.meta new file mode 100644 index 0000000..de7d3db --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBAdRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02bd534875030442a8c3a9f1bedc6967 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/DTBAdSize.cs b/Amazon/Scripts/Internal/Android/DTBAdSize.cs new file mode 100644 index 0000000..486711a --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBAdSize.cs @@ -0,0 +1,49 @@ +using System; +using UnityEngine; + +namespace AmazonAds.Android { + public class DTBAdSize : IAdSize { + private AndroidJavaObject client; + + public DTBAdSize (int width, int height, String slotUUID) { + client = new AndroidJavaObject ("com.amazon.device.ads.DTBAdSize", width, height, slotUUID); + } + public int GetWidth () { + return client.Call ("getWidth"); + } + + public int GetHeight () { + return client.Call ("getHeight"); + } + + public string GetSlotUUID () { + return client.Call ("getSlotUUID"); + } + + public AndroidJavaObject GetInstance () { + return client; + } + + public class DTBInterstitialAdSize : IInterstitialAdSize { + private AndroidJavaObject client; + public DTBInterstitialAdSize (String slotUUID) { + client = new AndroidJavaObject ("com.amazon.device.ads.DTBAdSize$DTBInterstitialAdSize", slotUUID); + } + + public AndroidJavaObject GetInstance () { + return client; + } + } + + public class DTBVideo : IVideo { + public AndroidJavaObject client; + public DTBVideo (int playerWidth, int playerHeight, String slotUUID) { + client = new AndroidJavaObject ("com.amazon.device.ads.DTBAdSize$DTBVideo", playerWidth, playerHeight, slotUUID); + } + + public AndroidJavaObject GetInstance () { + return client; + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/DTBAdSize.cs.meta b/Amazon/Scripts/Internal/Android/DTBAdSize.cs.meta new file mode 100644 index 0000000..0137b71 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBAdSize.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0707e98bd8f7c449fbaf05500bee828d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/DTBCallback.cs b/Amazon/Scripts/Internal/Android/DTBCallback.cs new file mode 100644 index 0000000..ba61261 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBCallback.cs @@ -0,0 +1,44 @@ +using System; +using UnityEngine; + +namespace AmazonAds.Android { + public class DTBCallback : AndroidJavaProxy { + public enum ErrorCode { NO_ERROR, NETWORK_ERROR, NETWORK_TIMEOUT, NO_FILL, INTERNAL_ERROR, REQUEST_ERROR } + + public DTBCallback () : base ("com.amazon.device.ads.DTBAdCallback") { } + + public Amazon.OnSuccessDelegate onSuccessCallback; + public Amazon.OnFailureDelegate onFailureCallback; + public Amazon.OnFailureWithErrorDelegate onFailureWithErrorCallback; + + private void onSuccess (AndroidJavaObject paramDTBAdResponse) { + AndroidAdResponse response = new AndroidAdResponse (paramDTBAdResponse); + if (paramDTBAdResponse != null) { + AndroidJavaObject refreshRequest = paramDTBAdResponse.Call ("getAdLoader"); + AdRequest refreshLoader = new AdRequest(new Android.DTBAdRequest(refreshRequest)); + response.SetAdLoader(refreshLoader); + } + onSuccessCallback (response); + } + + private void onFailure (AndroidJavaObject paramAdError) { + AndroidJavaObject codeObj = paramAdError.Call ("getCode"); + int codeInt = codeObj.Call ("ordinal"); + ErrorCode code = (ErrorCode) codeInt; + string message = paramAdError.Call ("getMessage"); + + if (onFailureCallback != null) { + onFailureCallback (code + ":" + message); + } + + if (onFailureWithErrorCallback != null) { + AdError adError = new AdError(codeInt, message); + AndroidJavaObject refreshRequest = paramAdError.Call ("getAdLoader"); + AdRequest refreshLoader = new AdRequest(new Android.DTBAdRequest(refreshRequest)); + adError.SetAdLoader(refreshLoader); + adError.SetAdError(paramAdError); + onFailureWithErrorCallback(adError); + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/DTBCallback.cs.meta b/Amazon/Scripts/Internal/Android/DTBCallback.cs.meta new file mode 100644 index 0000000..e8c6ff2 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97d96cb6052c247b88fb71963517d15f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/DTBFetchFactory.cs b/Amazon/Scripts/Internal/Android/DTBFetchFactory.cs new file mode 100644 index 0000000..7a0e8bf --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBFetchFactory.cs @@ -0,0 +1,32 @@ +using System; +using UnityEngine; +namespace AmazonAds.Android { + public class DTBFetchFactory { + private static readonly AndroidJavaClass dTBFetchFactoryClass = new AndroidJavaClass ("com.amazon.device.ads.DTBFetchFactory"); + private AndroidJavaObject dTBFetchFactory = null; + + public DTBFetchFactory (AndroidJavaObject obj) { + dTBFetchFactory = obj; + } + + public static DTBFetchFactory GetInstance () { + return new DTBFetchFactory (dTBFetchFactoryClass.CallStatic ("getInstance")); + } + + public DTBFetchManager GetFetchManager (String label) { + return new DTBFetchManager (dTBFetchFactory.Call ("getFetchManager", label)); + } + + public DTBFetchManager createFetchManager (String label, AndroidJavaObject loader) { //DTBAdLoader + return new DTBFetchManager (dTBFetchFactory.Call ("createFetchManager", label, loader)); + } + + public DTBFetchManager createFetchManager (String label, AndroidJavaObject loader, bool isSmartBanner) { //DTBAdLoader + return new DTBFetchManager (dTBFetchFactory.Call ("createFetchManager", label, loader, isSmartBanner)); + } + + public void removeFetchManager (String label) { + dTBFetchFactory.Call ("removeFetchManager", label); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/DTBFetchFactory.cs.meta b/Amazon/Scripts/Internal/Android/DTBFetchFactory.cs.meta new file mode 100644 index 0000000..9aa0979 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBFetchFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d8f17e173b3b34003b573efeaef83dce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/DTBFetchManager.cs b/Amazon/Scripts/Internal/Android/DTBFetchManager.cs new file mode 100644 index 0000000..36bd868 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBFetchManager.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections; +using System.Runtime.InteropServices; +using UnityEngine; +namespace AmazonAds.Android { + public class DTBFetchManager: IFetchManager { + private static readonly AndroidJavaClass dTBFetchManagerClass = new AndroidJavaClass ("com.amazon.device.ads.DTBFetchManager"); + private AndroidJavaObject dTBFetchManager = null; + + public DTBFetchManager (AndroidJavaObject client) { + dTBFetchManager = client; + } + + public void dispense () { + AndroidJavaObject dTBAdResponse = dTBFetchManager.Call ("dispense"); + } + + public void start () { + dTBFetchManager.Call ("start"); + } + + public void stop () { + dTBFetchManager.Call ("stop"); + } + + public bool isEmpty () { + return dTBFetchManager.Call ("isEmpty"); + } + + public AmazonAds.AdResponse peek () { + AndroidJavaObject dTBAdResponse = dTBFetchManager.Call ("peek"); + return new AndroidAdResponse(dTBAdResponse); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/Android/DTBFetchManager.cs.meta b/Amazon/Scripts/Internal/Android/DTBFetchManager.cs.meta new file mode 100644 index 0000000..96b7c9b --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBFetchManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2bf648a3f472141fdbc550ad18e55ac1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/Android/DTBSlotGroup.cs b/Amazon/Scripts/Internal/Android/DTBSlotGroup.cs new file mode 100644 index 0000000..4113a69 --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBSlotGroup.cs @@ -0,0 +1,33 @@ +namespace AmazonAds.Android +{ + public class DTBSlotGroup : ISlotGroup + { + Android.AdRegistration.SlotGroup client; + public DTBSlotGroup() + { + client = new Android.AdRegistration.SlotGroup(); + } + + public DTBSlotGroup(string slotGroupName) + { + client = new Android.AdRegistration.SlotGroup(slotGroupName); + } + + public void AddSlot(int width, int height, string uid) + { + AdSize size = new AdSize(width, height, uid); + AddSlot(size); + } + + public void AddSlot(AdSize size) + { + client.AddSlot(size.GetInstance()); + } + + public Android.AdRegistration.SlotGroup GetInstance() + { + return client; + } + } +} + diff --git a/Amazon/Scripts/Internal/Android/DTBSlotGroup.cs.meta b/Amazon/Scripts/Internal/Android/DTBSlotGroup.cs.meta new file mode 100644 index 0000000..a5a07cc --- /dev/null +++ b/Amazon/Scripts/Internal/Android/DTBSlotGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f997d4f0e62c14fcdb460c08b05ef913 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS.meta b/Amazon/Scripts/Internal/IOS.meta new file mode 100644 index 0000000..eea68d4 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cf23c2530685c4a709003ad1faddfd1c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/DTBAdBannerDispatcher.cs b/Amazon/Scripts/Internal/IOS/DTBAdBannerDispatcher.cs new file mode 100644 index 0000000..6b38391 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBAdBannerDispatcher.cs @@ -0,0 +1,61 @@ +using System; +using AOT; +using System.Runtime.InteropServices; +using UnityEngine; +namespace AmazonAds.IOS { + public class DTBAdBannerDispatcher { + public delegate void OnAdLoadedDelegate (IntPtr callback); + public delegate void OnAdFailedDelegate (IntPtr callback); + public delegate void OnAdClickedDelegate (IntPtr callback); + public delegate void OnImpressionFiredDelegate (IntPtr callback); + + IntPtr clientPtr; + IntPtr thisPtr; + public APSAdDelegate adDelegate; + + public DTBAdBannerDispatcher (APSAdDelegate delegates) { + thisPtr = (IntPtr)GCHandle.Alloc(this); + clientPtr = Externs._createBannerDelegate(); + adDelegate = delegates; + Externs._setBannerDelegate(thisPtr, clientPtr, + OnAdLoaded, OnAdFailed, + OnAdClicked, OnImpressionFired); + } + + public IntPtr GetPtr() + { + return clientPtr; + } + + private static DTBAdBannerDispatcher IntPtrToClient(IntPtr client) + { + GCHandle handle = (GCHandle)client; + return handle.Target as DTBAdBannerDispatcher; + } + + [MonoPInvokeCallback (typeof (OnAdLoadedDelegate))] + public static void OnAdLoaded (IntPtr client) { + DTBAdBannerDispatcher bannerDispatcher = IntPtrToClient(client); + bannerDispatcher.adDelegate.onAdLoaded(); + } + + [MonoPInvokeCallback (typeof (OnAdFailedDelegate))] + public static void OnAdFailed (IntPtr client) { + DTBAdBannerDispatcher bannerDispatcher = IntPtrToClient(client); + bannerDispatcher.adDelegate.onAdFailed(); + } + + [MonoPInvokeCallback (typeof (OnAdClickedDelegate))] + public static void OnAdClicked (IntPtr client) { + DTBAdBannerDispatcher bannerDispatcher = IntPtrToClient(client); + bannerDispatcher.adDelegate.onAdClicked(); + } + + [MonoPInvokeCallback (typeof (OnImpressionFiredDelegate))] + public static void OnImpressionFired (IntPtr client) { + DTBAdBannerDispatcher bannerDispatcher = IntPtrToClient(client); + bannerDispatcher.adDelegate.onImpressionFired(); + } + } + +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/DTBAdBannerDispatcher.cs.meta b/Amazon/Scripts/Internal/IOS/DTBAdBannerDispatcher.cs.meta new file mode 100644 index 0000000..4768117 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBAdBannerDispatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b2d2d02538c84466afc24234497484c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/DTBAdInterstitialDispatcher.cs b/Amazon/Scripts/Internal/IOS/DTBAdInterstitialDispatcher.cs new file mode 100644 index 0000000..9cba1b5 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBAdInterstitialDispatcher.cs @@ -0,0 +1,74 @@ +using System; +using AOT; +using System.Runtime.InteropServices; +using UnityEngine; +namespace AmazonAds.IOS { + public class DTBAdInterstitialDispatcher { + public delegate void OnAdLoadedDelegate (IntPtr callback); + public delegate void OnAdFailedDelegate (IntPtr callback); + public delegate void OnAdClickedDelegate (IntPtr callback); + public delegate void OnImpressionFiredDelegate (IntPtr callback); + public delegate void OnAdOpenDelegate (IntPtr callback); + public delegate void OnAdClosedDelegate (IntPtr callback); + + IntPtr clientPtr; + IntPtr thisPtr; + public APSAdDelegate adDelegate; + + public DTBAdInterstitialDispatcher (APSAdDelegate delegates) { + thisPtr = (IntPtr)GCHandle.Alloc(this); + clientPtr = Externs._createInterstitialDelegate(); + adDelegate = delegates; + Externs._setInterstitialDelegate(thisPtr, clientPtr, + OnAdLoaded, OnAdFailed, + OnAdClicked, OnImpressionFired, + OnAdOpen, OnAdClosed); + } + + public IntPtr GetPtr(){ + return clientPtr; + } + + private static DTBAdInterstitialDispatcher IntPtrToClient(IntPtr client) + { + GCHandle handle = (GCHandle)client; + return handle.Target as DTBAdInterstitialDispatcher; + } + + [MonoPInvokeCallback (typeof (OnAdLoadedDelegate))] + public static void OnAdLoaded (IntPtr client) { + DTBAdInterstitialDispatcher interstitialDispatcher = IntPtrToClient(client); + interstitialDispatcher.adDelegate.onAdLoaded(); + } + + [MonoPInvokeCallback (typeof (OnAdFailedDelegate))] + public static void OnAdFailed (IntPtr client) { + DTBAdInterstitialDispatcher interstitialDispatcher = IntPtrToClient(client); + interstitialDispatcher.adDelegate.onAdFailed(); + } + + [MonoPInvokeCallback (typeof (OnAdClickedDelegate))] + public static void OnAdClicked (IntPtr client) { + DTBAdInterstitialDispatcher interstitialDispatcher = IntPtrToClient(client); + interstitialDispatcher.adDelegate.onAdClicked(); + } + + [MonoPInvokeCallback (typeof (OnImpressionFiredDelegate))] + public static void OnImpressionFired (IntPtr client) { + DTBAdInterstitialDispatcher interstitialDispatcher = IntPtrToClient(client); + interstitialDispatcher.adDelegate.onImpressionFired(); + } + + [MonoPInvokeCallback (typeof (OnAdOpenDelegate))] + public static void OnAdOpen (IntPtr client) { + DTBAdInterstitialDispatcher interstitialDispatcher = IntPtrToClient(client); + interstitialDispatcher.adDelegate.onAdOpen(); + } + + [MonoPInvokeCallback (typeof (OnAdClosedDelegate))] + public static void OnAdClosed (IntPtr client) { + DTBAdInterstitialDispatcher interstitialDispatcher = IntPtrToClient(client); + interstitialDispatcher.adDelegate.onAdClosed(); + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/DTBAdInterstitialDispatcher.cs.meta b/Amazon/Scripts/Internal/IOS/DTBAdInterstitialDispatcher.cs.meta new file mode 100644 index 0000000..27cbc4c --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBAdInterstitialDispatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c027d873469c4440fbfdd1b55353f520 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/DTBAdRequest.cs b/Amazon/Scripts/Internal/IOS/DTBAdRequest.cs new file mode 100644 index 0000000..cbd17a7 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBAdRequest.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections; +using System.Runtime.InteropServices; +using UnityEngine; +namespace AmazonAds.IOS { + public class DTBAdRequest : IAdRequest { + private IntPtr adLoader; + private string _slotGroupName = null; + private IAdSize _bannerAdSize = null; + private IInterstitialAdSize _interstitialAdSize = null; + private IVideo _videoAdSize = null; + + public DTBAdRequest () { + adLoader = Externs._createAdLoader (); + } + + public DTBAdRequest (IntPtr adRequest) { + adLoader = adRequest; + } + + public IntPtr GetInstance(){ + return adLoader; + } + + public override void DisposeAd () { + if (fetchManager != null) { + fetchManager.dispense(); + } else { + UnityEngine.Debug.LogWarning ("FetchManager not Init. Please turn on auto-refresh."); + } + } + + public override void LoadAd (Amazon.OnFailureDelegate failure, Amazon.OnSuccessDelegate success) { + requestHasBeenUsed = true; + if (IsAutoRefreshAdMob ()) { + Schedule.WaitForAdResponce (fetchManager, failure, success); + return; + } + DTBCallback callback = new DTBCallback (failure, success); + Externs._loadAd (adLoader, callback.GetPtr ()); + } + + public override void LoadSmartBanner (Amazon.OnFailureDelegate failure, Amazon.OnSuccessDelegate success) { + requestHasBeenUsed = true; + if (IsAutoRefreshAdMob ()) { + Schedule.WaitForAdResponce (fetchManager, failure, success); + return; + } + DTBCallback callback = new DTBCallback (failure, success); + Externs._loadSmartBanner (adLoader, callback.GetPtr ()); + } + + public override void LoadAd (Amazon.OnFailureWithErrorDelegate failureWithError, Amazon.OnSuccessDelegate success) { + requestHasBeenUsed = true; + DTBCallback callback = new DTBCallback (failureWithError, success); + Externs._loadAd (adLoader, callback.GetPtr ()); + } + + public override void LoadSmartBanner (Amazon.OnFailureWithErrorDelegate failureWithError, Amazon.OnSuccessDelegate success) { + requestHasBeenUsed = true; + DTBCallback callback = new DTBCallback (failureWithError, success); + Externs._loadSmartBanner (adLoader, callback.GetPtr ()); + } + + public override void PutCustomTarget (string key, string value) { + Externs._putCustomTarget (adLoader, key, value); + } + + public override void SetAutoRefresh() { + Externs._setAutoRefreshNoArgs(adLoader); + } + + public override void SetAutoRefresh(int secs) { + Externs._setAutoRefresh(adLoader,secs); + } + + public override void PauseAutoRefresh() { + Externs._pauseAutoRefresh(adLoader); + } + + public override void StopAutoRefresh() { + Externs._stopAutoRefresh(adLoader); + } + + public override void ResumeAutoRefresh() { + Externs._resumeAutoRefresh(adLoader); + } + + public override void SetAutoRefreshMoPub (bool flag){ + SetAutoRefreshMoPub(flag, refreshTime); + } + + public override void SetAutoRefreshMoPub (bool flag, int refreshTime) { + isAutoRefreshMoPub = flag; + this.refreshTime = refreshTime; + if(flag){ + if( requestHasBeenUsed ){ + ResumeAutoRefresh(); + } else { + SetAutoRefresh(refreshTime); + } + } else { + PauseAutoRefresh(); + } + } + + public override void SetAutoRefreshAdMob (bool flag, bool isSmartBanner = false) { + isAutoRefreshAdMob = flag; + if(flag){ + CreateFetchManager(isSmartBanner); + StartFetchManager(); + } else { + StopFetchManager(); + } + } + + public override void SetRefreshFlag (bool flag) { + Externs._setRefreshFlag(adLoader, flag); + } + + public override void StartFetchManager () { + if (fetchManager != null){ + fetchManager.start (); + } + } + + public override void StopFetchManager () { + if (fetchManager != null){ + fetchManager.stop (); + } + } + + public override void CreateFetchManager (bool isSmartBanner = false) { + if (fetchManager == null){ + fetchManager = new DTBFetchManager(this, autoRefreshID, isSmartBanner); + } + } + + public override void DestroyFetchManager () { + if (fetchManager != null){ + ((AmazonAds.IOS.DTBFetchManager)fetchManager).destroy(autoRefreshID); + } + } + + public override void SetSizes (IAdSize sizes) { + _bannerAdSize = sizes; + int height = sizes.GetHeight (); + int width = sizes.GetWidth (); + string slotType = "SLOT_" + width + "_" + height; + autoRefreshID = slotType; + Externs._setSizes (adLoader, ((DTBAdSize) sizes).GetInstance ()); + } + + public override void SetSizes (IInterstitialAdSize sizes) { + _interstitialAdSize = sizes; + Externs._setSizes (adLoader, ((DTBAdSize.DTBInterstitialAdSize) sizes).GetInstance ()); + } + + public override void SetSizes (IVideo sizes) { + _videoAdSize = sizes; + Externs._setSizes (adLoader, ((DTBAdSize.DTBVideo) sizes).GetInstance ()); + } + + public override void SetSlotGroup (string slotGroupName) { + _slotGroupName = slotGroupName; + Externs._setSlotGroup (adLoader, slotGroupName); + } + + public IAdSize GetBannerAdSizes () { + return _bannerAdSize; + } + + public IInterstitialAdSize GetInterstitialSizes () { + return _interstitialAdSize; + } + + public IVideo GetVideoSizes () { + return _videoAdSize; + } + + public string GetSlotGroup () { + return _slotGroupName; + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/DTBAdRequest.cs.meta b/Amazon/Scripts/Internal/IOS/DTBAdRequest.cs.meta new file mode 100644 index 0000000..64cd525 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBAdRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 028c059572c3540cb8f18d6eb4f6c4be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/DTBAdSize.cs b/Amazon/Scripts/Internal/IOS/DTBAdSize.cs new file mode 100644 index 0000000..90e850f --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBAdSize.cs @@ -0,0 +1,69 @@ +using System; +using UnityEngine; + +namespace AmazonAds.IOS +{ + public class DTBAdSize : IAdSize + { + private IntPtr client; + private int width = 0; + private int height = 0; + private String slotUUID= ""; + + public DTBAdSize(int width, int height, String slotUUID) + { + this.slotUUID = slotUUID; + this.width = width; + this.height = height; + client = Externs._createBannerAdSize(width, height, slotUUID); + } + + public int GetHeight() + { + return height; + } + + public IntPtr GetInstance() + { + return client; + } + + public string GetSlotUUID() + { + return slotUUID; + } + + public int GetWidth() + { + return width; + } + + public class DTBInterstitialAdSize : IInterstitialAdSize + { + private IntPtr client; + public DTBInterstitialAdSize(String slotUUID) + { + client = Externs._createInterstitialAdSize(slotUUID); + } + + public IntPtr GetInstance() + { + return client; + } + } + + public class DTBVideo : IVideo + { + public IntPtr client; + public DTBVideo(int playerWidth, int playerHeight, String slotUUID) + { + client = Externs._createVideoAdSize(playerWidth, playerHeight, slotUUID); + } + + public IntPtr GetInstance() + { + return client; + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/DTBAdSize.cs.meta b/Amazon/Scripts/Internal/IOS/DTBAdSize.cs.meta new file mode 100644 index 0000000..1a04a63 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBAdSize.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b34576138f1bd4ced980dee0fd2996b0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/DTBCallback.cs b/Amazon/Scripts/Internal/IOS/DTBCallback.cs new file mode 100644 index 0000000..d19fcd1 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBCallback.cs @@ -0,0 +1,84 @@ +using System; +using AOT; +using System.Runtime.InteropServices; +using UnityEngine; +namespace AmazonAds.IOS { + public class DTBCallback { + public delegate void OnFailureWithErrorDelegate (IntPtr callback, int errorMsg, IntPtr adError); + public delegate void OnFailureDelegate (IntPtr callback, int errorMsg); + public delegate void OnSuccessDelegate (IntPtr callback, IntPtr response); + public enum ErrorCode { NO_ERROR, NETWORK_ERROR, NETWORK_TIMEOUT, NO_FILL, INTERNAL_ERROR, REQUEST_ERROR } + IntPtr clientPtr; + IntPtr thisPtr; + + public struct DTBAdResponceData{ + public string amznSlots; + public string mediationHints; + public string keywords; + } + + public DTBCallback (Amazon.OnFailureDelegate failureDelegate, Amazon.OnSuccessDelegate successDelegate) { + thisPtr = (IntPtr)GCHandle.Alloc(this); + clientPtr = Externs._createCallback(); + onSuccessCallback = successDelegate; + onFailureCallback = failureDelegate; + Externs._amazonSetListeners(thisPtr, clientPtr, OnSuccess, OnFailure); + } + + public DTBCallback (Amazon.OnFailureWithErrorDelegate failureWithErrorDelegate, Amazon.OnSuccessDelegate successDelegate) { + thisPtr = (IntPtr)GCHandle.Alloc(this); + clientPtr = Externs._createCallback(); + onSuccessCallback = successDelegate; + onFailureWithErrorCallback = failureWithErrorDelegate; + Externs._amazonSetListenersWithInfo(thisPtr, clientPtr, OnSuccess, OnFailureWithInfo); + } + + public Amazon.OnSuccessDelegate onSuccessCallback; + public Amazon.OnFailureDelegate onFailureCallback; + public Amazon.OnFailureWithErrorDelegate onFailureWithErrorCallback; + + private AdRequest refreshAdLoader = null; + + public IntPtr GetPtr(){ + return clientPtr; + } + + private static DTBCallback IntPtrToClient(IntPtr callbackClient) + { + GCHandle handle = (GCHandle)callbackClient; + return handle.Target as DTBCallback; + } + + [MonoPInvokeCallback (typeof (OnSuccessDelegate))] + public static void OnSuccess (IntPtr callbackClient, IntPtr response) { + DTBCallback client = IntPtrToClient(callbackClient); + IOSAdResponse resp = new IOSAdResponse (response); + IOS.DTBAdRequest dtbAdRequest = new IOS.DTBAdRequest(Externs._getAdLoaderFromResponse(response)); + resp.SetAdLoader(new AdRequest(dtbAdRequest)); + client.onSuccessCallback(resp); + } + + [MonoPInvokeCallback (typeof (OnFailureDelegate))] + public static void OnFailure (IntPtr callbackClient, int errorMsg) { + DTBCallback client = IntPtrToClient(callbackClient); + + if (client.onFailureCallback != null) { + client.onFailureCallback ("Code:" + errorMsg); + } + } + + [MonoPInvokeCallback (typeof (OnFailureWithErrorDelegate))] + public static void OnFailureWithInfo (IntPtr callbackClient, int errorMsg, IntPtr errorInfo) { + DTBCallback client = IntPtrToClient(callbackClient); + + if (client.onFailureWithErrorCallback != null) { + AdError adError = new AdError(errorMsg, ""); + IOS.DTBAdRequest dtbAdRequest = new IOS.DTBAdRequest(Externs._getAdLoaderFromAdError(errorInfo)); + adError.SetAdLoader(new AdRequest(dtbAdRequest)); + adError.SetInstance(errorInfo); + client.onFailureWithErrorCallback(adError); + } + } + + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/DTBCallback.cs.meta b/Amazon/Scripts/Internal/IOS/DTBCallback.cs.meta new file mode 100644 index 0000000..d8d784b --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 53febdb10cdf24c24ab963454803ad53 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/DTBFetchManager.cs b/Amazon/Scripts/Internal/IOS/DTBFetchManager.cs new file mode 100644 index 0000000..7d3e473 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBFetchManager.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections; +using System.Runtime.InteropServices; +using UnityEngine; +namespace AmazonAds.IOS { + public class DTBFetchManager: IFetchManager { + private IntPtr fetchManager; + protected enum DTBSlotType { + SLOT_320_50 = 0, + SLOT_300_250 = 1, + SLOT_728_90 = 2, + SLOT_SMART = 3 + } + public DTBFetchManager (DTBAdRequest adLoader, string autoRefreshID, bool isSmartBanner) { + Externs._createFetchManager (adLoader.GetInstance(), isSmartBanner); + fetchManager = Externs._getFetchManager ( (int) Enum.Parse(typeof(DTBSlotType), autoRefreshID), isSmartBanner); + } + + public void dispense () { + Externs._fetchManagerPop (fetchManager); + } + + public void start () { + Externs._startFetchManager (fetchManager); + } + + public void stop () { + Externs._stopFetchManager (fetchManager); + } + + public bool isEmpty () { + return Externs._isEmptyFetchManager(fetchManager); + } + + public AmazonAds.AdResponse peek () { + return new IOSAdResponse(); + } + + public void destroy(string autoRefreshID){ + Externs._destroyFetchManager ((int) Enum.Parse(typeof(DTBSlotType), autoRefreshID) ); + fetchManager = IntPtr.Zero; + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/DTBFetchManager.cs.meta b/Amazon/Scripts/Internal/IOS/DTBFetchManager.cs.meta new file mode 100644 index 0000000..fc4f76f --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBFetchManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d527c1c887004853918e03dc2f5c5c8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs b/Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs new file mode 100644 index 0000000..ecd2a59 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs @@ -0,0 +1,31 @@ +using System; + +namespace AmazonAds.IOS +{ + public class DTBSlotGroup : ISlotGroup + { + IntPtr client; + public DTBSlotGroup(string slotGroupName) + { + client = Externs._createSlotGroup(slotGroupName); + } + + public void AddSlot(int width, int height, string uid) + { + AdSize size = new AdSize(width, height, uid); + AddSlot(size); + } + + public void AddSlot(AdSize size) + { + DTBAdSize newSize = (DTBAdSize)size.GetInstance(); + Externs._addSlot(client, newSize.GetInstance()); + } + + public IntPtr GetInstance() + { + return client; + } + } +} + diff --git a/Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs.meta b/Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs.meta new file mode 100644 index 0000000..3ff304b --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/DTBSlotGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 734ab7005315a4ab1a6e683e7e864e28 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/Externs.cs b/Amazon/Scripts/Internal/IOS/Externs.cs new file mode 100644 index 0000000..f483b01 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/Externs.cs @@ -0,0 +1,218 @@ +using System.Runtime.InteropServices; +using System; + +namespace AmazonAds.IOS +{ + public class Externs + { +#if ENABLE_IL2CPP && UNITY_ANDROID + public static void _amazonInitialize(string appKey) {} + public static bool _amazonIsInitialized() { return false; } + public static void _amazonSetUseGeoLocation(bool flag) {} + public static bool _amazonGetUseGeoLocation() { return false; } + public static void _amazonSetLogLevel(int logLevel) {} + public static bool _amazonGetLogLevel() { return false; } + public static void _amazonSetTestMode(bool flag) {} + public static bool _amazonIsTestModeEnabled() { return false; } + public static IntPtr _createBannerAdSize(int width, int height, string uuid) { return IntPtr.Zero; } + public static IntPtr _createVideoAdSize(int width, int height, string uuid){ return IntPtr.Zero; } + public static IntPtr _createInterstitialAdSize(string uuid) { return IntPtr.Zero; } + public static IntPtr _createAdLoader() { return IntPtr.Zero; } + public static void _setSizes(IntPtr adLoader, IntPtr size) {} + public static void _loadAd(IntPtr adLoader, IntPtr callback) {} + public static void _loadSmartBanner(IntPtr adLoader, IntPtr callback) {} + public static void _amazonSetListeners(IntPtr unityRef, IntPtr callback, DTBCallback.OnSuccessDelegate onSuccessCallback, DTBCallback.OnFailureDelegate onErrorCallback) {} + public static void _amazonSetListenersWithInfo(IntPtr unityRef, IntPtr callback, DTBCallback.OnSuccessDelegate onSuccessCallback, DTBCallback.OnFailureWithErrorDelegate onErrorCallbackWithInfo) {} + public static void _setBannerDelegate(IntPtr unityRef, IntPtr callback, DTBAdBannerDispatcher.OnAdLoadedDelegate onAdLoadedDelegate, DTBAdBannerDispatcher.OnAdFailedDelegate onAdFailedDelegate, + DTBAdBannerDispatcher.OnAdClickedDelegate onAdClickedDelegate, DTBAdBannerDispatcher.OnImpressionFiredDelegate onImpressionFiredDelegate) {} + public static void _setInterstitialDelegate(IntPtr unityRef, IntPtr callback, DTBAdInterstitialDispatcher.OnAdLoadedDelegate onAdLoadedDelegate, DTBAdInterstitialDispatcher.OnAdFailedDelegate onAdFailedDelegate, + DTBAdInterstitialDispatcher.OnAdClickedDelegate onAdClickedDelegate, DTBAdInterstitialDispatcher.OnImpressionFiredDelegate onImpressionFiredDelegate, DTBAdInterstitialDispatcher.OnAdOpenDelegate onAdOpenDelegate, DTBAdInterstitialDispatcher.OnAdClosedDelegate onAdClosedDelegate) {} + public static void _amazonSetMRAIDPolicy(int policy) {} + public static int _amazonGetMRAIDPolicy() {return -1;} + public static void _amazonSetMRAIDSupportedVersions(string versions) {} + public static IntPtr _createCallback() { return IntPtr.Zero; } + public static IntPtr _createBannerDelegate() { return IntPtr.Zero; } + public static IntPtr _createInterstitialDelegate() { return IntPtr.Zero; } + public static IntPtr _getFetchManager(int autoRefreshID, bool isSmartBanner) { return IntPtr.Zero; } + public static void _fetchManagerPop(IntPtr fetchManager) {} + public static void _putCustomTarget(IntPtr adLoader, string key, string value) {} + public static void _createFetchManager(IntPtr adLoader, bool isSmartBanner) {} + public static void _startFetchManager(IntPtr fetchManager) {} + public static void _stopFetchManager(IntPtr fetchManager) {} + public static bool _isEmptyFetchManager(IntPtr fetchManager) {return false; } + public static void _destroyFetchManager(int autoRefreshID) { } + public static void _setSlotGroup(IntPtr adLoader, string slotGroupName) {} + public static IntPtr _createSlotGroup(string slotGroupName) { return IntPtr.Zero; } + public static void _addSlot(IntPtr slot, IntPtr size) {} + public static void _addSlotGroup(IntPtr group) {} + public static string _fetchMediationHints(IntPtr resp, bool isSmartBanner) { return null; } + public static string _fetchAmznSlots(IntPtr resp) { return null; } + public static string _fetchMoPubKeywords(IntPtr resp) { return null; } + public static void _setCMPFlavor(int cFlavor) {} + public static void _setConsentStatus(int consentStatus) {} + public static IntPtr _createArray() { return IntPtr.Zero; } + public static void _addToArray(IntPtr dictionary, int item) {} + public static void _setVendorList(IntPtr dictionary) {} + public static void _setAutoRefreshNoArgs(IntPtr adLoader) {} + public static void _setAutoRefresh(IntPtr adLoader, int secs) {} + public static void _pauseAutoRefresh(IntPtr adLoader) {} + public static void _stopAutoRefresh(IntPtr adLoader) {} + public static void _resumeAutoRefresh(IntPtr adLoader) {} + public static void _setAPSFrequencyCappingIdFeatureEnabled(bool frequencyCappingIdFeatureEnabled) {} + public static void _addCustomAttribute(string withKey, string value) {} + public static void _removeCustomAttribute(string forKey) {} + public static void _setAdNetworkInfo(int adNetwork) {} + public static void _setLocalExtras(string adUnitId, IntPtr localExtras) {} + public static IntPtr _createAdView(int width, int height, IntPtr dispatcher) { return IntPtr.Zero; } + public static IntPtr _createAdInterstitial(IntPtr dispatcher) { return IntPtr.Zero; } + public static void _fetchBannerAd(IntPtr adDispatcher, IntPtr adResponse) {} + public static void _fetchInterstitialAd(IntPtr adDispatcher, IntPtr adResponse) {} + public static void _showInterstitial(IntPtr adDispatcher) {} + public static void _setRefreshFlag(IntPtr adLoader, bool flag) {} + public static IntPtr _getAdLoaderFromResponse(IntPtr response) { return IntPtr.Zero; } + public static IntPtr _getAdLoaderFromAdError(IntPtr adErrorInfo) { return IntPtr.Zero; } + public static int _fetchAdWidth(IntPtr resp) { return -1; } + public static int _fetchAdHeight(IntPtr resp) { return -1; } +#else + [DllImport("__Internal")] + public static extern void _amazonInitialize(string appKey); + [DllImport("__Internal")] + public static extern bool _amazonIsInitialized(); + [DllImport("__Internal")] + public static extern void _amazonSetUseGeoLocation(bool flag); + [DllImport("__Internal")] + public static extern bool _amazonGetUseGeoLocation(); + [DllImport("__Internal")] + public static extern void _amazonSetLogLevel(int logLevel); + [DllImport("__Internal")] + public static extern bool _amazonGetLogLevel(); + [DllImport("__Internal")] + public static extern void _amazonSetTestMode(bool flag); + [DllImport("__Internal")] + public static extern bool _amazonIsTestModeEnabled(); + [DllImport("__Internal")] + public static extern IntPtr _createBannerAdSize(int width, int height, string uuid); + [DllImport("__Internal")] + public static extern IntPtr _createVideoAdSize(int width, int height, string uuid); + [DllImport("__Internal")] + public static extern IntPtr _createInterstitialAdSize(string uuid); + [DllImport("__Internal")] + public static extern IntPtr _createAdLoader(); + [DllImport("__Internal")] + public static extern void _setSizes(IntPtr adLoader, IntPtr size); + [DllImport("__Internal")] + public static extern void _loadAd(IntPtr adLoader, IntPtr callback); + [DllImport("__Internal")] + public static extern void _loadSmartBanner(IntPtr adLoader, IntPtr callback); + [DllImport("__Internal")] + public static extern void _amazonSetListeners(IntPtr unityRef, IntPtr callback, DTBCallback.OnSuccessDelegate onSuccessCallback, DTBCallback.OnFailureDelegate onErrorCallback); + [DllImport("__Internal")] + public static extern void _amazonSetListenersWithInfo(IntPtr unityRef, IntPtr callback, DTBCallback.OnSuccessDelegate onSuccessCallback, DTBCallback.OnFailureWithErrorDelegate onErrorCallbackWithInfo); + [DllImport("__Internal")] + public static extern void _setBannerDelegate(IntPtr unityRef, IntPtr callback, + DTBAdBannerDispatcher.OnAdLoadedDelegate onAdLoadedDelegate, DTBAdBannerDispatcher.OnAdFailedDelegate onAdFailedDelegate, + DTBAdBannerDispatcher.OnAdClickedDelegate onAdClickedDelegate, DTBAdBannerDispatcher.OnImpressionFiredDelegate onImpressionFiredDelegate); + [DllImport("__Internal")] + public static extern void _setInterstitialDelegate(IntPtr unityRef, IntPtr callback, + DTBAdInterstitialDispatcher.OnAdLoadedDelegate onAdLoadedDelegate, DTBAdInterstitialDispatcher.OnAdFailedDelegate onAdFailedDelegate, + DTBAdInterstitialDispatcher.OnAdClickedDelegate onAdClickedDelegate, DTBAdInterstitialDispatcher.OnImpressionFiredDelegate onImpressionFiredDelegate, + DTBAdInterstitialDispatcher.OnAdOpenDelegate onAdOpenDelegate, DTBAdInterstitialDispatcher.OnAdClosedDelegate onAdClosedDelegate); + [DllImport("__Internal")] + public static extern void _amazonSetMRAIDPolicy(int policy); + [DllImport("__Internal")] + public static extern int _amazonGetMRAIDPolicy(); + [DllImport("__Internal")] + public static extern void _amazonSetMRAIDSupportedVersions(string versions); + [DllImport("__Internal")] + public static extern IntPtr _createCallback(); + [DllImport("__Internal")] + public static extern IntPtr _createBannerDelegate(); + [DllImport("__Internal")] + public static extern IntPtr _createInterstitialDelegate(); + [DllImport("__Internal")] + public static extern IntPtr _getFetchManager(int autoRefreshID, bool isSmartBanner); + [DllImport("__Internal")] + public static extern void _fetchManagerPop(IntPtr fetchManager); + [DllImport("__Internal")] + public static extern void _putCustomTarget(IntPtr adLoader, string key, string value); + [DllImport("__Internal")] + public static extern void _createFetchManager(IntPtr adLoader, bool isSmartBanner); + [DllImport("__Internal")] + public static extern void _startFetchManager(IntPtr fetchManager); + [DllImport("__Internal")] + public static extern void _stopFetchManager(IntPtr fetchManager); + [DllImport("__Internal")] + public static extern bool _isEmptyFetchManager(IntPtr fetchManager); + [DllImport("__Internal")] + public static extern void _destroyFetchManager(int autoRefreshID); + [DllImport("__Internal")] + public static extern void _setSlotGroup(IntPtr adLoader, string slotGroupName); + [DllImport("__Internal")] + public static extern IntPtr _createSlotGroup(string slotGroupName); + [DllImport("__Internal")] + public static extern void _addSlot(IntPtr slot, IntPtr size); + [DllImport("__Internal")] + public static extern void _addSlotGroup(IntPtr group); + [DllImport("__Internal")] + public static extern string _fetchMediationHints(IntPtr resp, bool isSmartBanner); + [DllImport("__Internal")] + public static extern string _fetchAmznSlots(IntPtr resp); + [DllImport("__Internal")] + public static extern int _fetchAdWidth(IntPtr resp); + [DllImport("__Internal")] + public static extern int _fetchAdHeight(IntPtr resp); + [DllImport("__Internal")] + public static extern string _fetchMoPubKeywords(IntPtr resp); + [DllImport("__Internal")] + public static extern void _setCMPFlavor(int cFlavor); + [DllImport("__Internal")] + public static extern void _setConsentStatus(int consentStatus); + [DllImport("__Internal")] + public static extern IntPtr _createArray(); + [DllImport("__Internal")] + public static extern void _addToArray(IntPtr dictionary, int item); + [DllImport("__Internal")] + public static extern void _setVendorList(IntPtr dictionary); + [DllImport("__Internal")] + public static extern void _setAutoRefreshNoArgs(IntPtr adLoader); + [DllImport("__Internal")] + public static extern void _setAutoRefresh(IntPtr adLoader, int secs); + [DllImport("__Internal")] + public static extern void _pauseAutoRefresh(IntPtr adLoader); + [DllImport("__Internal")] + public static extern void _stopAutoRefresh(IntPtr adLoader); + [DllImport("__Internal")] + public static extern void _resumeAutoRefresh(IntPtr adLoader); + [DllImport("__Internal")] + public static extern void _addCustomAttribute(string withKey, string value); + [DllImport("__Internal")] + public static extern void _removeCustomAttribute(string forKey); + [DllImport("__Internal")] + public static extern void _setAdNetworkInfo(int adNetwork); + [DllImport("__Internal")] + public static extern IntPtr _createAdView(int width, int height, IntPtr dispatcher); + [DllImport("__Internal")] + public static extern IntPtr _createAdInterstitial(IntPtr dispatcher); + [DllImport("__Internal")] + public static extern void _fetchBannerAd(IntPtr adDispatcher, IntPtr adResponse); + [DllImport("__Internal")] + public static extern void _fetchInterstitialAd(IntPtr adDispatcher, IntPtr adResponse); + [DllImport("__Internal")] + public static extern void _showInterstitial(IntPtr adDispatcher); + [DllImport("__Internal")] + public static extern void _setRefreshFlag(IntPtr adLoader, bool flag); + [DllImport("__Internal")] + public static extern IntPtr _getAdLoaderFromResponse(IntPtr response); + [DllImport("__Internal")] + public static extern IntPtr _getAdLoaderFromAdError(IntPtr adErrorInfo); +#if UNITY_IOS + [DllImport("__Internal")] + public static extern void _setAPSPublisherExtendedIdFeatureEnabled(bool isEnabled); + [DllImport("__Internal")] + public static extern void _setLocalExtras(string adUnitId, IntPtr localExtras); + [DllImport("__Internal")] + public static extern IntPtr _getMediationHintsDict(IntPtr resp, bool isSmartBanner); +#endif +#endif + } +} diff --git a/Amazon/Scripts/Internal/IOS/Externs.cs.meta b/Amazon/Scripts/Internal/IOS/Externs.cs.meta new file mode 100644 index 0000000..3561351 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/Externs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1708dd63a5c574f8db8866d86b2fb232 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/IOSAdInterstitial.cs b/Amazon/Scripts/Internal/IOS/IOSAdInterstitial.cs new file mode 100644 index 0000000..2a0bcf9 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSAdInterstitial.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds.IOS { + public class IOSAdInterstitial : IAdInterstitial { + private IntPtr adDispatcher; + + public IOSAdInterstitial (APSAdDelegate delegates) { + DTBAdInterstitialDispatcher adInterstitialDispatcher = new DTBAdInterstitialDispatcher(delegates); + adDispatcher = Externs._createAdInterstitial(adInterstitialDispatcher.GetPtr()); + } + + public override void FetchAd (AdResponse adResponse) { + if (adDispatcher != null) { + Externs._fetchInterstitialAd(adDispatcher, adResponse.GetInstance()); + } + } + + public override void Show () { + if (adDispatcher != null) { + Externs._showInterstitial(adDispatcher); + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/IOSAdInterstitial.cs.meta b/Amazon/Scripts/Internal/IOS/IOSAdInterstitial.cs.meta new file mode 100644 index 0000000..b117149 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSAdInterstitial.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0d4d502223b4a4092b39024b38722b89 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/IOSAdResponce.cs b/Amazon/Scripts/Internal/IOS/IOSAdResponce.cs new file mode 100644 index 0000000..914704f --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSAdResponce.cs @@ -0,0 +1,4 @@ +namespace AmazonAds.IOS { + public class IOSAdResponceObsolete { + } +} diff --git a/Amazon/Scripts/Internal/IOS/IOSAdResponce.cs.meta b/Amazon/Scripts/Internal/IOS/IOSAdResponce.cs.meta new file mode 100644 index 0000000..99f191e --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSAdResponce.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9111bf37862934342b4a39f926faa2b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/IOSAdResponse.cs b/Amazon/Scripts/Internal/IOS/IOSAdResponse.cs new file mode 100644 index 0000000..d627c43 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSAdResponse.cs @@ -0,0 +1,92 @@ +using System.Collections.Generic; +using System; +using UnityEngine; + +namespace AmazonAds.IOS { + public class IOSAdResponse : AdResponse { + IntPtr resp; + private AdRequest adLoader; + + public IOSAdResponse(){ } + public IOSAdResponse(IntPtr response){ + resp = response; + } + + public override int GetHeight() + { + return Externs._fetchAdHeight(resp); + } + + public override int GetWidth() + { + return Externs._fetchAdWidth(resp); + } + + public override string GetMoPubKeywords () { + return Externs._fetchMoPubKeywords(resp); + } + + public override IntPtr GetIosResponseObject() + { + return resp; + } + + public override AndroidJavaObject GetAndroidResponseObject() + { + throw new NotImplementedException(); + } + + public override string GetBidInfo() + { + throw new NotImplementedException(); + } + + public override string GetPricePoint() + { + return Externs._fetchAmznSlots(resp); + } + + public override string GetMediationHints(bool isSmartBanner = false) + { + return Externs._fetchMediationHints(resp, isSmartBanner); + } + + public override IntPtr GetInstance() + { + return resp; + } + +#if UNITY_ANDROID + public override AndroidJavaObject GetResponse() + { + throw new NotImplementedException(); + } +#else + public override IntPtr GetResponse() + { + return resp; + } +#endif + + public override Dictionary GetRendering (bool isSmartBanner = false, string fetchLabel = null) { + Dictionary rendering = new Dictionary(); + if( resp != IntPtr.Zero){ + string mediationHints = Externs._fetchMediationHints(resp, isSmartBanner); + string amznSlots = Externs._fetchAmznSlots(resp); + rendering.Add("mediationHints", mediationHints); + rendering.Add("amznSlots", amznSlots); + } else { + rendering.Add("useFetchManager", "YES"); + } + return rendering; + } + + public override AdRequest GetAdLoader() { + return adLoader; + } + + internal override void SetAdLoader(AdRequest adRequest) { + adLoader = adRequest; + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/IOSAdResponse.cs.meta b/Amazon/Scripts/Internal/IOS/IOSAdResponse.cs.meta new file mode 100644 index 0000000..f1d95d5 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSAdResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9fdebaea51295482fb17caa1dfcb2fd9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/IOSAdView.cs b/Amazon/Scripts/Internal/IOS/IOSAdView.cs new file mode 100644 index 0000000..910b45b --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSAdView.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AmazonAds.IOS { + public class IOSAdView : IAdView { + private IntPtr adDispatcher; + + public IOSAdView (AdSize adSize, APSAdDelegate delegates) { + DTBAdBannerDispatcher adBannerDispatcher = new DTBAdBannerDispatcher(delegates); + adDispatcher = Externs._createAdView(adSize.GetInstance().GetWidth(), adSize.GetInstance().GetHeight(), adBannerDispatcher.GetPtr()); + } + + public override void FetchAd (AdResponse adResponse) { + if (adDispatcher != null) { + Externs._fetchBannerAd(adDispatcher, adResponse.GetInstance()); + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/IOSAdView.cs.meta b/Amazon/Scripts/Internal/IOS/IOSAdView.cs.meta new file mode 100644 index 0000000..4bfb326 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSAdView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a23b0b9ff70c443cbbb45c959a58503d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/IOS/IOSPlatform.cs b/Amazon/Scripts/Internal/IOS/IOSPlatform.cs new file mode 100644 index 0000000..8618062 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSPlatform.cs @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using AOT; +using UnityEngine; +using System.Runtime.InteropServices; +using System; + +namespace AmazonAds.IOS { + public class IOSPlatform : PlatformApi { + + public override void Initialization (string key) { + Externs._amazonInitialize (key); + } + + public override bool IsInitialized () { + return Externs._amazonIsInitialized (); + } + + public override bool IsTestMode () { + return Externs._amazonIsTestModeEnabled (); + } + + public override void EnableTesting (bool flag) { + Externs._amazonSetTestMode (flag); + } + public override void EnableLogging (bool flag) { + Externs._amazonSetLogLevel (flag ? 1 : 0); + } + + public override void UseGeoLocation (bool isLocationEnabled) { + Externs._amazonSetUseGeoLocation (isLocationEnabled); + } + + public override bool IsLocationEnabled () { + return Externs._amazonGetUseGeoLocation (); + } + + public override void SetMRAIDPolicy (Amazon.MRAIDPolicy policy) { + Externs._amazonSetMRAIDPolicy ((int) policy); + } + + public override Amazon.MRAIDPolicy GetMRAIDPolicy () { + return (Amazon.MRAIDPolicy) Externs._amazonGetMRAIDPolicy (); + } + + public override void SetMRAIDSupportedVersions (string[] versions) { + Externs._amazonSetMRAIDSupportedVersions (versions.ToString()); + } + + public override void AddSlotGroup(SlotGroup group) + { + DTBSlotGroup ptr = (DTBSlotGroup)group.GetInstance(); + Externs._addSlotGroup(ptr.GetInstance()); + } + + public override void SetCMPFlavor(Amazon.CMPFlavor cFlavor) + { + int fla = 0; + switch (cFlavor) + { + case Amazon.CMPFlavor.CMP_NOT_DEFINED: + fla = -1; + break; + case Amazon.CMPFlavor.GOOGLE_CMP: + fla = 1; + break; + case Amazon.CMPFlavor.MOPUB_CMP: + fla = 2; + break; + } + Externs._setCMPFlavor(fla); + } + + public override void SetConsentStatus(Amazon.ConsentStatus consentStatus) + { + int cons = 0; + switch (consentStatus) + { + case Amazon.ConsentStatus.CONSENT_NOT_DEFINED: + cons = -1; + break; + case Amazon.ConsentStatus.EXPLICIT_YES: + cons = 7; + break; + case Amazon.ConsentStatus.EXPLICIT_NO: + cons = -0; + break; + case Amazon.ConsentStatus.UNKNOWN: + cons = 1; + break; + } + Externs._setConsentStatus(cons); + } + + public override void SetVendorList(List vendorList) + { + IntPtr dictionary = Externs._createArray(); + foreach (var item in vendorList) + { + Externs._addToArray(dictionary, item); + } + Externs._setVendorList(dictionary); + } + + public override void AddCustomAttribute(string withKey, string value) + { + Externs._addCustomAttribute(withKey, value); + } + + public override void RemoveCustomAttr(string forKey) + { + Externs._removeCustomAttribute(forKey); + } + + public override void SetAdNetworkInfo(AdNetworkInfo adNetworkInfo) + { + DTBAdNetwork dtbAdNetwork = adNetworkInfo.getAdNetwork(); + Externs._setAdNetworkInfo((int)dtbAdNetwork); + } + +#if UNITY_IOS + public override void SetAPSPublisherExtendedIdFeatureEnabled(bool isEnabled) + { + Externs._setAPSPublisherExtendedIdFeatureEnabled(isEnabled); + } + + public override void SetLocalExtras(string adUnitId, AmazonAds.AdResponse adResponse) { + Externs._setLocalExtras(adUnitId, Externs._getMediationHintsDict(adResponse.GetInstance(), false)); + } +#endif + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/IOS/IOSPlatform.cs.meta b/Amazon/Scripts/Internal/IOS/IOSPlatform.cs.meta new file mode 100644 index 0000000..a907b99 --- /dev/null +++ b/Amazon/Scripts/Internal/IOS/IOSPlatform.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ac416f8316ced40589eeba7b04efc627 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/MiniJSON.cs b/Amazon/Scripts/Internal/MiniJSON.cs new file mode 100644 index 0000000..492bbb7 --- /dev/null +++ b/Amazon/Scripts/Internal/MiniJSON.cs @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2013 Calvin Rien + * + * Based on the JSON parser by Patrick van Bergen + * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html + * + * Simplified it so that it doesn't throw exceptions + * and can be used in Unity iPhone with maximum code stripping. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +using System.Globalization; + +namespace AmazonInternal.ThirdParty { + using System.Collections.Generic; + using System.Collections; + using System.IO; + using System.Text; + using System; + + // Example usage: + // + // using UnityEngine; + // using System.Collections; + // using System.Collections.Generic; + // using MiniJSON; + // + // public class MiniJSONTest : MonoBehaviour { + // void Start () { + // var jsonString = "{ \"array\": [1.44,2,3], " + + // "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + + // "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + + // "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + + // "\"int\": 65536, " + + // "\"float\": 3.1415926, " + + // "\"bool\": true, " + + // "\"null\": null }"; + // + // var dict = Json.Deserialize(jsonString) as Dictionary; + // + // Debug.Log("deserialized: " + dict.GetType()); + // Debug.Log("dict['array'][0]: " + ((List) dict["array"])[0]); + // Debug.Log("dict['string']: " + (string) dict["string"]); + // Debug.Log("dict['float']: " + (double) dict["float"]); // floats come out as doubles + // Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs + // Debug.Log("dict['unicode']: " + (string) dict["unicode"]); + // + // var str = Json.Serialize(dict); + // + // Debug.Log("serialized: " + str); + // } + // } + + /// + /// This class encodes and decodes JSON strings. + /// Spec. details, see http://www.json.org/ + /// + /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. + /// All numbers are parsed to doubles. + /// + public static class Json { + /// + /// Parses the string json into a value + /// + /// A JSON string. + /// An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false + public static object Deserialize (string json) { + // save the string for debug information + if (json == null) { + return null; + } + + return Parser.Parse (json); + } + + sealed class Parser : IDisposable { + const string WORD_BREAK = "{}[],:\""; + + public static bool IsWordBreak (char c) { + return Char.IsWhiteSpace (c) || WORD_BREAK.IndexOf (c) != -1; + } + + enum TOKEN { + NONE, + CURLY_OPEN, + CURLY_CLOSE, + SQUARED_OPEN, + SQUARED_CLOSE, + COLON, + COMMA, + STRING, + NUMBER, + TRUE, + FALSE, + NULL + } + + StringReader json; + + Parser (string jsonString) { + json = new StringReader (jsonString); + } + + public static object Parse (string jsonString) { + using (var instance = new Parser (jsonString)) { + return instance.ParseValue (); + } + } + + public void Dispose () { + json.Dispose (); + json = null; + } + + Dictionary ParseObject () { + Dictionary table = new Dictionary (); + + // ditch opening brace + json.Read (); + + // { + while (true) { + switch (NextToken) { + case TOKEN.NONE: + return null; + case TOKEN.COMMA: + continue; + case TOKEN.CURLY_CLOSE: + return table; + default: + // name + string name = ParseString (); + if (name == null) { + return null; + } + + // : + if (NextToken != TOKEN.COLON) { + return null; + } + // ditch the colon + json.Read (); + + // value + table[name] = ParseValue (); + break; + } + } + } + + List ParseArray () { + List array = new List (); + + // ditch opening bracket + json.Read (); + + // [ + var parsing = true; + while (parsing) { + TOKEN nextToken = NextToken; + + switch (nextToken) { + case TOKEN.NONE: + return null; + case TOKEN.COMMA: + continue; + case TOKEN.SQUARED_CLOSE: + parsing = false; + break; + default: + object value = ParseByToken (nextToken); + + array.Add (value); + break; + } + } + + return array; + } + + object ParseValue () { + TOKEN nextToken = NextToken; + return ParseByToken (nextToken); + } + + object ParseByToken (TOKEN token) { + switch (token) { + case TOKEN.STRING: + return ParseString (); + case TOKEN.NUMBER: + return ParseNumber (); + case TOKEN.CURLY_OPEN: + return ParseObject (); + case TOKEN.SQUARED_OPEN: + return ParseArray (); + case TOKEN.TRUE: + return true; + case TOKEN.FALSE: + return false; + case TOKEN.NULL: + return null; + default: + return null; + } + } + + string ParseString () { + StringBuilder s = new StringBuilder (); + char c; + + // ditch opening quote + json.Read (); + + bool parsing = true; + while (parsing) { + + if (json.Peek () == -1) { + parsing = false; + break; + } + + c = NextChar; + switch (c) { + case '"': + parsing = false; + break; + case '\\': + if (json.Peek () == -1) { + parsing = false; + break; + } + + c = NextChar; + switch (c) { + case '"': + case '\\': + case '/': + s.Append (c); + break; + case 'b': + s.Append ('\b'); + break; + case 'f': + s.Append ('\f'); + break; + case 'n': + s.Append ('\n'); + break; + case 'r': + s.Append ('\r'); + break; + case 't': + s.Append ('\t'); + break; + case 'u': + var hex = new char[4]; + + for (int i = 0; i < 4; i++) { + hex[i] = NextChar; + } + + s.Append ((char) Convert.ToInt32 (new string (hex), 16)); + break; + } + break; + default: + s.Append (c); + break; + } + } + + return s.ToString (); + } + + object ParseNumber () { + string number = NextWord; + + if (number.IndexOf ('.') == -1) { + long parsedInt; + Int64.TryParse (number, NumberStyles.Any, CultureInfo.InvariantCulture, out parsedInt); + return parsedInt; + } + + double parsedDouble; + Double.TryParse (number, NumberStyles.Any, CultureInfo.InvariantCulture, out parsedDouble); + return parsedDouble; + } + + void EatWhitespace () { + while (Char.IsWhiteSpace (PeekChar)) { + json.Read (); + + if (json.Peek () == -1) { + break; + } + } + } + + char PeekChar { + get { + return Convert.ToChar (json.Peek ()); + } + } + + char NextChar { + get { + return Convert.ToChar (json.Read ()); + } + } + + string NextWord { + get { + StringBuilder word = new StringBuilder (); + + while (!IsWordBreak (PeekChar)) { + word.Append (NextChar); + + if (json.Peek () == -1) { + break; + } + } + + return word.ToString (); + } + } + + TOKEN NextToken { + get { + EatWhitespace (); + + if (json.Peek () == -1) { + return TOKEN.NONE; + } + + switch (PeekChar) { + case '{': + return TOKEN.CURLY_OPEN; + case '}': + json.Read (); + return TOKEN.CURLY_CLOSE; + case '[': + return TOKEN.SQUARED_OPEN; + case ']': + json.Read (); + return TOKEN.SQUARED_CLOSE; + case ',': + json.Read (); + return TOKEN.COMMA; + case '"': + return TOKEN.STRING; + case ':': + return TOKEN.COLON; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + return TOKEN.NUMBER; + } + + switch (NextWord) { + case "false": + return TOKEN.FALSE; + case "true": + return TOKEN.TRUE; + case "null": + return TOKEN.NULL; + } + + return TOKEN.NONE; + } + } + } + + /// + /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string + /// + /// A Dictionary<string, object> / List<object> + /// A JSON encoded string, or null if object 'json' is not serializable + public static string Serialize (object obj) { + return Serializer.Serialize (obj); + } + + sealed class Serializer { + StringBuilder builder; + + Serializer () { + builder = new StringBuilder (); + } + + public static string Serialize (object obj) { + var instance = new Serializer (); + + instance.SerializeValue (obj); + + return instance.builder.ToString (); + } + + void SerializeValue (object value) { + IList asList; + IDictionary asDict; + string asStr; + + if (value == null) { + builder.Append ("null"); + } else if ((asStr = value as string) != null) { + SerializeString (asStr); + } else if (value is bool) { + builder.Append ((bool) value ? "true" : "false"); + } else if ((asList = value as IList) != null) { + SerializeArray (asList); + } else if ((asDict = value as IDictionary) != null) { + SerializeObject (asDict); + } else if (value is char) { + SerializeString (new string ((char) value, 1)); + } else { + SerializeOther (value); + } + } + + void SerializeObject (IDictionary obj) { + bool first = true; + + builder.Append ('{'); + + foreach (object e in obj.Keys) { + if (!first) { + builder.Append (','); + } + + SerializeString (e.ToString ()); + builder.Append (':'); + + SerializeValue (obj[e]); + + first = false; + } + + builder.Append ('}'); + } + + void SerializeArray (IList anArray) { + builder.Append ('['); + + bool first = true; + + foreach (object obj in anArray) { + if (!first) { + builder.Append (','); + } + + SerializeValue (obj); + + first = false; + } + + builder.Append (']'); + } + + void SerializeString (string str) { + builder.Append ('\"'); + + char[] charArray = str.ToCharArray (); + foreach (var c in charArray) { + switch (c) { + case '"': + builder.Append ("\\\""); + break; + case '\\': + builder.Append ("\\\\"); + break; + case '\b': + builder.Append ("\\b"); + break; + case '\f': + builder.Append ("\\f"); + break; + case '\n': + builder.Append ("\\n"); + break; + case '\r': + builder.Append ("\\r"); + break; + case '\t': + builder.Append ("\\t"); + break; + default: + int codepoint = Convert.ToInt32 (c); + if ((codepoint >= 32) && (codepoint <= 126)) { + builder.Append (c); + } else { + builder.Append ("\\u"); + builder.Append (codepoint.ToString ("x4")); + } + break; + } + } + + builder.Append ('\"'); + } + + void SerializeOther (object value) { + // NOTE: decimals lose precision during serialization. + // They always have, I'm just letting you know. + // Previously floats and doubles lost precision too. + if (value is float) { + builder.Append (((float) value).ToString ("R")); + } else if (value is int || + value is uint || + value is long || + value is sbyte || + value is byte || + value is short || + value is ushort || + value is ulong) { + builder.Append (value); + } else if (value is double || + value is decimal) { + builder.Append (Convert.ToDouble (value).ToString ("R")); + } else { + SerializeString (value.ToString ()); + } + } + } + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/MiniJSON.cs.meta b/Amazon/Scripts/Internal/MiniJSON.cs.meta new file mode 100644 index 0000000..ac9e379 --- /dev/null +++ b/Amazon/Scripts/Internal/MiniJSON.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b235ee00c3e948deaa8d5af245c9318 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/PlatformApi.cs b/Amazon/Scripts/Internal/PlatformApi.cs new file mode 100644 index 0000000..07e858a --- /dev/null +++ b/Amazon/Scripts/Internal/PlatformApi.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace AmazonAds { + public abstract class PlatformApi { + public abstract void Initialization (string key); + public abstract bool IsInitialized (); + public abstract bool IsTestMode (); + public abstract void EnableTesting (bool flag); + public abstract void EnableLogging (bool flag); + public abstract void UseGeoLocation (bool isLocationEnabled); + public abstract bool IsLocationEnabled (); + public abstract void SetMRAIDPolicy (Amazon.MRAIDPolicy policy); + public abstract Amazon.MRAIDPolicy GetMRAIDPolicy (); + public abstract void SetMRAIDSupportedVersions (String[] versions); + public abstract void AddSlotGroup(SlotGroup group); + public abstract void SetCMPFlavor(Amazon.CMPFlavor cFlavor); + public abstract void SetConsentStatus(Amazon.ConsentStatus consentStatus); + public abstract void SetVendorList(List vendorList); + public abstract void AddCustomAttribute(string withKey, string value); + public abstract void RemoveCustomAttr(String forKey); + public abstract void SetAdNetworkInfo(AdNetworkInfo adNetworkInfo); +#if UNITY_IOS + public abstract void SetAPSPublisherExtendedIdFeatureEnabled(bool isEnable); + public abstract void SetLocalExtras(string adUnitId, AmazonAds.AdResponse adResponse); +#endif + } +} \ No newline at end of file diff --git a/Amazon/Scripts/Internal/PlatformApi.cs.meta b/Amazon/Scripts/Internal/PlatformApi.cs.meta new file mode 100644 index 0000000..d4ffe97 --- /dev/null +++ b/Amazon/Scripts/Internal/PlatformApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a7e4c885c2b514bab912a1d10b93b56b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Internal/SlotGroup.cs b/Amazon/Scripts/Internal/SlotGroup.cs new file mode 100644 index 0000000..8cd7487 --- /dev/null +++ b/Amazon/Scripts/Internal/SlotGroup.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +namespace AmazonAds{ +public class SlotGroup +{ + ISlotGroup client; + + public SlotGroup(string slotGroupName){ + #if UNITY_ANDROID + client = new AmazonAds.Android.DTBSlotGroup(slotGroupName); + #elif UNITY_IOS + client = new AmazonAds.IOS.DTBSlotGroup(slotGroupName); + #endif + } + + public void AddSlot(int width, int height, string uid){ + AdSize size = new AdSize(width, height, uid); + AddSlot(size); + } + + public void AddSlot(AdSize size){ + client.AddSlot(size); + } + + public ISlotGroup GetInstance(){ + return client; + } +} +} + diff --git a/Amazon/Scripts/Internal/SlotGroup.cs.meta b/Amazon/Scripts/Internal/SlotGroup.cs.meta new file mode 100644 index 0000000..46e9ed3 --- /dev/null +++ b/Amazon/Scripts/Internal/SlotGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0721cd33e88d476385237c2bf17af32 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Mediations.meta b/Amazon/Scripts/Mediations.meta new file mode 100644 index 0000000..77042fe --- /dev/null +++ b/Amazon/Scripts/Mediations.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc21c213b3887496a9b450a63d014a4b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Mediations/AppLovinMediation.meta b/Amazon/Scripts/Mediations/AppLovinMediation.meta new file mode 100644 index 0000000..b2fab5b --- /dev/null +++ b/Amazon/Scripts/Mediations/AppLovinMediation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 39980aa183b504d8a8897519535976bf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Mediations/AppLovinMediation/Editor.meta b/Amazon/Scripts/Mediations/AppLovinMediation/Editor.meta new file mode 100644 index 0000000..d8d55c5 --- /dev/null +++ b/Amazon/Scripts/Mediations/AppLovinMediation/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eb50eb92fd8e241589b99bc4635578a1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Mediations/AppLovinMediation/Editor/APSAppLovinPackageConfig.cs b/Amazon/Scripts/Mediations/AppLovinMediation/Editor/APSAppLovinPackageConfig.cs new file mode 100644 index 0000000..3c90618 --- /dev/null +++ b/Amazon/Scripts/Mediations/AppLovinMediation/Editor/APSAppLovinPackageConfig.cs @@ -0,0 +1,14 @@ +public class APSAppLovinPackageConfig : AmazonPackageConfig +{ + public const string VERSION = "1.4.3"; + + public override string Name + { + get { return "applovin_max"; } + } + + public override string Version + { + get { return VERSION; } + } +} diff --git a/Amazon/Scripts/Mediations/AppLovinMediation/Editor/APSAppLovinPackageConfig.cs.meta b/Amazon/Scripts/Mediations/AppLovinMediation/Editor/APSAppLovinPackageConfig.cs.meta new file mode 100644 index 0000000..5516962 --- /dev/null +++ b/Amazon/Scripts/Mediations/AppLovinMediation/Editor/APSAppLovinPackageConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 605f6ed8576974f2c9a821be69531aba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml b/Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml new file mode 100644 index 0000000..88914bc --- /dev/null +++ b/Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml.meta b/Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..0d908f4 --- /dev/null +++ b/Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: b7874141996c14ba4b9b32651bc21d2a +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/AmazonAdMarketplace/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor.meta b/Editor.meta new file mode 100644 index 0000000..8d027e3 --- /dev/null +++ b/Editor.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fa3f786500bd4d3e97ccae58e18caade +timeCreated: 1700544851 \ No newline at end of file diff --git a/Editor/CodeMods.meta b/Editor/CodeMods.meta new file mode 100644 index 0000000..47b6d50 --- /dev/null +++ b/Editor/CodeMods.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e76a67036c2d420da2425e11ab623f3a +timeCreated: 1700788339 \ No newline at end of file diff --git a/Editor/CodeMods/AmazonMod.cs b/Editor/CodeMods/AmazonMod.cs new file mode 100644 index 0000000..a9a7fe1 --- /dev/null +++ b/Editor/CodeMods/AmazonMod.cs @@ -0,0 +1,116 @@ +using System.IO; +using System.Text; +using System.Xml; +using NUnit.Framework; +using UnityEditor; +using UnityEditor.Compilation; +using UnityEngine; + +namespace Guru.Editor.Max +{ + public class AmazonMod: GuruModifier + { + protected override string TargetPath => $"Amazon/Scripts/Editor/AmazonDependencies.xml"; + + private static string SDKManagerPath = "Amazon/Scripts/Editor/AmazonSDKManager.cs"; + + public static void Apply() + { + var mod = new AmazonMod(); + mod.FixDepsViaPackage(); + mod.HideAmazonMenuItems(); + } + + #region 修复依赖 + + [Test] + public void FixDepsViaPackage() + { + string path = GetFullPath(TargetPath); + + if (!File.Exists(path)) + { + Debug.Log($"---- file not found: {path}"); + return; + } + + var doc = new XmlDocument(); + doc.LoadXml(File.ReadAllText(path, Encoding.UTF8)); + if (doc.ChildNodes.Count < 2) + { + Debug.LogError($"--- Wrong Xml nodes or no root node"); + return; + } + + var root = doc.ChildNodes[1]; + foreach (XmlNode node in root.ChildNodes) + { + if (node.Name == "iosPods") + { + foreach (XmlElement n in node.ChildNodes) + { + if (n.GetAttribute("name") == "Amazon-SDK-Plugin") + { + var p = n.GetAttribute("path"); + p = p.Replace("Assets", $"Packages/{GuruMaxSdkAPI.PackageName}"); + n.SetAttribute("path", p); + } + } + } + } + + // 保存文档 + doc.Save(path); + + var xml = File.ReadAllText(path); + xml = xml.Replace(">", ">").Replace("<", "<"); + File.WriteAllText(path, xml); + + Debug.Log($"[GuruMax]--- Fix Amazon depences success: {path}"); + } + + #endregion + + #region 隐藏菜单 + + [Test] + public void HideAmazonMenuItems() + { + string partten = "[MenuItem (\"Amazon/"; + string path = GetFullPath(SDKManagerPath); + bool isDirty = false; + if (File.Exists(path)) + { + var line = ""; + var lines = File.ReadAllLines(path); + for (int i = 0; i < lines.Length; i++) + { + line = lines[i]; + if (line.Contains(partten)) + { + lines[i] = $"//{line}"; + isDirty = true; + } + } + + if (isDirty) + { + Debug.Log($"[GuruMax]--- Hide Amazon Menu success: {path}"); + File.WriteAllLines(path, lines); + CompilationPipeline.RequestScriptCompilation(); + } + + } + else + { + Debug.LogError($"--- AmazonSDKManager cannot be found"); + } + } + + + + #endregion + + + } +} \ No newline at end of file diff --git a/Editor/CodeMods/AmazonMod.cs.meta b/Editor/CodeMods/AmazonMod.cs.meta new file mode 100644 index 0000000..b884294 --- /dev/null +++ b/Editor/CodeMods/AmazonMod.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d80f5acb03684c688816ea8fdf046197 +timeCreated: 1701007829 \ No newline at end of file diff --git a/Editor/CodeMods/ApplovinMod.cs b/Editor/CodeMods/ApplovinMod.cs new file mode 100644 index 0000000..660a6cf --- /dev/null +++ b/Editor/CodeMods/ApplovinMod.cs @@ -0,0 +1,173 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Guru.Editor; +using NUnit.Framework; +using UnityEngine; + +namespace Guru.Editor.Max +{ + public class ApplovinMod: GuruModifier + { + + private const string IntergrationManagerPath = "MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs"; + private const string MenuItemsPath = "MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs"; + private const string SettingsPath = "MaxSdk/Resources/AppLovinSettings.asset"; + + private static readonly string K_IsPluginOutside = "public static bool IsPluginOutsideAssetsDirectory"; + private const string EXT_BACKUP = ".backup"; + + + public static void Apply() + { + ApplovinMod mod = new ApplovinMod(); + // 替换代码内的组件路径 + mod.FixIntegrationManager(); + // 隐藏编辑器菜单 + mod.DoBackup(); + // 删除其他的 AppLovinSettings 组件 + mod.CheckAndCleanOtherSettings(); + } + + + #region IntegrationManager 注入 + + + /// + /// 修复脚本 + /// + /// + [Test] + public void FixIntegrationManager() + { + var path = GetFullPath(IntergrationManagerPath); + if (!File.Exists(path)) + { + Debug.LogError($"File not found: {path}"); + return; + } + + // --------- Scan All the code lines ------------- + List lines = File.ReadLines(path).ToList(); + + string line = ""; + int i = 0; + int incNum = 0; + int count = lines.Count; + while (i < count) + { + line = lines[i]; + + if (line.TrimStart(new char[] { '\t', ' ' }).Contains(K_IsPluginOutside)) + { + incNum = FixupIsPluginOutside(lines, i); + i += incNum; + count = lines.Count; + } + + i++; + } + File.WriteAllLines(path, lines.ToArray()); + Debug.Log($"[GuruMax] --- code fixed: {path} ---"); + } + + + private const string MK_PluginOutside_START = "//--- INJECT PluginOutside START ---"; + private const string MK_PluginOutside_OVER = "//--- INJECT PluginOutside OVER ---"; + private int FixupIsPluginOutside(List lines, int startIndex) + { + int inc = 0; + string line = ""; + + line = lines[startIndex - 1]; + if (line.Contains(MK_PluginOutside_START)) return 0; // 已经修复过了 + + line = lines[startIndex + 1].Trim(); + if (line.Contains("{")) + { + lines[startIndex + 1] = $"//{lines[startIndex + 1]}"; + lines[startIndex + 2] = $"//{lines[startIndex + 2]}"; + lines[startIndex + 3] = $"//{lines[startIndex + 3]}"; + } + lines.Insert(startIndex, $"{MK_PluginOutside_START}"); + lines.Insert(startIndex + 2, "\t\t{ get => !(PluginParentDirectory.StartsWith(\"Assets\") || PluginParentDirectory.StartsWith(\"Packages\")); }"); + lines.Insert(startIndex + 3, $"{MK_PluginOutside_OVER}"); + inc += 3; + + return inc; + } + + + #endregion + + #region MenuItems 隐藏 + [Test] + public static bool MenuItemsHide() + { + return new ApplovinMod().DoBackup(); + } + [Test] + public static bool MenuItemsRecover() + { + return new ApplovinMod().DoRecover(); + } + + private bool DoBackup() + { + var path = GetFullPath(MenuItemsPath); + string backup = $"{path}.backup"; + if (File.Exists(path) && !path.EndsWith(EXT_BACKUP)) + { + File.Move(path, backup); + Debug.Log($"[GuruMax] --- Max Menu backuped "); + return true; + } + + Debug.Log($"File not found or different name: {path}"); + return false; + } + + private bool DoRecover() + { + var path = GetFullPath(MenuItemsPath); + string backup = $"{path}{EXT_BACKUP}"; + if (path.EndsWith(EXT_BACKUP)) + { + backup = path; + path = backup.Replace(EXT_BACKUP, ""); + } + + if (File.Exists(backup)) + { + File.Move(backup, path); + Debug.Log($"[GuruMax] --- Max Menu recovered"); + return true; + } + + Debug.LogError($"File not found: {path}"); + return false; + } + + + + #endregion + + #region AppLovinSettings + + //销毁其他路径的 AppLovinSettings + [Test] + public void CheckAndCleanOtherSettings() + { + var path = GetFullPath(SettingsPath); + + if (this.FileExists(path)) + { + this.DeleteFile(path); + Debug.Log($"[GuruMax] --- AppLovinSettings has been removed: {path} "); + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/Editor/CodeMods/ApplovinMod.cs.meta b/Editor/CodeMods/ApplovinMod.cs.meta new file mode 100644 index 0000000..d7993f8 --- /dev/null +++ b/Editor/CodeMods/ApplovinMod.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0e17cf11ee9e4ba688ebd141fc9da004 +timeCreated: 1701055867 \ No newline at end of file diff --git a/Editor/CodeMods/GuruMaxCodeFixer.cs b/Editor/CodeMods/GuruMaxCodeFixer.cs new file mode 100644 index 0000000..5f7d2a2 --- /dev/null +++ b/Editor/CodeMods/GuruMaxCodeFixer.cs @@ -0,0 +1,77 @@ +using System.IO; +using UnityEditor; +using UnityEditor.Compilation; +using UnityEngine; + +namespace Guru.Editor.Max +{ + public static class GuruMaxCodeFixer + { + + public static void Compile() => CompilationPipeline.RequestScriptCompilation(); + + + /// + /// Gets the path of the asset in the project for a given MAX plugin export path. + /// + /// The actual exported path of the asset. + /// The exported path of the MAX plugin asset or the default export path if the asset is not found. + public static string GetAssetPathFromPackageForExportPath(string exportPath) + { + var defaultPath = Path.Combine(GuruMaxSdkAPI.PackageDataPath, exportPath); + var assetLabelToFind = + "l:al_max_export_path-" + + exportPath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + var assetGuids = AssetDatabase.FindAssets(assetLabelToFind); + return assetGuids.Length < 1 ? defaultPath : AssetDatabase.GUIDToAssetPath(assetGuids[0]); + } + + /// + /// 更新所有的修改器 + /// + public static void ApplyAllMods() + { + + // --- 修改 AppLovinMax + Debug.Log($"------ #1. Apply AppLovinMax"); + ApplovinMod.Apply(); + + // --- 修复 Amazon 依赖 + Debug.Log($"------ #2. Apply Amazon"); + AmazonMod.Apply(); + + // --- 修复 Pubmatic 依赖 + Debug.Log($"------ #3. Apply Pubmatic"); + PubmaticMod.Apply(); + + Compile(); + } + + +#if GURU_SDK_DEV + + //---------- 编辑器快捷菜单 ------------------- + + [MenuItem("Guru/Dev/Max/Apply All Mods")] + private static void DevInjectCodeFix() + { + ApplyAllMods(); + } + + + [MenuItem("Guru/Dev/Max/Show Max Menu")] + private static void DevRecoverMenu() + { + var res = ApplovinMod.MenuItemsRecover(); + if(res) Compile(); + } + +#endif + + } + + + + + +} \ No newline at end of file diff --git a/Editor/CodeMods/GuruMaxCodeFixer.cs.meta b/Editor/CodeMods/GuruMaxCodeFixer.cs.meta new file mode 100644 index 0000000..1712b59 --- /dev/null +++ b/Editor/CodeMods/GuruMaxCodeFixer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b20bfef8eb4402893b7d919056ab34a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/CodeMods/GuruModifier.cs b/Editor/CodeMods/GuruModifier.cs new file mode 100644 index 0000000..2eafa05 --- /dev/null +++ b/Editor/CodeMods/GuruModifier.cs @@ -0,0 +1,28 @@ +using System.IO; +using Guru; + +namespace Guru.Editor.Max +{ + public abstract class GuruModifier: IFileIO + { + protected virtual string TargetPath { get; set; } + + public const string Tag = "[GuruMod]"; + + protected string GetFullPath(string path = "") + { + if (string.IsNullOrEmpty(path)) path = TargetPath; + return Path.GetFullPath(GetAssetPath(path)); + } + + + protected string GetAssetPath(string path = "") + { + if (string.IsNullOrEmpty(path)) path = TargetPath; + return GuruMaxCodeFixer.GetAssetPathFromPackageForExportPath(path); + } + + + + } +} \ No newline at end of file diff --git a/Editor/CodeMods/GuruModifier.cs.meta b/Editor/CodeMods/GuruModifier.cs.meta new file mode 100644 index 0000000..aceed7a --- /dev/null +++ b/Editor/CodeMods/GuruModifier.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0579b31b8deb4dc3b6e33e768a4ec6ee +timeCreated: 1700794796 \ No newline at end of file diff --git a/Editor/CodeMods/PubmaticMod.cs b/Editor/CodeMods/PubmaticMod.cs new file mode 100644 index 0000000..bb90226 --- /dev/null +++ b/Editor/CodeMods/PubmaticMod.cs @@ -0,0 +1,39 @@ +using System.IO; +using UnityEngine; + +namespace Guru.Editor.Max +{ + public class PubmaticMod: GuruModifier + { + protected override string TargetPath => "OpenWrapSDK/Editor/POBPlistProcessor.cs"; + + + public static void Apply() + { + PubmaticMod mod = new PubmaticMod(); + mod.FixPostBuildPath(); + } + + private void FixPostBuildPath() + { + var path = GetFullPath(); + + if (File.Exists(path)) + { + string raw = File.ReadAllText(path); + string realDataPath = $"Packages/{GuruMaxSdkAPI.PackageName}"; + raw = raw.Replace("Application.dataPath", $"\"{realDataPath}\""); + File.WriteAllText(path, raw); + Debug.Log($"{Tag} --- code has injected: {path}."); + } + else + { + Debug.Log($"{Tag} --- File not found: {path}."); + } + + } + + + + } +} \ No newline at end of file diff --git a/Editor/CodeMods/PubmaticMod.cs.meta b/Editor/CodeMods/PubmaticMod.cs.meta new file mode 100644 index 0000000..acca524 --- /dev/null +++ b/Editor/CodeMods/PubmaticMod.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 426309db9cf044448233d23633f76fdd +timeCreated: 1701054970 \ No newline at end of file diff --git a/Editor/EasyGUILayout.cs b/Editor/EasyGUILayout.cs new file mode 100644 index 0000000..8865687 --- /dev/null +++ b/Editor/EasyGUILayout.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace Guru +{ + public static class EasyGUILayout + { + private const string K_BOX_STYPE = "Box"; + public static GUIStyle BoxStyle => new GUIStyle(K_BOX_STYPE); + + private static ulong _genId = ulong.MinValue; + private static ulong GenId + { + get + { + if (_genId == ulong.MaxValue) _genId = ulong.MinValue; + _genId++; + return _genId; + } + } + + public static void Label(string value, float width = 0, int fontSize = 0, FontStyle fontStyle = FontStyle.Normal, TextAnchor anchor = TextAnchor.MiddleLeft, params GUILayoutOption[] options) + { + GUILayoutOption w = null; + if (width > 0) + { + w = GUILayout.Width(width); + } + + GUIStyle s = null; + if (fontSize > 0) + { + s = new GUIStyle("Label"); + s.fontSize = fontSize; + s.alignment = anchor; + s.fontStyle = fontStyle; + } + + List opts = new List(); + if (w != null) opts.Add(w); + if (options != null && options.Length > 0) opts.AddRange(options); + + if (s == null) + { + GUILayout.Label(value, opts.ToArray()); + return; + } + + GUILayout.Label(value, s, opts.ToArray()); + } + + /// + /// 水平Box布局 + /// + /// + public static void HBox(Action content) + { + GUILayout.BeginHorizontal(BoxStyle); + content?.Invoke(); + GUILayout.EndHorizontal(); + } + + /// + /// 水平Box布局 + /// + /// + public static void VBox(Action content) + { + GUILayout.BeginVertical(BoxStyle); + content?.Invoke(); + GUILayout.EndVertical(); + } + + + /// + /// BoxLineItem 风格图框 + /// + /// + /// + /// + /// + public static void BoxLineItem(string label, float width = 60, int fontSize = 0, params Action[] contents) + { + HBox( + () => + { + Label(label, width, fontSize); + if (contents != null && contents.Length > 0) + { + for (int i = 0; i < contents.Length; i++) + { + contents[i]?.Invoke(); + } + } + } + ); + } + + /// + /// Text 文本框 + /// + /// + /// + public static string Text(string value, Action onValueChanged = null, params GUILayoutOption[] options) + { + return Text(value, "", null, onValueChanged, options);; + } + + /// + /// Text 文本框 + /// + /// + /// + public static string Text(string value, string label, Action onValueChanged = null, params GUILayoutOption[] options) + { + return Text(value, label, null, onValueChanged, options); + } + + /// + /// Text 文本框 + /// + /// + /// + public static string Text(string value, GUIStyle style, Action onValueChanged = null, params GUILayoutOption[] options) + { + return Text(value, "", style, onValueChanged, options); + } + + + /// + /// Text 文本框 + /// + /// + /// + public static string Text(string text , string label, GUIStyle style, Action onValueChanged = null, params GUILayoutOption[] options) + { + string _cname = label; + if (string.IsNullOrEmpty(_cname)) _cname = $"lab_{GenId}"; + GUI.SetNextControlName(_cname); + + string newValue = ""; + if (string.IsNullOrEmpty(label) && style == null) + { + newValue = EditorGUILayout.TextField(text, options); + } + else if (string.IsNullOrEmpty(label)) + { + newValue = EditorGUILayout.TextField(text, style, options); + } + else if (style == null) + { + newValue = EditorGUILayout.TextField(label, text, options); + } + else + { + newValue = EditorGUILayout.TextField(label, text, style, options); + } + + if ( newValue != text ) + // && GUI.GetNameOfFocusedControl() != _cname) + { + if (null != onValueChanged) + { + onValueChanged?.Invoke(newValue); + } + } + return newValue; + } + + /// + /// Text 文本框 + /// + /// + /// + public static bool Toggle(bool value, Action onValueChanged = null) + { + bool newValue = GUILayout.Toggle(value, ""); + if (newValue != value) + { + if (null != onValueChanged) + { + onValueChanged?.Invoke(newValue); + } + } + return newValue; + } + + } +} \ No newline at end of file diff --git a/Editor/EasyGUILayout.cs.meta b/Editor/EasyGUILayout.cs.meta new file mode 100644 index 0000000..0b5ab6e --- /dev/null +++ b/Editor/EasyGUILayout.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e1efa9261bb6437aa4815df890e456cc +timeCreated: 1700635233 \ No newline at end of file diff --git a/Editor/EditorExtention.cs b/Editor/EditorExtention.cs new file mode 100644 index 0000000..e0ddbdc --- /dev/null +++ b/Editor/EditorExtention.cs @@ -0,0 +1,59 @@ +using System.IO; + +namespace Guru.Editor +{ + public static class GuruEditorExtentions + { + + + + public static bool FileExists(this IFileIO _, string filePath) => File.Exists(filePath); + + public static bool DirectoryExists(this IFileIO _, string directoryPath) => Directory.Exists(directoryPath); + + public static void EnsureDir(this IFileIO _, string dirPath) + { + var dir = new DirectoryInfo(dirPath); + if(!dir.Exists) dir.Create(); + } + + public static void EnsureRootDir(this IFileIO _, string filePath) => + EnsureDir(_, Directory.GetParent(filePath)?.FullName); + + public static bool DeleteFile(this IFileIO _, string filePath) + { + if (FileExists(_, filePath)) + { + File.Delete(filePath); + return true; + } + return false; + } + + public static bool MoveFile(this IFileIO _,string from, string to) + { + if (FileExists(_, from)) + { + EnsureRootDir(_, to); + DeleteFile(_, to); + File.Move(from, to); + return true; + } + return false; + } + + public static bool CopyFile(this IFileIO _,string from, string to) + { + if (FileExists(_, from)) + { + EnsureRootDir(_, to); + File.Copy(from, to); + return true; + } + return false; + } + + + + } +} \ No newline at end of file diff --git a/Editor/EditorExtention.cs.meta b/Editor/EditorExtention.cs.meta new file mode 100644 index 0000000..b28b28a --- /dev/null +++ b/Editor/EditorExtention.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eebf6b41fef246e0839ce1d54f4128bc +timeCreated: 1700802014 \ No newline at end of file diff --git a/Editor/GuruEditorMax.asmdef b/Editor/GuruEditorMax.asmdef new file mode 100644 index 0000000..ac2ec88 --- /dev/null +++ b/Editor/GuruEditorMax.asmdef @@ -0,0 +1,18 @@ +{ + "name": "GuruEditorMax", + "rootNamespace": "Guru.Editor.Max", + "references": [ + "MaxSdk.Scripts.IntegrationManager.Editor" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Editor/GuruEditorMax.asmdef.meta b/Editor/GuruEditorMax.asmdef.meta new file mode 100644 index 0000000..01d9fa9 --- /dev/null +++ b/Editor/GuruEditorMax.asmdef.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 07910557543a4b178acb19f69b340971 +timeCreated: 1700624261 \ No newline at end of file diff --git a/Editor/GuruEditorMax.meta b/Editor/GuruEditorMax.meta new file mode 100644 index 0000000..e187ff5 --- /dev/null +++ b/Editor/GuruEditorMax.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c41a373610a894ceaba39989220343db +timeCreated: 1700211475 \ No newline at end of file diff --git a/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs b/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs new file mode 100644 index 0000000..b950036 --- /dev/null +++ b/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs @@ -0,0 +1,381 @@ +using System; +using AppLovinMax.Scripts.IntegrationManager.Editor; +using UnityEditor; +using UnityEngine; +using EUI= Guru.EasyGUILayout; +using Network = AppLovinMax.Scripts.IntegrationManager.Editor.Network; + +namespace Guru.Editor.Max +{ + public class GuruMaxIntegrationManager: EditorWindow + { + private static GuruMaxIntegrationManager _currentWindow; + private static Vector2 _miniSize = new Vector2(600, 800); + private AppLovinSettings _settings; + + private static GUIStyle _labelBoldStyle; + + public static GUIStyle LabelBoldStyle { + get { + if (_labelBoldStyle == null) + { + _labelBoldStyle = new GUIStyle(EditorStyles.label) + { + fontSize = 14, + fontStyle = FontStyle.Bold, + fixedHeight = 20 + }; + } + + return _labelBoldStyle; + } + } + + private string _maxSdkKey; + private string _admobAndroidId; + private string _admobIOSId; + private bool _qualityServiceEnabled = true; + private bool _setAttributionReportEndpoint = true; + private bool _isDirty; + + //------- AppLovinData -------- + private AppLovinEditorCoroutine loadDataCoroutine; + private PluginData pluginData; + + #region 生命周期 + + + + /// + /// 打开窗体 + /// + public static void Open() + { + if (_currentWindow != null) + { + _currentWindow.Close(); + } + _currentWindow = GetWindow(); + if (_currentWindow != null) + { + _currentWindow.minSize = _miniSize; + _currentWindow.Show(); + } + } + + + private void Awake() + { + this.titleContent = new GUIContent("Guru.Max"); + } + + + /// + /// 窗体激活 + /// + private void OnEnable() + { + LoadSettings(); + _isDirty = false; + + LoadPluginData(); + } + + private void OnDisable() + { + CheckSaveData(true); + + if (loadDataCoroutine != null) + { + loadDataCoroutine.Stop(); + loadDataCoroutine = null; + } + } + + #endregion + + + #region GUI + + + private void OnGUI() + { + + GUI_Title(); + GUILayout.Space(4); + GUI_MaxParamsSettings(); + GUILayout.Space(8); + GUI_DrawMediatedNetworks(); +#if MAX_DEV + GUILayout.Space(8); + GUI_DebugMenu(); +#endif + CheckSaveData(); + } + + + private float _timePassed = 0; + private void CheckSaveData(bool force = false) + { + _timePassed += Time.deltaTime; + + if (force || _timePassed >= 2 ) + { + if ( force || _isDirty) + { + SaveSettings(); + _isDirty = false; + } + _timePassed= 0; + } + } + + + private void GUI_Title() + { + GUILayout.Space(10); + EUI.Label("Guru Max Manager", 0, 24, FontStyle.Bold, TextAnchor.MiddleCenter); + GUILayout.Space(4); + EUI.Label($"Version: {GuruMaxSdkAPI.Version}", fontSize:12, anchor:TextAnchor.MiddleCenter); + GUILayout.Space(16); + } + + + #endregion + + #region DataSave + + private void LoadSettings() + { + _settings = GuruMaxSdkAPI.LoadOrCreateAppLovinSettings(); + if (null != _settings) + { + _maxSdkKey = _settings.SdkKey; + _admobAndroidId = _settings.AdMobAndroidAppId; + _admobIOSId = _settings.AdMobIosAppId; + _qualityServiceEnabled = _settings.QualityServiceEnabled; + _setAttributionReportEndpoint = _settings.SetAttributionReportEndpoint; + } + else + { + Debug.LogError("[GuruMax] Load AppLovinSettings failed..."); + if(EditorUtility.DisplayDialog("Guru Max", "Can't find AppLovinSettings in project, Something is wrong.", "OK")) + { + Close(); + } + } + } + + + + private void SaveSettings() + { + if (null != _settings) + { + _settings.SdkKey = _maxSdkKey; + _settings.AdMobAndroidAppId = _admobAndroidId; + _settings.AdMobIosAppId = _admobIOSId; + _settings.QualityServiceEnabled = _qualityServiceEnabled; + _settings.SetAttributionReportEndpoint = _setAttributionReportEndpoint; + + EditorUtility.SetDirty(_settings); + AssetDatabase.SaveAssetIfDirty(_settings); + + Debug.Log("[GuruMax] AppLovinSettings Saved."); + } + } + + + #endregion + + #region Params Settings + + + private void GUI_MaxParamsSettings() + { + EditorGUILayout.LabelField("AppLovin Settings", LabelBoldStyle); + GUILayout.Space(4); + string indentStr = " "; + + float label_width = 160; + EUI.Label($"{indentStr}[ Keys for Max ]"); + //----------- MAX SDK KEY ----------- + EUI.BoxLineItem($"{indentStr}AppLovin SDK Key", label_width, contents: () => + { + EUI.Text(_maxSdkKey, value => + { + _isDirty = true; + _maxSdkKey = value; + }); + }); + + GUILayout.Space(8); + EUI.Label($"{indentStr}[ Ids for AdMob ]"); + EUI.BoxLineItem($"{indentStr}Google App ID (Android)", label_width, contents: () => + { + EUI.Text(_admobAndroidId, value => + { + _isDirty = true; + _admobAndroidId = value; + }); + }); + + EUI.BoxLineItem($"{indentStr}Google App ID (iOS)", label_width, contents: () => + { + EUI.Text(_admobIOSId, value => + { + _isDirty = true; + _admobIOSId = value; + }); + }); + GUILayout.Space(8); + + + EUI.Label($"{indentStr}[ Default: {GuruMaxSdkAPI.DefaultQualityServiceEnabled} ]"); + EUI.BoxLineItem($"{indentStr}Quality Service Enabled", label_width, contents: () => + { + EUI.Toggle(_qualityServiceEnabled, value => + { + _isDirty = true; + _qualityServiceEnabled = value; + }); + }); + GUILayout.Space(8); + + EUI.Label($"{indentStr}[ Default: {GuruMaxSdkAPI.DefaultAttributionReportEndpoint} ]"); + EUI.BoxLineItem($"{indentStr}Attribution Report Endpoint(iOS)", label_width, contents: () => + { + EUI.Toggle(_setAttributionReportEndpoint, value => + { + _isDirty = true; + _setAttributionReportEndpoint = value; + }); + }); + GUILayout.Space(8); + + } + + + #endregion + + #region AppLovinData + + + private void LoadPluginData() + { + loadDataCoroutine = AppLovinEditorCoroutine.StartCoroutine( + AppLovinIntegrationManager.Instance.LoadPluginData( data => { + if (data != null) + { + pluginData = data; + _showNetworks = true; + } + })); + } + + private bool _showNetworks = false; + private Vector2 scrollPos; + /// + /// 绘制接入的各种Network + /// + private void GUI_DrawMediatedNetworks() + { + + float label_width = 160; + EditorGUILayout.LabelField("Mediated Networks", LabelBoldStyle); + + + _showNetworks = EditorGUILayout.Foldout(_showNetworks, "Installed Networks" + (pluginData == null ? " (loading...)": "")); + + if (_showNetworks) + { + if (pluginData == null || pluginData.MediatedNetworks == null) + { + EditorGUILayout.LabelField("Loading...", new GUIStyle("box"), GUILayout.Width(this.minSize.x)); + } + else + { + + using (new EditorGUILayout.VerticalScope("box")) + { + EditorGUI.indentLevel++; + DrawMaxTitle("Network", "Android", "iOS"); + // scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(320)); + GUILayout.Space(6); + Network network = null; + for (int i =0; i < pluginData.MediatedNetworks.Length; i++) + { + network = pluginData.MediatedNetworks[i]; + if ( null != network && network.CurrentVersions != null && + !string.IsNullOrEmpty(network.CurrentVersions.Unity)) + { + DrawMaxNetwork(network); + GUILayout.Space(2); + } + } + // EditorGUILayout.EndScrollView(); + EditorGUI.indentLevel--; + } + } + } + + } + + + private void DrawMaxTitle(string name, string androidVersion, string iosVersion) + { + var st = new GUIStyle(EditorStyles.label) + { + fontSize = 14, + fontStyle = FontStyle.Bold, + fixedHeight = 22 + }; + + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField(name, st); + // GUILayout.Space(2); + EditorGUILayout.LabelField(androidVersion, st); + // GUILayout.Space(2); + EditorGUILayout.LabelField(iosVersion, st); + } + } + + private void DrawMaxNetwork(Network network) + { + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUILayout.LabelField(network.DisplayName); + // GUILayout.Space(2); + EditorGUILayout.LabelField(network.CurrentVersions.Android ?? "..."); + // GUILayout.Space(2); + EditorGUILayout.LabelField(network.CurrentVersions.Ios ?? "..."); + } + } + + + #endregion + + #region Debug + + + private bool _showMaxIntegrateManager = false; + private void GUI_DebugMenu() + { + EditorGUILayout.LabelField("Debug Menu", LabelBoldStyle); + GUILayout.Space(2); + + bool val = EditorGUILayout.Toggle("Show Max Menu", _showMaxIntegrateManager); + if (val != _showMaxIntegrateManager) + { + _showMaxIntegrateManager = val; + GuruMaxSdkAPI.SetMaxMenuActive(val); + } + + + + } + + #endregion + } +} \ No newline at end of file diff --git a/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs.meta b/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs.meta new file mode 100644 index 0000000..c7467dd --- /dev/null +++ b/Editor/GuruEditorMax/GuruMaxIntegrationManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ab5131664ada4d4b88c8c0201bf341b6 +timeCreated: 1700622836 \ No newline at end of file diff --git a/Editor/GuruEditorMax/GuruMaxMenuItems.cs b/Editor/GuruEditorMax/GuruMaxMenuItems.cs new file mode 100644 index 0000000..2feccf7 --- /dev/null +++ b/Editor/GuruEditorMax/GuruMaxMenuItems.cs @@ -0,0 +1,16 @@ +namespace Guru.Editor.Max +{ + using UnityEditor; + using UnityEngine; + + public class GuruMaxMenuItems + { + #if GURU_MAX_MENU + [MenuItem("Guru/AppLovin/Integration Manager")] + #endif + private static void ShowGuruMaxIntegrationManager() + { + GuruMaxIntegrationManager.Open(); + } + } +} \ No newline at end of file diff --git a/Editor/GuruEditorMax/GuruMaxMenuItems.cs.meta b/Editor/GuruEditorMax/GuruMaxMenuItems.cs.meta new file mode 100644 index 0000000..da0e4a5 --- /dev/null +++ b/Editor/GuruEditorMax/GuruMaxMenuItems.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 462d994fe9644e5e91f4f4abccc4cf75 +timeCreated: 1700622699 \ No newline at end of file diff --git a/Editor/GuruEditorMax/GuruMaxSdkAPI.cs b/Editor/GuruEditorMax/GuruMaxSdkAPI.cs new file mode 100644 index 0000000..c416fbd --- /dev/null +++ b/Editor/GuruEditorMax/GuruMaxSdkAPI.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using UnityEditor; +using UnityEditor.Compilation; +using Debug = UnityEngine.Debug; + +namespace Guru.Editor.Max +{ + + /// + /// GuruMaxIntegrationManager Support for MaxPlugins + /// + public class GuruMaxSdkAPI + { + // ------------ VERSION INFO ------------ + public const string Version = "0.1.0"; + public const string SdkVersion = "5.11.3"; + // ------------ VERSION INFO ------------ + + public const string PackageName = "com.guru.unity.max"; + private static readonly string AppLovinSettingsRootDir = "Assets/Guru/Resources"; + private static string AppLovinSettingsAssetPath = $"{AppLovinSettingsRootDir}/AppLovinSettings.asset"; + + public static bool DefaultQualityServiceEnabled = true; + public static bool DefaultUseMaxConsentFlow = false; + public static bool DefaultAttributionReportEndpoint = true; + + + + /// + /// GuruMaxIntegrationManager Max 的根目录地址 + /// + public static string PackageDataPath + { + get + { +#if GURU_SDK_DEV + return DevPackageRoot; +#endif + return $"Packages/{PackageName}"; + + } + } + + +#if GURU_SDK_DEV + private static readonly string DefaultDevPackageRoot = $"Assets/__upm/{PackageName}"; + private static string _devPackageRoot = ""; + public static string DevPackageRoot + { + get + { + if (string.IsNullOrEmpty(_devPackageRoot)) + { + _devPackageRoot = DefaultDevPackageRoot; + var assets = AssetDatabase.FindAssets($"GuruMaxSdkAPI t:script"); + if (assets != null && assets.Length > 0) + { + string path = AssetDatabase.GUIDToAssetPath(assets[0]); + if (File.Exists(path) && path.Replace("\\", "/").Contains("/Editor")) + { + _devPackageRoot = path.Replace("/Editor", ",").Split(',')[0]; + } + } + } + return _devPackageRoot; + } + } +#endif + + + + /// + /// 加载并修复AppLovinSettings组件路径和位置 + /// + public static AppLovinSettings LoadOrCreateAppLovinSettings() + { + + // 若原始文件存在 + if (File.Exists(Path.Combine(Application.dataPath.Replace("Assets", ""), AppLovinSettingsAssetPath))) + { + return AssetDatabase.LoadAssetAtPath(AppLovinSettingsAssetPath); + } + + // 否则开始查找文件 + var guids = AssetDatabase.FindAssets("AppLovinSettings t:ScriptableObject"); + + int removed = 0; + if (guids.Length > 0) + { + foreach (var g in guids) + { + var path = AssetDatabase.GUIDToAssetPath(g); + + Debug.Log($"--- Found assets at path:{path}"); + + + if (!path.StartsWith(AppLovinSettingsRootDir)) + { + AssetDatabase.DeleteAsset(path); + removed++; + } + } + } + + if (guids.Length == 0 || removed >= guids.Length) + { + return CreateDefaultAppLovinSettings(); // 创建默认的AppLovin Settings 配置 + } + + + return AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guids[0])); + + + } + + /// + /// 创建AppLovinSettings 配置默认路径 + /// + /// + private static AppLovinSettings CreateDefaultAppLovinSettings() + { + // Create Root dir + var expDir = + new DirectoryInfo(Path.Combine(Application.dataPath.Replace("Assets", ""), AppLovinSettingsRootDir)); + if (!expDir.Exists) expDir.Create(); + + // Make a new one + var settings = ScriptableObject.CreateInstance(); + settings.QualityServiceEnabled = DefaultQualityServiceEnabled; + settings.SetAttributionReportEndpoint = DefaultAttributionReportEndpoint; + settings.ConsentFlowEnabled = DefaultUseMaxConsentFlow; + AssetDatabase.CreateAsset(settings, AppLovinSettingsAssetPath); + AssetDatabase.SaveAssetIfDirty(settings); + AssetDatabase.Refresh(); + + Debug.Log($"[Guru] --- Create AppLovinSettings at: \n{AppLovinSettingsAssetPath}"); + + return settings; + } + + + /// + /// 是否显示MAX菜单 + /// + /// + public static void SetMaxMenuActive(bool active) + { + if (active) + { + ApplovinMod.MenuItemsRecover(); + } + else + { + ApplovinMod.MenuItemsHide(); + } + CompilationPipeline.RequestScriptCompilation(); + } + + /// + /// 移动文件 + /// + /// + /// + private static void MoveFile(string from, string to) + { + if (!File.Exists(from)) + { + Debug.Log($"File not found: {from}"); + return; + } + + if (File.Exists(to)) File.Delete(to); + + File.Move(from, to); + Debug.Log($"File move: {from} to \n{to}"); + } + + } + + +} \ No newline at end of file diff --git a/Editor/GuruEditorMax/GuruMaxSdkAPI.cs.meta b/Editor/GuruEditorMax/GuruMaxSdkAPI.cs.meta new file mode 100644 index 0000000..f31ebeb --- /dev/null +++ b/Editor/GuruEditorMax/GuruMaxSdkAPI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ff9c52b08d64e4b52b59646de0cbdcf5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/IFileIO.cs b/Editor/IFileIO.cs new file mode 100644 index 0000000..1c26180 --- /dev/null +++ b/Editor/IFileIO.cs @@ -0,0 +1,7 @@ +namespace Guru +{ + public class IFileIO + { + + } +} \ No newline at end of file diff --git a/Editor/IFileIO.cs.meta b/Editor/IFileIO.cs.meta new file mode 100644 index 0000000..6668341 --- /dev/null +++ b/Editor/IFileIO.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 05389be35a144a72ba846a082148d66c +timeCreated: 1700801996 \ No newline at end of file diff --git a/Editor/Test.meta b/Editor/Test.meta new file mode 100644 index 0000000..51074e6 --- /dev/null +++ b/Editor/Test.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a8c01fc58fb90438d97e8c1d29955cb4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Test/GuruMaxTest.cs b/Editor/Test/GuruMaxTest.cs new file mode 100644 index 0000000..edaf0c9 --- /dev/null +++ b/Editor/Test/GuruMaxTest.cs @@ -0,0 +1,35 @@ +using System.Collections; +using System.Collections.Generic; +using Guru.Editor.Max; +using NUnit.Framework; +using UnityEditor; +using UnityEngine; + +namespace Guru.Editor +{ + public class GuruMaxTest + { + [Test] + public void TestSettingsPath() + { + var sttings = AppLovinSettings.Instance; + + var path = AssetDatabase.GetAssetPath(sttings.GetInstanceID()); + Debug.Log($"path: {path}"); + Debug.Log($"SdkKey: {sttings.SdkKey}"); + Debug.Log($"AdMobAndroidAppId: {sttings.AdMobAndroidAppId}"); + Debug.Log($"AdMobIosAppId: {sttings.AdMobIosAppId}"); + + } + +#if GURU_SDK_DEV + // 测试API检测地址 + [Test] + public void Test_GetAPIPath() + { + var aipPath = GuruMaxSdkAPI.DevPackageRoot; + Debug.Log($"--- aipPath: {aipPath}"); + } +#endif + } +} diff --git a/Editor/Test/GuruMaxTest.cs.meta b/Editor/Test/GuruMaxTest.cs.meta new file mode 100644 index 0000000..4083f06 --- /dev/null +++ b/Editor/Test/GuruMaxTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02c9b658cf394409f8d331edf7f53922 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/GuruMax.asmdef b/GuruMax.asmdef new file mode 100644 index 0000000..3b6fab1 --- /dev/null +++ b/GuruMax.asmdef @@ -0,0 +1,17 @@ +{ + "name": "GuruMax", + "references": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [ + "GURU_MAX" + ], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/GuruMax.asmdef.meta b/GuruMax.asmdef.meta new file mode 100644 index 0000000..943badc --- /dev/null +++ b/GuruMax.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f7ff085cbd25241beb0289b3ffc6fe32 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk.meta b/MaxSdk.meta new file mode 100644 index 0000000..ea74ffa --- /dev/null +++ b/MaxSdk.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 314db9fe234a74acdb84517d32a1c16b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/AppLovin.meta b/MaxSdk/AppLovin.meta new file mode 100644 index 0000000..e025615 --- /dev/null +++ b/MaxSdk/AppLovin.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24350f435b5f14067b88bad9e54f4776 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/AppLovin/Editor.meta b/MaxSdk/AppLovin/Editor.meta new file mode 100644 index 0000000..7224034 --- /dev/null +++ b/MaxSdk/AppLovin/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c096cc384c7446b5b962f359a291792 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/AppLovin/Editor/Dependencies.xml b/MaxSdk/AppLovin/Editor/Dependencies.xml new file mode 100644 index 0000000..b951879 --- /dev/null +++ b/MaxSdk/AppLovin/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/MaxSdk/AppLovin/Editor/Dependencies.xml.meta b/MaxSdk/AppLovin/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..50f9829 --- /dev/null +++ b/MaxSdk/AppLovin/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a36972e13b9b64a87a11421020969d76 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/AppLovin/Plugins.meta b/MaxSdk/AppLovin/Plugins.meta new file mode 100644 index 0000000..cad18f4 --- /dev/null +++ b/MaxSdk/AppLovin/Plugins.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f0263dd851654e7598f11593e8da7a8 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/AppLovin/Plugins/Android.meta b/MaxSdk/AppLovin/Plugins/Android.meta new file mode 100644 index 0000000..cb45a3d --- /dev/null +++ b/MaxSdk/AppLovin/Plugins/Android.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b47263f475c14ff8861bc3b40f416b9 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins/Android +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar b/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar new file mode 100644 index 0000000000000000000000000000000000000000..9d2a709a5fd3be423cf718213f8b42eea54189a2 GIT binary patch literal 75984 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 +#import + +NS_ASSUME_NONNULL_BEGIN +typedef const void *MAUnityRef; +typedef void (*ALUnityBackgroundCallback)(const char* args); + +@interface MAUnityAdManager : NSObject + +- (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; ++ (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)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)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)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)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)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; + +// Event Tracking +- (void)trackEvent:(NSString *)event parameters:(NSString *)parameters; + +// Ad Info +- (NSString *)adInfoForAdUnitIdentifier:(NSString *)adUnitIdentifier; + +// Ad Value +- (NSString *)adValueForAdUnitIdentifier:(NSString *)adUnitIdentifier withKey:(NSString *)key; + +// User Service +- (void)didDismissUserConsentDialog; + +// Consent Flow +- (void)startConsentFlow; + +// Utils ++ (NSString *)serializeParameters:(NSDictionary *)dict; ++ (NSDictionary *)deserializeParameters:(NSString *)serialized; + +/** + * Creates an instance of @c MAUnityAdManager if needed and returns the singleton instance. + */ ++ (instancetype)shared; + +- (instancetype)init NS_UNAVAILABLE; + +@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 new file mode 100644 index 0000000..47ae840 --- /dev/null +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta @@ -0,0 +1,115 @@ +fileFormatVersion: 2 +guid: d3a319587a4a744d898e112357c46370 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + Exclude tvOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m new file mode 100644 index 0000000..ad26ac6 --- /dev/null +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m @@ -0,0 +1,2046 @@ +// +// MAUnityAdManager.m +// AppLovin MAX Unity Plugin +// + +#import "MAUnityAdManager.h" + +#define VERSION @"5.11.4" + +#define KEY_WINDOW [UIApplication sharedApplication].keyWindow +#define DEVICE_SPECIFIC_ADVIEW_AD_FORMAT ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) ? MAAdFormat.leader : MAAdFormat.banner +#define IS_VERTICAL_BANNER_POSITION(_POS) ( [@"center_left" isEqual: adViewPosition] || [@"center_right" isEqual: adViewPosition] ) +#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI) + +#ifdef __cplusplus +extern "C" { +#endif + + // UnityAppController.mm + UIViewController* UnityGetGLViewController(void); + UIWindow* UnityGetMainWindow(void); + + // life cycle management + void UnityPause(int pause); + void UnitySendMessage(const char* obj, const char* method, const char* msg); + + void max_unity_dispatch_on_main_thread(dispatch_block_t block) + { + if ( block ) + { + if ( [NSThread isMainThread] ) + { + block(); + } + else + { + dispatch_async(dispatch_get_main_queue(), block); + } + } + } +#ifdef __cplusplus +} +#endif + +@interface MAUnityAdManager() + +// Parent Fields +@property (nonatomic, weak) ALSdk *sdk; + +// Fullscreen Ad Fields +@property (nonatomic, strong) NSMutableDictionary *interstitials; +@property (nonatomic, strong) NSMutableDictionary *appOpenAds; +@property (nonatomic, strong) NSMutableDictionary *rewardedAds; +@property (nonatomic, strong) NSMutableDictionary *rewardedInterstitialAds; + +// AdView Fields +@property (nonatomic, strong) NSMutableDictionary *adViews; +@property (nonatomic, strong) NSMutableDictionary *adViewAdFormats; +@property (nonatomic, strong) NSMutableDictionary *adViewPositions; +@property (nonatomic, strong) NSMutableDictionary *adViewOffsets; +@property (nonatomic, strong) NSMutableDictionary *adViewWidths; +@property (nonatomic, strong) NSMutableDictionary *crossPromoAdViewHeights; +@property (nonatomic, strong) NSMutableDictionary *crossPromoAdViewRotations; +@property (nonatomic, strong) NSMutableDictionary *verticalAdViewFormats; +@property (nonatomic, strong) NSMutableDictionary *> *adViewConstraints; +@property (nonatomic, strong) NSMutableDictionary *> *adViewExtraParametersToSetAfterCreate; +@property (nonatomic, strong) NSMutableDictionary *> *adViewLocalExtraParametersToSetAfterCreate; +@property (nonatomic, strong) NSMutableDictionary *adViewCustomDataToSetAfterCreate; +@property (nonatomic, strong) NSMutableArray *adUnitIdentifiersToShowAfterCreate; +@property (nonatomic, strong) NSMutableSet *disabledAdaptiveBannerAdUnitIdentifiers; +@property (nonatomic, strong) NSMutableSet *disabledAutoRefreshAdViewAdUnitIdentifiers; +@property (nonatomic, strong) UIView *safeAreaBackground; +@property (nonatomic, strong, nullable) UIColor *publisherBannerBackgroundColor; + +@property (nonatomic, strong) NSMutableDictionary *adInfoDict; +@property (nonatomic, strong) NSObject *adInfoDictLock; + +@end + +// Internal +@interface UIColor (ALUtils) ++ (nullable UIColor *)al_colorWithHexString:(NSString *)hexString; +@end + +@interface NSNumber (ALUtils) ++ (NSNumber *)al_numberWithString:(NSString *)string; +@end + +@interface NSString (ALUtils) +@property (assign, readonly, getter=al_isValidString) BOOL al_validString; +@end + +@interface MAAdFormat (ALUtils) +@property (nonatomic, assign, readonly, getter=isFullscreenAd) BOOL fullscreenAd; +@property (nonatomic, assign, readonly, getter=isAdViewAd) BOOL adViewAd; +@end + +@implementation MAUnityAdManager +static NSString *const SDK_TAG = @"AppLovinSdk"; +static NSString *const TAG = @"MAUnityAdManager"; +static NSString *const DEFAULT_AD_VIEW_POSITION = @"top_left"; +static ALUnityBackgroundCallback backgroundCallback; + +#pragma mark - Initialization + +- (instancetype)init +{ + self = [super init]; + if ( self ) + { + self.interstitials = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.appOpenAds = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.rewardedAds = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.rewardedInterstitialAds = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViews = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewAdFormats = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewPositions = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewOffsets = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewWidths = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.crossPromoAdViewHeights = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.crossPromoAdViewRotations = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.verticalAdViewFormats = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewConstraints = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewExtraParametersToSetAfterCreate = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adViewLocalExtraParametersToSetAfterCreate = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adViewCustomDataToSetAfterCreate = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adUnitIdentifiersToShowAfterCreate = [NSMutableArray arrayWithCapacity: 2]; + self.disabledAdaptiveBannerAdUnitIdentifiers = [NSMutableSet setWithCapacity: 2]; + self.disabledAutoRefreshAdViewAdUnitIdentifiers = [NSMutableSet setWithCapacity: 2]; + self.adInfoDict = [NSMutableDictionary dictionary]; + self.adInfoDictLock = [[NSObject alloc] init]; + + max_unity_dispatch_on_main_thread(^{ + self.safeAreaBackground = [[UIView alloc] init]; + self.safeAreaBackground.hidden = YES; + self.safeAreaBackground.backgroundColor = UIColor.clearColor; + self.safeAreaBackground.translatesAutoresizingMaskIntoConstraints = NO; + self.safeAreaBackground.userInteractionEnabled = NO; + + UIViewController *rootViewController = [self unityViewController]; + [rootViewController.view addSubview: self.safeAreaBackground]; + }); + + // Enable orientation change listener, so that the position can be updated for vertical banners. + [[NSNotificationCenter defaultCenter] addObserverForName: UIDeviceOrientationDidChangeNotification + object: nil + queue: [NSOperationQueue mainQueue] + usingBlock:^(NSNotification *notification) { + + for ( NSString *adUnitIdentifier in self.verticalAdViewFormats ) + { + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: self.verticalAdViewFormats[adUnitIdentifier]]; + } + }]; + } + return self; +} + ++ (MAUnityAdManager *)shared +{ + static dispatch_once_t token; + static MAUnityAdManager *shared; + dispatch_once(&token, ^{ + shared = [[MAUnityAdManager alloc] init]; + }); + return shared; +} + +#pragma mark - Plugin Initialization + +- (ALSdk *)initializeSdkWithSettings:(ALSdkSettings *)settings + backgroundCallback:(ALUnityBackgroundCallback)unityBackgroundCallback + andCompletionHandler:(ALSdkInitializationCompletionHandler)completionHandler +{ + backgroundCallback = unityBackgroundCallback; + NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; + NSString *sdkKey = infoDict[@"AppLovinSdkKey"]; + if ( [sdkKey al_isValidString] ) + { + self.sdk = [ALSdk sharedWithKey: sdkKey settings: settings]; + } + else + { + 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) + { + // Note: internal state should be updated first + completionHandler( configuration ); + + 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", + @"consentDialogState" : consentDialogStateStr, + @"countryCode" : configuration.countryCode, + @"appTrackingStatus" : appTrackingStatus, + @"isSuccessfullyInitialized" : @([self.sdk isInitialized]), + @"isTestModeEnabled" : @([configuration isTestModeEnabled])}]; + }]; + + return self.sdk; +} + +#pragma mark - Banners + +- (void)createBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier atPosition:(NSString *)bannerPosition +{ + [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] atPosition: bannerPosition withOffset: CGPointZero]; +} + +- (void)createBannerWithAdUnitIdentifier:(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 +{ + [self loadAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)setBannerBackgroundColorForAdUnitIdentifier:(NSString *)adUnitIdentifier hexColorCode:(NSString *)hexColorCode +{ + [self setAdViewBackgroundColorForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] hexColorCode: hexColorCode]; +} + +- (void)setBannerPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)startBannerAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self startAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)stopBannerAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self stopAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)setBannerWidth:(CGFloat)width forAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self setAdViewWidth: width forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)updateBannerPosition:(NSString *)bannerPosition forAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self updateAdViewPosition: bannerPosition withOffset: CGPointZero forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)updateBannerPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(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 +{ + [self setAdViewExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] key: key value: value]; +} + +- (void)setBannerLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +{ + [self setAdViewLocalExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] key: key value: value]; +} + +- (void)setBannerCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self setAdViewCustomData: customData forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)showBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)hideBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (NSString *)bannerLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + return [self adViewLayoutForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)destroyBannerWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + ++ (CGFloat)adaptiveBannerHeightForWidth:(CGFloat)width +{ + return [DEVICE_SPECIFIC_ADVIEW_AD_FORMAT adaptiveSizeForWidth: width].height; +} + +#pragma mark - MRECs + +- (void)createMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier atPosition:(NSString *)mrecPosition +{ + [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec atPosition: mrecPosition withOffset: CGPointZero]; +} + +- (void)createMRecWithAdUnitIdentifier:(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 +{ + [self loadAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)setMRecPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)startMRecAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self startAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)stopMRecAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self stopAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)updateMRecPosition:(NSString *)mrecPosition forAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self updateAdViewPosition: mrecPosition withOffset: CGPointZero forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)updateMRecPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(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 +{ + [self setAdViewExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec key: key value: value]; +} + +- (void)setMRecLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +{ + [self setAdViewLocalExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec key: key value: value]; +} + +- (void)setMRecCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier; +{ + [self setAdViewCustomData: customData forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)showMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)destroyMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)hideMRecWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (NSString *)mrecLayoutForAdUnitIdentifier:(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 +{ + self.adViewWidths[adUnitIdentifier] = @(width); + self.crossPromoAdViewHeights[adUnitIdentifier] = @(height); + self.crossPromoAdViewRotations[adUnitIdentifier] = @(rotation); + [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo atPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset)]; +} + +- (void)setCrossPromoAdPlacement:(nullable NSString *)placement forAdUnitIdentifier:(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 +{ + self.adViewWidths[adUnitIdentifier] = @(width); + self.crossPromoAdViewHeights[adUnitIdentifier] = @(height); + self.crossPromoAdViewRotations[adUnitIdentifier] = @(rotation); + [self updateAdViewPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset) forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; +} + +- (void)showCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; +} + +- (void)destroyCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; +} + +- (void)hideCrossPromoAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + [self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; +} + +- (NSString *)crossPromoAdLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + return [self adViewLayoutForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.crossPromo]; +} + +#pragma mark - Interstitials + +- (void)loadInterstitialWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + [interstitial loadAd]; +} + +- (BOOL)isInterstitialReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + return [interstitial isReady]; +} + +- (void)showInterstitialWithAdUnitIdentifier:(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 +{ + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + [interstitial setExtraParameterForKey: key value: value]; +} + +- (void)setInterstitialLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +{ + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + [interstitial setLocalExtraParameterForKey: key value: value]; +} + +#pragma mark - App Open Ads + +- (void)loadAppOpenAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + [appOpenAd loadAd]; +} + +- (BOOL)isAppOpenAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + return [appOpenAd isReady]; +} + +- (void)showAppOpenAdWithAdUnitIdentifier:(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 +{ + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + [appOpenAd setExtraParameterForKey: key value: value]; +} + +- (void)setAppOpenAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +{ + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + [appOpenAd setLocalExtraParameterForKey: key value: value]; +} + +#pragma mark - Rewarded + +- (void)loadRewardedAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedAd loadAd]; +} + +- (BOOL)isRewardedAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + return [rewardedAd isReady]; +} + +- (void)showRewardedAdWithAdUnitIdentifier:(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 +{ + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedAd setExtraParameterForKey: key value: value]; +} + +- (void)setRewardedAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value; +{ + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedAd setLocalExtraParameterForKey: key value: value]; +} + +#pragma mark - Rewarded Interstitials + +- (void)loadRewardedInterstitialAdWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedInterstitialAd loadAd]; +} + +- (BOOL)isRewardedInterstitialAdReadyWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + return [rewardedInterstitialAd isReady]; +} + +- (void)showRewardedInterstitialAdWithAdUnitIdentifier:(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 +{ + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedInterstitialAd setExtraParameterForKey: key value: value]; +} + +- (void)setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier key:(NSString *)key value:(nullable id)value +{ + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedInterstitialAd setLocalExtraParameterForKey: key value: value]; +} + +#pragma mark - Event Tracking + +- (void)trackEvent:(NSString *)event parameters:(NSString *)parameters +{ + NSDictionary *deserializedParameters = [MAUnityAdManager deserializeParameters: parameters]; + [self.sdk.eventService trackEvent: event parameters: deserializedParameters]; +} + +#pragma mark - Ad Info + +- (NSString *)adInfoForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + if ( adUnitIdentifier.length == 0 ) return @""; + + MAAd *ad = [self adWithAdUnitIdentifier: adUnitIdentifier]; + if ( !ad ) return @""; + + return [MAUnityAdManager serializeParameters: [self adInfoForAd: ad]]; +} + +- (NSDictionary *)adInfoForAd:(MAAd *)ad +{ + return @{@"adUnitId" : ad.adUnitIdentifier, + @"adFormat" : ad.format.label, + @"networkName" : ad.networkName, + @"networkPlacement" : ad.networkPlacement, + @"creativeId" : ad.creativeIdentifier ?: @"", + @"placement" : ad.placement ?: @"", + @"revenue" : [@(ad.revenue) stringValue], + @"revenuePrecision" : ad.revenuePrecision, + @"waterfallInfo" : [self createAdWaterfallInfo: ad.waterfall], + @"dspName" : ad.DSPName ?: @""}; +} + +#pragma mark - Waterfall Information + +- (NSDictionary *)createAdWaterfallInfo:(MAAdWaterfallInfo *)waterfallInfo +{ + NSMutableDictionary *waterfallInfoDict = [NSMutableDictionary dictionary]; + if ( !waterfallInfo ) return waterfallInfoDict; + + waterfallInfoDict[@"name"] = waterfallInfo.name; + waterfallInfoDict[@"testName"] = waterfallInfo.testName; + + NSMutableArray *> *networkResponsesArray = [NSMutableArray arrayWithCapacity: waterfallInfo.networkResponses.count]; + for ( MANetworkResponseInfo *response in waterfallInfo.networkResponses ) + { + [networkResponsesArray addObject: [self createNetworkResponseInfo: response]]; + } + waterfallInfoDict[@"networkResponses"] = networkResponsesArray; + + // Convert latency from seconds to milliseconds to match Android. + long latencyMillis = waterfallInfo.latency * 1000; + waterfallInfoDict[@"latencyMillis"] = @(latencyMillis).stringValue; + + return waterfallInfoDict; +} + +- (NSDictionary *)createNetworkResponseInfo:(MANetworkResponseInfo *)response +{ + NSMutableDictionary *networkResponseDict = [NSMutableDictionary dictionary]; + + networkResponseDict[@"adLoadState"] = @(response.adLoadState).stringValue; + + MAMediatedNetworkInfo *mediatedNetworkInfo = response.mediatedNetwork; + if ( mediatedNetworkInfo ) + { + NSMutableDictionary *networkInfoObject = [NSMutableDictionary dictionary]; + networkInfoObject[@"name"] = response.mediatedNetwork.name; + networkInfoObject[@"adapterClassName"] = response.mediatedNetwork.adapterClassName; + networkInfoObject[@"adapterVersion"] = response.mediatedNetwork.adapterVersion; + networkInfoObject[@"sdkVersion"] = response.mediatedNetwork.sdkVersion; + + networkResponseDict[@"mediatedNetwork"] = networkInfoObject; + } + + networkResponseDict[@"credentials"] = response.credentials; + networkResponseDict[@"isBidding"] = @([response isBidding]); + + MAError *error = response.error; + if ( error ) + { + NSMutableDictionary *errorObject = [NSMutableDictionary dictionary]; + errorObject[@"errorMessage"] = error.message; + errorObject[@"adLoadFailure"] = error.adLoadFailureInfo; + errorObject[@"errorCode"] = @(error.code).stringValue; + + networkResponseDict[@"error"] = errorObject; + } + + // Convert latency from seconds to milliseconds to match Android. + long latencySeconds = response.latency * 1000; + networkResponseDict[@"latencyMillis"] = @(latencySeconds).stringValue; + + return networkResponseDict; +} + +#pragma mark - Ad Value + +- (NSString *)adValueForAdUnitIdentifier:(NSString *)adUnitIdentifier withKey:(NSString *)key +{ + if ( adUnitIdentifier.length == 0 ) return @""; + + MAAd *ad = [self adWithAdUnitIdentifier: adUnitIdentifier]; + if ( !ad ) return @""; + + return [ad adValueForKey: key]; +} + +#pragma mark - Ad Callbacks + +- (void)didLoadAd:(MAAd *)ad +{ + NSString *name; + MAAdFormat *adFormat = ad.format; + if ( [adFormat isAdViewAd] ) + { + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: ad.adUnitIdentifier adFormat: adFormat]; + // An ad is now being shown, enable user interaction. + adView.userInteractionEnabled = YES; + + if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdLoadedEvent"; + } + else if ( MAAdFormat.crossPromo == adFormat ) + { + name = @"OnCrossPromoAdLoadedEvent"; + } + else + { + name = @"OnBannerAdLoadedEvent"; + } + [self positionAdViewForAd: ad]; + + // Do not auto-refresh by default if the ad view is not showing yet (e.g. first load during app launch and publisher does not automatically show banner upon load success) + // We will resume auto-refresh in -[MAUnityAdManager showBannerWithAdUnitIdentifier:]. + if ( adView && [adView isHidden] ) + { + [adView stopAutoRefresh]; + } + } + else if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialLoadedEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdLoadedEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdLoadedEvent"; + } + else if ( MAAdFormat.rewardedInterstitial == adFormat ) + { + name = @"OnRewardedInterstitialAdLoadedEvent"; + } + else + { + [self logInvalidAdFormat: adFormat]; + return; + } + + @synchronized ( self.adInfoDictLock ) + { + self.adInfoDict[ad.adUnitIdentifier] = ad; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [MAUnityAdManager forwardUnityEventWithArgs: args]; +} + +- (void)didFailToLoadAdForAdUnitIdentifier:(NSString *)adUnitIdentifier withError:(MAError *)error +{ + if ( !adUnitIdentifier ) + { + [self log: @"adUnitIdentifier cannot be nil from %@", [NSThread callStackSymbols]]; + return; + } + + NSString *name; + if ( self.adViews[adUnitIdentifier] ) + { + MAAdFormat *adFormat = self.adViewAdFormats[adUnitIdentifier]; + if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdLoadFailedEvent"; + } + else if ( MAAdFormat.crossPromo == adFormat ) + { + name = @"OnCrossPromoAdLoadFailedEvent"; + } + else + { + name = @"OnBannerAdLoadFailedEvent"; + } + } + else if ( self.interstitials[adUnitIdentifier] ) + { + name = @"OnInterstitialLoadFailedEvent"; + } + else if ( self.appOpenAds[adUnitIdentifier] ) + { + name = @"OnAppOpenAdLoadFailedEvent"; + } + else if ( self.rewardedAds[adUnitIdentifier] ) + { + name = @"OnRewardedAdLoadFailedEvent"; + } + else if ( self.rewardedInterstitialAds[adUnitIdentifier] ) + { + name = @"OnRewardedInterstitialAdLoadFailedEvent"; + } + else + { + [self log: @"invalid adUnitId from %@", [NSThread callStackSymbols]]; + return; + } + + @synchronized ( self.adInfoDictLock ) + { + [self.adInfoDict removeObjectForKey: adUnitIdentifier]; + } + + [MAUnityAdManager forwardUnityEventWithArgs: @{@"name" : name, + @"adUnitId" : adUnitIdentifier, + @"errorCode" : [@(error.code) stringValue], + @"errorMessage" : error.message, + @"waterfallInfo" : [self createAdWaterfallInfo: error.waterfall], + @"adLoadFailureInfo" : error.adLoadFailureInfo ?: @""}]; +} + +- (void)didClickAd:(MAAd *)ad +{ + NSString *name; + MAAdFormat *adFormat = ad.format; + if ( MAAdFormat.banner == adFormat || MAAdFormat.leader == adFormat ) + { + name = @"OnBannerAdClickedEvent"; + } + else if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdClickedEvent"; + } + else if ( MAAdFormat.crossPromo == adFormat ) + { + name = @"OnCrossPromoAdClickedEvent"; + } + else if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialClickedEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdClickedEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdClickedEvent"; + } + else if ( MAAdFormat.rewardedInterstitial == adFormat ) + { + name = @"OnRewardedInterstitialAdClickedEvent"; + } + else + { + [self logInvalidAdFormat: adFormat]; + return; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [MAUnityAdManager forwardUnityEventWithArgs: args]; +} + +- (void)didDisplayAd:(MAAd *)ad +{ + // BMLs do not support [DISPLAY] events in Unity + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isFullscreenAd] ) return; + +#if !IS_TEST_APP + UnityPause(1); +#endif + + NSString *name; + if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialDisplayedEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdDisplayedEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdDisplayedEvent"; + } + else // rewarded inters + { + name = @"OnRewardedInterstitialAdDisplayedEvent"; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [MAUnityAdManager forwardUnityEventWithArgs: args]; +} + +- (void)didFailToDisplayAd:(MAAd *)ad withError:(MAError *)error +{ + // BMLs do not support [DISPLAY] events in Unity + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isFullscreenAd] ) return; + + NSString *name; + if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialAdFailedToDisplayEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdFailedToDisplayEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdFailedToDisplayEvent"; + } + else // rewarded inters + { + name = @"OnRewardedInterstitialAdFailedToDisplayEvent"; + } + + NSMutableDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + args[@"errorCode"] = [@(error.code) stringValue]; + args[@"errorMessage"] = error.message; + args[@"mediatedNetworkErrorCode"] = [@(error.mediatedNetworkErrorCode) stringValue]; + args[@"mediatedNetworkErrorMessage"] = error.mediatedNetworkErrorMessage; + args[@"waterfallInfo"] = [self createAdWaterfallInfo: error.waterfall]; + [MAUnityAdManager forwardUnityEventWithArgs: args]; +} + +- (void)didHideAd:(MAAd *)ad +{ + // BMLs do not support [HIDDEN] events in Unity + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isFullscreenAd] ) return; + +#if !IS_TEST_APP + UnityPause(0); +#endif + + NSString *name; + if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialHiddenEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdHiddenEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdHiddenEvent"; + } + else // rewarded inters + { + name = @"OnRewardedInterstitialAdHiddenEvent"; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [MAUnityAdManager forwardUnityEventWithArgs: args]; +} + +- (void)didExpandAd:(MAAd *)ad +{ + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isAdViewAd] ) + { + [self logInvalidAdFormat: adFormat]; + return; + } + +#if !IS_TEST_APP + UnityPause(1); +#endif + + NSString *name; + if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdExpandedEvent"; + } + else if ( MAAdFormat.crossPromo == adFormat ) + { + name = @"OnCrossPromoAdExpandedEvent"; + } + else + { + name = @"OnBannerAdExpandedEvent"; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [MAUnityAdManager forwardUnityEventWithArgs: args]; +} + +- (void)didCollapseAd:(MAAd *)ad +{ + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isAdViewAd] ) + { + [self logInvalidAdFormat: adFormat]; + return; + } + +#if !IS_TEST_APP + UnityPause(0); +#endif + + NSString *name; + if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdCollapsedEvent"; + } + else if ( MAAdFormat.crossPromo == adFormat ) + { + name = @"OnCrossPromoAdCollapsedEvent"; + } + else + { + name = @"OnBannerAdCollapsedEvent"; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [MAUnityAdManager forwardUnityEventWithArgs: args]; +} + +- (void)didStartRewardedVideoForAd:(MAAd *)ad +{ + // This event is not forwarded +} + +- (void)didCompleteRewardedVideoForAd:(MAAd *)ad +{ + // This event is not forwarded +} + +- (void)didRewardUserForAd:(MAAd *)ad withReward:(MAReward *)reward +{ + MAAdFormat *adFormat = ad.format; + if ( adFormat != MAAdFormat.rewarded && adFormat != MAAdFormat.rewardedInterstitial ) + { + [self logInvalidAdFormat: adFormat]; + return; + } + + NSString *rewardLabel = reward ? reward.label : @""; + NSInteger rewardAmountInt = reward ? reward.amount : 0; + NSString *rewardAmount = [@(rewardAmountInt) stringValue]; + + NSString *name = (adFormat == MAAdFormat.rewarded) ? @"OnRewardedAdReceivedRewardEvent" : @"OnRewardedInterstitialAdReceivedRewardEvent"; + + + NSMutableDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + args[@"rewardLabel"] = rewardLabel; + args[@"rewardAmount"] = rewardAmount; + [MAUnityAdManager forwardUnityEventWithArgs: args]; +} + +- (void)didPayRevenueForAd:(MAAd *)ad +{ + NSString *name; + MAAdFormat *adFormat = ad.format; + if ( MAAdFormat.banner == adFormat || MAAdFormat.leader == adFormat ) + { + name = @"OnBannerAdRevenuePaidEvent"; + } + else if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdRevenuePaidEvent"; + } + else if ( MAAdFormat.crossPromo == adFormat ) + { + name = @"OnCrossPromoAdRevenuePaidEvent"; + } + else if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialAdRevenuePaidEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdRevenuePaidEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdRevenuePaidEvent"; + } + else if ( MAAdFormat.rewardedInterstitial == adFormat ) + { + name = @"OnRewardedInterstitialAdRevenuePaidEvent"; + } + else + { + [self logInvalidAdFormat: adFormat]; + return; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [MAUnityAdManager forwardUnityEventWithArgs: args forwardInBackground: [adFormat isFullscreenAd]]; +} + +- (void)didGenerateCreativeIdentifier:(NSString *)creativeIdentifier forAd:(MAAd *)ad +{ + NSString *name; + MAAdFormat *adFormat = ad.format; + if ( MAAdFormat.banner == adFormat || MAAdFormat.leader == adFormat ) + { + name = @"OnBannerAdReviewCreativeIdGeneratedEvent"; + } + else if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdReviewCreativeIdGeneratedEvent"; + } + else if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialAdReviewCreativeIdGeneratedEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdReviewCreativeIdGeneratedEvent"; + } + else if ( MAAdFormat.rewardedInterstitial == adFormat ) + { + name = @"OnRewardedInterstitialAdReviewCreativeIdGeneratedEvent"; + } + else + { + [self logInvalidAdFormat: adFormat]; + return; + } + + NSMutableDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + args[@"adReviewCreativeId"] = creativeIdentifier; + + // Forward the event in background for fullscreen ads so that the user gets the callback even while the ad is playing. + [MAUnityAdManager forwardUnityEventWithArgs: args forwardInBackground: [adFormat isFullscreenAd]]; +} + +- (NSMutableDictionary *)defaultAdEventParametersForName:(NSString *)name withAd:(MAAd *)ad +{ + NSMutableDictionary *args = [[self adInfoForAd: ad] mutableCopy]; + args[@"name"] = name; + + return args; +} + +#pragma mark - Internal Methods + +- (void)createAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat atPosition:(NSString *)adViewPosition withOffset:(CGPoint)offset +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Creating %@ with ad unit identifier \"%@\" and position: \"%@\"", adFormat, adUnitIdentifier, adViewPosition]; + + if ( self.adViews[adUnitIdentifier] ) + { + [self log: @"Trying to create a %@ that was already created. This will cause the current ad to be hidden.", adFormat.label]; + } + + // Retrieve ad view from the map + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat atPosition: adViewPosition withOffset: offset]; + adView.hidden = YES; + self.safeAreaBackground.hidden = YES; + + // Position ad view immediately so if publisher sets color before ad loads, it will not be the size of the screen + 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 ) ) + { + [adView setExtraParameterForKey: @"adaptive_banner" value: @"true"]; + } + + // Handle initial extra parameters if publisher sets it before creating ad view + if ( self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier] ) + { + NSDictionary *extraParameters = self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier]; + for ( NSString *key in extraParameters ) + { + [adView setExtraParameterForKey: key value: extraParameters[key]]; + + [self handleExtraParameterChangesIfNeededForAdUnitIdentifier: adUnitIdentifier + adFormat: adFormat + key: key + value: extraParameters[key]]; + } + + [self.adViewExtraParametersToSetAfterCreate removeObjectForKey: adUnitIdentifier]; + } + + // Handle initial local extra parameters if publisher sets it before creating ad view + if ( self.adViewLocalExtraParametersToSetAfterCreate[adUnitIdentifier] ) + { + NSDictionary *localExtraParameters = self.adViewLocalExtraParametersToSetAfterCreate[adUnitIdentifier]; + for ( NSString *key in localExtraParameters ) + { + [adView setLocalExtraParameterForKey: key value: localExtraParameters[key]]; + } + + [self.adViewLocalExtraParametersToSetAfterCreate removeObjectForKey: adUnitIdentifier]; + } + + // Handle initial custom data if publisher sets it before creating ad view + if ( self.adViewCustomDataToSetAfterCreate[adUnitIdentifier] ) + { + NSString *customData = self.adViewCustomDataToSetAfterCreate[adUnitIdentifier]; + adView.customData = customData; + + [self.adViewCustomDataToSetAfterCreate removeObjectForKey: adUnitIdentifier]; + } + + [adView loadAd]; + + // Disable auto-refresh if publisher sets it before creating the ad view. + if ( [self.disabledAutoRefreshAdViewAdUnitIdentifiers containsObject: adUnitIdentifier] ) + { + [adView stopAutoRefresh]; + } + + // The publisher may have requested to show the banner before it was created. Now that the banner is created, show it. + if ( [self.adUnitIdentifiersToShowAfterCreate containsObject: adUnitIdentifier] ) + { + [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + [self.adUnitIdentifiersToShowAfterCreate removeObject: adUnitIdentifier]; + } + }); +} + +- (void)loadAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !adView ) + { + [self log: @"%@ does not exist for ad unit identifier %@.", adFormat.label, adUnitIdentifier]; + return; + } + + if ( ![self.disabledAutoRefreshAdViewAdUnitIdentifiers containsObject: adUnitIdentifier] ) + { + if ( [adView isHidden] ) + { + [self log: @"Auto-refresh will resume when the %@ ad is shown. You should only call LoadBanner() or LoadMRec() if you explicitly pause auto-refresh and want to manually load an ad.", adFormat.label]; + return; + } + + [self log: @"You must stop auto-refresh if you want to manually load %@ ads.", adFormat.label]; + return; + } + + [adView loadAd]; + }); +} + +- (void)setAdViewBackgroundColorForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat hexColorCode:(NSString *)hexColorCode +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting %@ with ad unit identifier \"%@\" to color: \"%@\"", adFormat, adUnitIdentifier, hexColorCode]; + + // In some cases, black color may get redrawn on each frame update, resulting in an undesired flicker + NSString *hexColorCodeToUse = [hexColorCode containsString: @"FF000000"] ? @"FF000001" : hexColorCode; + UIColor *convertedColor = [UIColor al_colorWithHexString: hexColorCodeToUse]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + self.publisherBannerBackgroundColor = convertedColor; + self.safeAreaBackground.backgroundColor = view.backgroundColor = convertedColor; + + // Position adView to ensure logic that depends on background color is properly run + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + }); +} + +- (void)setAdViewPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting placement \"%@\" for \"%@\" with ad unit identifier \"%@\"", placement, adFormat, adUnitIdentifier]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + adView.placement = placement; + }); +} + +- (void)startAdViewAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Starting %@ auto refresh for ad unit identifier \"%@\"", adFormat.label, adUnitIdentifier]; + + [self.disabledAutoRefreshAdViewAdUnitIdentifiers removeObject: adUnitIdentifier]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !adView ) + { + [self log: @"%@ does not exist for ad unit identifier %@.", adFormat.label, adUnitIdentifier]; + return; + } + + [adView startAutoRefresh]; + }); +} + +- (void)stopAdViewAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Stopping %@ auto refresh for ad unit identifier \"%@\"", adFormat.label, adUnitIdentifier]; + + [self.disabledAutoRefreshAdViewAdUnitIdentifiers addObject: adUnitIdentifier]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !adView ) + { + [self log: @"%@ does not exist for ad unit identifier %@.", adFormat.label, adUnitIdentifier]; + return; + } + + [adView stopAutoRefresh]; + }); +} + +- (void)setAdViewWidth:(CGFloat)width forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting width %f for \"%@\" with ad unit identifier \"%@\"", width, adFormat, adUnitIdentifier]; + + CGFloat minWidth = 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.adViewWidths[adUnitIdentifier] = @(width); + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + }); +} + +- (void)updateAdViewPosition:(NSString *)adViewPosition withOffset:(CGPoint)offset forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + self.adViewPositions[adUnitIdentifier] = adViewPosition; + self.adViewOffsets[adUnitIdentifier] = [NSValue valueWithCGPoint: offset]; + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + }); +} + +- (void)setAdViewExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat key:(NSString *)key value:(nullable NSString *)value +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting %@ extra with key: \"%@\" value: \"%@\"", adFormat, key, value]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( adView ) + { + [adView setExtraParameterForKey: key value: value]; + } + else + { + [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]; + if ( !extraParameters ) + { + extraParameters = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier] = extraParameters; + } + + extraParameters[key] = value; + } + + // Certain extra parameters need to be handled immediately + [self handleExtraParameterChangesIfNeededForAdUnitIdentifier: adUnitIdentifier + adFormat: adFormat + key: key + value: value]; + }); +} + +- (void)setAdViewLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat key:(NSString *)key value:(nullable id)value +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting %@ local extra with key: \"%@\" value: \"%@\"", adFormat, key, value]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( adView ) + { + [adView setLocalExtraParameterForKey: key value: value]; + } + else + { + [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]; + if ( !localExtraParameters ) + { + localExtraParameters = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adViewLocalExtraParametersToSetAfterCreate[adUnitIdentifier] = localExtraParameters; + } + + localExtraParameters[key] = value; + } + }); +} + +- (void)setAdViewCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( adView ) + { + adView.customData = customData; + } + else + { + [self log: @"%@ does not exist for ad unit identifier %@. Saving custom data to be set when it is created.", adFormat, adUnitIdentifier]; + + // The adView has not yet been created. Store the custom data, so that they can be added once the AdView has been created. + self.adViewCustomDataToSetAfterCreate[adUnitIdentifier] = customData; + } + }); +} + +- (void)handleExtraParameterChangesIfNeededForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat key:(NSString *)key value:(nullable NSString *)value +{ + if ( MAAdFormat.mrec != adFormat ) + { + if ( [@"force_banner" isEqualToString: key] ) + { + BOOL shouldForceBanner = [NSNumber al_numberWithString: value].boolValue; + MAAdFormat *forcedAdFormat = shouldForceBanner ? MAAdFormat.banner : DEVICE_SPECIFIC_ADVIEW_AD_FORMAT; + + self.adViewAdFormats[adUnitIdentifier] = forcedAdFormat; + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: forcedAdFormat]; + } + else if ( [@"adaptive_banner" isEqualToString: key] ) + { + BOOL shouldUseAdaptiveBanner = [NSNumber al_numberWithString: value].boolValue; + if ( shouldUseAdaptiveBanner ) + { + [self.disabledAdaptiveBannerAdUnitIdentifiers removeObject: adUnitIdentifier]; + } + else + { + [self.disabledAdaptiveBannerAdUnitIdentifiers addObject: adUnitIdentifier]; + } + + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + } + } +} + +- (void)showAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Showing %@ with ad unit identifier \"%@\"", adFormat, adUnitIdentifier]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !view ) + { + [self log: @"%@ does not exist for ad unit identifier %@.", adFormat, adUnitIdentifier]; + + // The adView has not yet been created. Store the ad unit ID, so that it can be displayed once the banner has been created. + [self.adUnitIdentifiersToShowAfterCreate addObject: adUnitIdentifier]; + } + else + { + // Check edge case where ad may be detatched from view controller + if ( !view.window.rootViewController ) + { + [self log: @"%@ missing view controller - re-attaching to %@...", adFormat, [self unityViewController]]; + + UIViewController *rootViewController = [self unityViewController]; + [rootViewController.view addSubview: view]; + + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + } + } + + self.safeAreaBackground.hidden = NO; + view.hidden = NO; + + if ( ![self.disabledAutoRefreshAdViewAdUnitIdentifiers containsObject: adUnitIdentifier] ) + { + [view startAutoRefresh]; + } + }); +} + +- (void)hideAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Hiding %@ with ad unit identifier \"%@\"", adFormat, adUnitIdentifier]; + [self.adUnitIdentifiersToShowAfterCreate removeObject: adUnitIdentifier]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + view.hidden = YES; + self.safeAreaBackground.hidden = YES; + + [view stopAutoRefresh]; + }); +} + +- (NSString *)adViewLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + [self log: @"Getting %@ position with ad unit identifier \"%@\"", adFormat, adUnitIdentifier]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !view ) + { + [self log: @"%@ does not exist for ad unit identifier %@", adFormat, adUnitIdentifier]; + + return @""; + } + + CGRect adViewFrame = view.frame; + return [MAUnityAdManager serializeParameters: @{@"origin_x" : [NSString stringWithFormat: @"%f", adViewFrame.origin.x], + @"origin_y" : [NSString stringWithFormat: @"%f", adViewFrame.origin.y], + @"width" : [NSString stringWithFormat: @"%f", CGRectGetWidth(adViewFrame)], + @"height" : [NSString stringWithFormat: @"%f", CGRectGetHeight(adViewFrame)]}]; +} + +- (void)destroyAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Destroying %@ with ad unit identifier \"%@\"", adFormat, adUnitIdentifier]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + view.delegate = nil; + view.revenueDelegate = nil; + view.adReviewDelegate = nil; + + [view removeFromSuperview]; + + [self.adViews removeObjectForKey: adUnitIdentifier]; + [self.adViewAdFormats removeObjectForKey: adUnitIdentifier]; + [self.adViewPositions removeObjectForKey: adUnitIdentifier]; + [self.adViewOffsets removeObjectForKey: adUnitIdentifier]; + [self.adViewWidths removeObjectForKey: adUnitIdentifier]; + [self.crossPromoAdViewHeights removeObjectForKey: adUnitIdentifier]; + [self.crossPromoAdViewRotations removeObjectForKey: adUnitIdentifier]; + [self.verticalAdViewFormats removeObjectForKey: adUnitIdentifier]; + [self.disabledAdaptiveBannerAdUnitIdentifiers removeObject: adUnitIdentifier]; + }); +} + +- (void)logInvalidAdFormat:(MAAdFormat *)adFormat +{ + [self log: @"invalid ad format: %@, from %@", adFormat, [NSThread callStackSymbols]]; +} + +- (void)log:(NSString *)format, ... +{ + va_list valist; + va_start(valist, format); + NSString *message = [[NSString alloc] initWithFormat: format arguments: valist]; + va_end(valist); + + NSLog(@"[%@] [%@] %@", SDK_TAG, TAG, message); +} + ++ (void)log:(NSString *)format, ... +{ + va_list valist; + va_start(valist, format); + NSString *message = [[NSString alloc] initWithFormat: format arguments: valist]; + va_end(valist); + + NSLog(@"[%@] [%@] %@", SDK_TAG, TAG, message); +} + +- (MAInterstitialAd *)retrieveInterstitialForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MAInterstitialAd *result = self.interstitials[adUnitIdentifier]; + if ( !result ) + { + result = [[MAInterstitialAd alloc] initWithAdUnitIdentifier: adUnitIdentifier sdk: self.sdk]; + result.delegate = self; + result.revenueDelegate = self; + result.adReviewDelegate = self; + + self.interstitials[adUnitIdentifier] = result; + } + + return result; +} + +- (MAAppOpenAd *)retrieveAppOpenAdForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MAAppOpenAd *result = self.appOpenAds[adUnitIdentifier]; + if ( !result ) + { + result = [[MAAppOpenAd alloc] initWithAdUnitIdentifier: adUnitIdentifier sdk: self.sdk]; + result.delegate = self; + result.revenueDelegate = self; + + self.appOpenAds[adUnitIdentifier] = result; + } + + return result; +} + +- (MARewardedAd *)retrieveRewardedAdForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MARewardedAd *result = self.rewardedAds[adUnitIdentifier]; + if ( !result ) + { + result = [MARewardedAd sharedWithAdUnitIdentifier: adUnitIdentifier sdk: self.sdk]; + result.delegate = self; + result.revenueDelegate = self; + result.adReviewDelegate = self; + + self.rewardedAds[adUnitIdentifier] = result; + } + + return result; +} + +- (MARewardedInterstitialAd *)retrieveRewardedInterstitialAdForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MARewardedInterstitialAd *result = self.rewardedInterstitialAds[adUnitIdentifier]; + if ( !result ) + { + result = [[MARewardedInterstitialAd alloc] initWithAdUnitIdentifier: adUnitIdentifier sdk: self.sdk]; + result.delegate = self; + result.revenueDelegate = self; + result.adReviewDelegate = self; + + self.rewardedInterstitialAds[adUnitIdentifier] = result; + } + + return result; +} + +- (MAAdView *)retrieveAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + return [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat atPosition: nil withOffset: CGPointZero]; +} + +- (MAAdView *)retrieveAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat atPosition:(NSString *)adViewPosition withOffset:(CGPoint)offset +{ + MAAdView *result = self.adViews[adUnitIdentifier]; + if ( !result && adViewPosition ) + { + result = [[MAAdView alloc] initWithAdUnitIdentifier: adUnitIdentifier adFormat: adFormat sdk: self.sdk]; + // There is a Unity bug where if an empty UIView is on screen with user interaction enabled, and a user interacts with it, it just passes the events to random parts of the screen. + result.userInteractionEnabled = NO; + result.translatesAutoresizingMaskIntoConstraints = NO; + result.delegate = self; + result.revenueDelegate = self; + result.adReviewDelegate = self; + + self.adViews[adUnitIdentifier] = result; + self.adViewPositions[adUnitIdentifier] = adViewPosition; + self.adViewOffsets[adUnitIdentifier] = [NSValue valueWithCGPoint: offset]; + + UIViewController *rootViewController = [self unityViewController]; + [rootViewController.view addSubview: result]; + + // Allow pubs to pause auto-refresh immediately, by default. + [result setExtraParameterForKey: @"allow_pause_auto_refresh_immediately" value: @"true"]; + } + + return result; +} + +- (void)positionAdViewForAd:(MAAd *)ad +{ + [self positionAdViewForAdUnitIdentifier: ad.adUnitIdentifier adFormat: ad.format]; +} + +- (void)positionAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + NSString *adViewPosition = self.adViewPositions[adUnitIdentifier]; + NSValue *adViewPositionValue = self.adViewOffsets[adUnitIdentifier]; + CGPoint adViewOffset = [adViewPositionValue CGPointValue]; + BOOL isAdaptiveBannerDisabled = [self.disabledAdaptiveBannerAdUnitIdentifiers containsObject: adUnitIdentifier]; + BOOL isWidthPtsOverridden = self.adViewWidths[adUnitIdentifier] != nil; + BOOL isCrossPromoHeightPtsOverridden = self.crossPromoAdViewHeights[adUnitIdentifier] != nil; + BOOL isCrossPromoRotationOverridden = self.crossPromoAdViewRotations[adUnitIdentifier] != nil; + + UIView *superview = adView.superview; + if ( !superview ) return; + + // Deactivate any previous constraints and reset rotation so that the banner can be positioned again. + NSArray *activeConstraints = self.adViewConstraints[adUnitIdentifier]; + [NSLayoutConstraint deactivateConstraints: activeConstraints]; + adView.transform = CGAffineTransformIdentity; + [self.verticalAdViewFormats removeObjectForKey: adUnitIdentifier]; + + // Ensure superview contains the safe area background. + if ( ![superview.subviews containsObject: self.safeAreaBackground] ) + { + [self.safeAreaBackground removeFromSuperview]; + [superview insertSubview: self.safeAreaBackground belowSubview: adView]; + } + + // Deactivate any previous constraints and reset visibility state so that the safe area background can be positioned again. + [NSLayoutConstraint deactivateConstraints: self.safeAreaBackground.constraints]; + self.safeAreaBackground.hidden = adView.hidden; + + // + // Determine ad width + // + CGFloat adViewWidth; + + // Check if publisher has overridden width as points + if ( isWidthPtsOverridden ) + { + adViewWidth = self.adViewWidths[adUnitIdentifier].floatValue; + } + // Top center / bottom center stretches full screen + else if ( [adViewPosition isEqual: @"top_center"] || [adViewPosition isEqual: @"bottom_center"] ) + { + adViewWidth = CGRectGetWidth(KEY_WINDOW.bounds); + } + // Else use standard widths of 320, 728, or 300 + else + { + adViewWidth = adFormat.size.width; + } + + // + // Determine ad height + // + CGFloat adViewHeight; + + if ( isCrossPromoHeightPtsOverridden ) + { + adViewHeight = self.crossPromoAdViewHeights[adUnitIdentifier].floatValue; + } + else if ( (adFormat == MAAdFormat.banner || adFormat == MAAdFormat.leader) && !isAdaptiveBannerDisabled ) + { + adViewHeight = [adFormat adaptiveSizeForWidth: adViewWidth].height; + } + else + { + adViewHeight = adFormat.size.height; + } + + CGSize adViewSize = CGSizeMake(adViewWidth, adViewHeight); + + // 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; + } + + if ( [adViewPosition isEqual: @"top_center"] || [adViewPosition isEqual: @"bottom_center"] ) + { + // Non AdMob banners will still be of 50/90 points tall. Set the auto sizing mask such that the inner ad view is pinned to the bottom or top according to the ad view position. + if ( !isAdaptiveBannerDisabled ) + { + adView.autoresizingMask = UIViewAutoresizingFlexibleWidth; + + if ( [@"top_center" isEqual: adViewPosition] ) + { + adView.autoresizingMask |= UIViewAutoresizingFlexibleBottomMargin; + } + else // bottom_center + { + adView.autoresizingMask |= UIViewAutoresizingFlexibleTopMargin; + } + } + + // If publisher actually provided a banner background color + if ( self.publisherBannerBackgroundColor && adFormat != MAAdFormat.mrec ) + { + if ( isWidthPtsOverridden ) + { + [constraints addObjectsFromArray: @[[adView.widthAnchor constraintEqualToConstant: adViewWidth], + [adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor], + [self.safeAreaBackground.widthAnchor constraintEqualToConstant: adViewWidth], + [self.safeAreaBackground.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor]]]; + + if ( [adViewPosition isEqual: @"top_center"] ) + { + [constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor], + [self.safeAreaBackground.topAnchor constraintEqualToAnchor: superview.topAnchor], + [self.safeAreaBackground.bottomAnchor constraintEqualToAnchor: adView.topAnchor]]]; + } + else // bottom_center + { + [constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor], + [self.safeAreaBackground.topAnchor constraintEqualToAnchor: adView.bottomAnchor], + [self.safeAreaBackground.bottomAnchor constraintEqualToAnchor: superview.bottomAnchor]]]; + } + } + else + { + [constraints addObjectsFromArray: @[[adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor], + [adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor], + [self.safeAreaBackground.leftAnchor constraintEqualToAnchor: superview.leftAnchor], + [self.safeAreaBackground.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + + if ( [adViewPosition isEqual: @"top_center"] ) + { + [constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor], + [self.safeAreaBackground.topAnchor constraintEqualToAnchor: superview.topAnchor], + [self.safeAreaBackground.bottomAnchor constraintEqualToAnchor: adView.topAnchor]]]; + } + else // bottom_center + { + [constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor], + [self.safeAreaBackground.topAnchor constraintEqualToAnchor: adView.bottomAnchor], + [self.safeAreaBackground.bottomAnchor constraintEqualToAnchor: superview.bottomAnchor]]]; + } + } + } + // If pub does not have a background color set or this is not a banner + else + { + self.safeAreaBackground.hidden = YES; + + [constraints addObjectsFromArray: @[[adView.widthAnchor constraintEqualToConstant: adViewWidth], + [adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor]]]; + + if ( [adViewPosition isEqual: @"top_center"] ) + { + [constraints addObject: [adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor]]; + } + else // BottomCenter + { + [constraints addObject: [adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor]]; + } + } + } + // Check if the publisher wants vertical banners. + else if ( [adViewPosition isEqual: @"center_left"] || [adViewPosition isEqual: @"center_right"] ) + { + if ( MAAdFormat.mrec == adFormat ) + { + [constraints addObject: [adView.widthAnchor constraintEqualToConstant: adViewSize.width]]; + + if ( [adViewPosition isEqual: @"center_left"] ) + { + [constraints addObjectsFromArray: @[[adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor], + [adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor]]]; + + [constraints addObjectsFromArray: @[[self.safeAreaBackground.rightAnchor constraintEqualToAnchor: layoutGuide.leftAnchor], + [self.safeAreaBackground.leftAnchor constraintEqualToAnchor: superview.leftAnchor]]]; + } + else // center_right + { + [constraints addObjectsFromArray: @[[adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor], + [adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + + [constraints addObjectsFromArray: @[[self.safeAreaBackground.leftAnchor constraintEqualToAnchor: layoutGuide.rightAnchor], + [self.safeAreaBackground.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + } + } + else + { + /* Align the center of the view such that when rotated it snaps into place. + * + * +---+---+-------+ + * | | | + * | | | + * | | | + * | | | + * | | | + * | | | + * +-------------+---+-----------+--+ + * | | + | + | | + * +-------------+---+-----------+--+ + * <+> | | + * |+ | | + * || | | + * || | | + * || | | + * || | | + * +|--+-----------+ + * v + * Banner Half Height + */ + self.safeAreaBackground.hidden = YES; + + adView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI_2); + + CGFloat width; + // If the publiser has a background color set - set the width to the height of the screen, to span the ad across the screen after it is rotated. + if ( self.publisherBannerBackgroundColor ) + { + if ( isWidthPtsOverridden ) + { + width = adViewWidth; + } + else + { + width = CGRectGetHeight(KEY_WINDOW.bounds); + } + } + // Otherwise - we shouldn't span the banner the width of the realm (there might be user-interactable UI on the sides) + else + { + width = adViewWidth; + } + [constraints addObject: [adView.widthAnchor constraintEqualToConstant: width]]; + + // Set constraints such that the center of the banner aligns with the center left or right as needed. That way, once rotated, the banner snaps into place. + [constraints addObject: [adView.centerYAnchor constraintEqualToAnchor: superview.centerYAnchor]]; + + // Place the center of the banner half the height of the banner away from the side. If we align the center exactly with the left/right anchor, only half the banner will be visible. + CGFloat bannerHalfHeight = adViewSize.height / 2.0; + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + if ( [adViewPosition isEqual: @"center_left"] ) + { + NSLayoutAnchor *anchor = ( orientation == UIInterfaceOrientationLandscapeRight ) ? layoutGuide.leftAnchor : superview.leftAnchor; + [constraints addObject: [adView.centerXAnchor constraintEqualToAnchor: anchor constant: bannerHalfHeight]]; + } + else // CenterRight + { + NSLayoutAnchor *anchor = ( orientation == UIInterfaceOrientationLandscapeLeft ) ? layoutGuide.rightAnchor : superview.rightAnchor; + [constraints addObject: [adView.centerXAnchor constraintEqualToAnchor: anchor constant: -bannerHalfHeight]]; + } + + // Store the ad view with format, so that it can be updated when the orientation changes. + self.verticalAdViewFormats[adUnitIdentifier] = adFormat; + + // If adaptive - make top flexible since we anchor with the bottom of the banner at the edge of the screen + if ( !isAdaptiveBannerDisabled ) + { + adView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; + } + } + } + // Otherwise, publisher will likely construct his own views around the adview + else + { + self.safeAreaBackground.hidden = YES; + + [constraints addObject: [adView.widthAnchor constraintEqualToConstant: adViewWidth]]; + + if ( [adViewPosition isEqual: @"top_left"] ) + { + [constraints addObjectsFromArray: @[[adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor constant: adViewOffset.x], + [adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor constant: adViewOffset.y]]]; + } + else if ( [adViewPosition isEqual: @"top_right"] ) + { + [constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor], + [adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + } + else if ( [adViewPosition isEqual: @"centered"] ) + { + [constraints addObjectsFromArray: @[[adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor], + [adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor]]]; + } + else if ( [adViewPosition isEqual: @"bottom_left"] ) + { + [constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor], + [adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor]]]; + } + else if ( [adViewPosition isEqual: @"bottom_right"] ) + { + [constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor], + [adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + } + } + + if ( isCrossPromoRotationOverridden ) + { + adView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, DEGREES_TO_RADIANS(self.crossPromoAdViewRotations[adUnitIdentifier].floatValue)); + } + + self.adViewConstraints[adUnitIdentifier] = constraints; + + [NSLayoutConstraint activateConstraints: constraints]; + }); +} + +- (UIViewController *)unityViewController +{ + // Handle edge case where `UnityGetGLViewController()` returns nil + return UnityGetGLViewController() ?: UnityGetMainWindow().rootViewController ?: [KEY_WINDOW rootViewController]; +} + ++ (void)forwardUnityEventWithArgs:(NSDictionary *)args +{ + [MAUnityAdManager forwardUnityEventWithArgs: args forwardInBackground: NO]; +} + ++ (void)forwardUnityEventWithArgs:(NSDictionary *)args forwardInBackground:(BOOL)forwardInBackground +{ +#if !IS_TEST_APP + char *serializedParameters = [self serializeParameters: args].UTF8String; + if ( forwardInBackground ) + { + backgroundCallback(serializedParameters); + } + else + { + UnitySendMessage("MaxSdkCallbacks", "ForwardEvent", serializedParameters); + } +#endif +} + ++ (NSString *)serializeParameters:(NSDictionary *)dict +{ + NSData *jsonData = [NSJSONSerialization dataWithJSONObject: dict options: 0 error: nil]; + return [[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding]; +} + ++ (NSDictionary *)deserializeParameters:(NSString *)serialized +{ + if ( serialized.length > 0 ) + { + NSError *error; + NSDictionary *deserialized = [NSJSONSerialization JSONObjectWithData: [serialized dataUsingEncoding:NSUTF8StringEncoding] + options: 0 + error: &error]; + if ( error ) + { + [self log: @"Failed to deserialize (%@) with error %@", serialized, error]; + return @{}; + } + + return deserialized; + } + else + { + return @{}; + } +} + +- (MAAdFormat *)adViewAdFormatForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + if ( self.adViewAdFormats[adUnitIdentifier] ) + { + return self.adViewAdFormats[adUnitIdentifier]; + } + else + { + return DEVICE_SPECIFIC_ADVIEW_AD_FORMAT; + } +} + +#pragma mark - User Service + +- (void)didDismissUserConsentDialog +{ + [MAUnityAdManager forwardUnityEventWithArgs: @{@"name" : @"OnSdkConsentDialogDismissedEvent"}]; +} + +#pragma mark - Consent Flow + +- (void)startConsentFlow +{ + [self.sdk.cfService scfWithCompletionHander:^(ALCFError * _Nullable error) { + + NSMutableDictionary *args = [NSMutableDictionary dictionaryWithCapacity: 3]; + args[@"name"] = @"OnSdkConsentFlowCompletedEvent"; + + if ( error ) + { + args[@"code"] = @(error.code); + args[@"message"] = error.message; + } + + [MAUnityAdManager forwardUnityEventWithArgs: args]; + }]; +} + +#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 ) + { + return self.adInfoDict[adUnitIdentifier]; + } +} + +@end diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta new file mode 100644 index 0000000..6cd047c --- /dev/null +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta @@ -0,0 +1,109 @@ +fileFormatVersion: 2 +guid: 6106db18e3d7745c0a67bd23e2996272 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + Exclude tvOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm b/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm new file mode 100644 index 0000000..7db976f --- /dev/null +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm @@ -0,0 +1,1105 @@ +// +// MAUnityPlugin.mm +// AppLovin MAX Unity Plugin +// + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#import "MAUnityAdManager.h" + +#define NSSTRING(_X) ( (_X != NULL) ? [NSString stringWithCString: _X encoding: NSStringEncodingConversionAllowLossy].al_stringByTrimmingWhitespace : nil) + +@interface NSString (ALUtils) +@property (nonatomic, copy, readonly) NSString *al_stringByTrimmingWhitespace; +@property (assign, readonly, getter=al_isValidString) BOOL al_validString; +@end + +UIView* UnityGetGLView(); + +// When native code plugin is implemented in .mm / .cpp file, then functions +// should be surrounded with extern "C" block to conform C function naming rules +extern "C" +{ + static NSString *const TAG = @"MAUnityPlugin"; + + static ALSdk *_sdk; + static MAUnityAdManager *_adManager; + static bool _isPluginInitialized = false; + static bool _isSdkInitialized = false; + static ALSdkConfiguration *_sdkConfiguration; + + // Store these values if pub attempts to set it before calling _MaxInitializeSdk() + static NSString *_userIdentifierToSet; + static NSString *_userSegmentNameToSet; + static NSArray *_testDeviceIdentifiersToSet; + static NSNumber *_verboseLoggingToSet; + static NSNumber *_creativeDebuggerEnabledToSet; + static NSNumber *_exceptionHandlerEnabledToSet; + static NSNumber *_locationCollectionEnabledToSet; + static NSNumber *_targetingYearOfBirth; + static NSString *_targetingGender; + static NSNumber *_targetingMaximumAdContentRating; + static NSString *_targetingEmail; + static NSString *_targetingPhoneNumber; + static NSArray *_targetingKeywords; + static NSArray *_targetingInterests; + static NSMutableDictionary *_extraParametersToSet = [NSMutableDictionary dictionary]; + static NSObject *_extraParametersToSetLock = [[NSObject alloc] init]; + + // Helper method to create C string copy + static const char * cStringCopy(NSString *string); + // Helper method to log errors + void logUninitializedAccessError(char *callingMethod); + + bool isPluginInitialized() + { + return _isPluginInitialized; + } + + void maybeInitializePlugin() + { + if ( isPluginInitialized() ) return; + + _adManager = [MAUnityAdManager shared]; + _isPluginInitialized = true; + } + + NSArray * toStringArray(char **arrayPointer, int size) + { + NSMutableArray *array = [NSMutableArray arrayWithCapacity: size]; + for ( int i = 0; i < size; i++ ) + { + [array addObject: NSSTRING(arrayPointer[i])]; + } + + return array; + } + + void setPendingExtraParametersIfNeeded(ALSdkSettings *settings) + { + NSDictionary *extraParameters; + @synchronized ( _extraParametersToSetLock ) + { + if ( _extraParametersToSet.count <= 0 ) return; + + extraParameters = [NSDictionary dictionaryWithDictionary: _extraParametersToSet]; + [_extraParametersToSet removeAllObjects]; + } + + for ( NSString *key in extraParameters.allKeys ) + { + [settings setExtraParameterForKey: key value: extraParameters[key]]; + } + } + + ALSdkSettings * generateSDKSettings(const char *serializedAdUnitIdentifiers, const char *serializedMetaData) + { + ALSdkSettings *settings = [[ALSdkSettings alloc] init]; + + setPendingExtraParametersIfNeeded( settings ); + + if ( _testDeviceIdentifiersToSet ) + { + settings.testDeviceAdvertisingIdentifiers = _testDeviceIdentifiersToSet; + _testDeviceIdentifiersToSet = nil; + } + + if ( _verboseLoggingToSet ) + { + settings.verboseLoggingEnabled = _verboseLoggingToSet.boolValue; + _verboseLoggingToSet = nil; + } + + if ( _creativeDebuggerEnabledToSet ) + { + settings.creativeDebuggerEnabled = _creativeDebuggerEnabledToSet.boolValue; + _creativeDebuggerEnabledToSet = nil; + } + + if ( _exceptionHandlerEnabledToSet ) + { + settings.exceptionHandlerEnabled = _exceptionHandlerEnabledToSet.boolValue; + _exceptionHandlerEnabledToSet = nil; + } + + if ( _locationCollectionEnabledToSet ) + { + settings.locationCollectionEnabled = _locationCollectionEnabledToSet.boolValue; + _locationCollectionEnabledToSet = nil; + } + + settings.initializationAdUnitIdentifiers = [[NSString stringWithUTF8String: serializedAdUnitIdentifiers] componentsSeparatedByString: @","]; + + NSDictionary *unityMetaData = [MAUnityAdManager deserializeParameters: [NSString stringWithUTF8String: serializedMetaData]]; + + // Set the meta data to settings. + NSMutableDictionary *metaDataDict = [settings valueForKey: @"metaData"]; + for ( NSString *key in unityMetaData ) + { + metaDataDict[key] = unityMetaData[key]; + } + + return settings; + } + + ALGender getAppLovinGender(NSString *genderString) + { + if ( [@"F" al_isEqualToStringIgnoringCase: genderString] ) + { + return ALGenderFemale; + } + else if ( [@"M" al_isEqualToStringIgnoringCase: genderString] ) + { + return ALGenderMale; + } + else if ( [@"O" al_isEqualToStringIgnoringCase: genderString] ) + { + return ALGenderOther; + } + + return ALGenderUnknown; + } + + ALAdContentRating getAppLovinAdContentRating(int maximumAdContentRating) + { + if ( maximumAdContentRating == 1 ) + { + return ALAdContentRatingAllAudiences; + } + else if ( maximumAdContentRating == 2 ) + { + return ALAdContentRatingEveryoneOverTwelve; + } + else if ( maximumAdContentRating == 3 ) + { + return ALAdContentRatingMatureAudiences; + } + + return ALAdContentRatingNone; + } + + void _MaxSetSdkKey(const char *sdkKey) + { + maybeInitializePlugin(); + + if (!sdkKey) return; + + NSString *sdkKeyStr = [NSString stringWithUTF8String: sdkKey]; + + NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; + [infoDict setValue: sdkKeyStr forKey: @"AppLovinSdkKey"]; + } + + void _MaxInitializeSdk(const char *serializedAdUnitIdentifiers, const char *serializedMetaData, ALUnityBackgroundCallback backgroundCallback) + { + maybeInitializePlugin(); + + _sdk = [_adManager initializeSdkWithSettings: generateSDKSettings(serializedAdUnitIdentifiers, serializedMetaData) + backgroundCallback: backgroundCallback + andCompletionHandler:^(ALSdkConfiguration *configuration) { + _sdkConfiguration = configuration; + _isSdkInitialized = true; + }]; + + if ( _userIdentifierToSet ) + { + _sdk.userIdentifier = _userIdentifierToSet; + _userIdentifierToSet = nil; + } + + if ( _userSegmentNameToSet ) + { + _sdk.userSegment.name = _userSegmentNameToSet; + _userSegmentNameToSet = nil; + } + + if ( _targetingYearOfBirth ) + { + _sdk.targetingData.yearOfBirth = _targetingYearOfBirth.intValue <= 0 ? nil : _targetingYearOfBirth; + _targetingYearOfBirth = nil; + } + + if ( _targetingGender ) + { + _sdk.targetingData.gender = getAppLovinGender(_targetingGender); + _targetingGender = nil; + } + + if ( _targetingMaximumAdContentRating ) + { + _sdk.targetingData.maximumAdContentRating = getAppLovinAdContentRating(_targetingMaximumAdContentRating.intValue); + _targetingMaximumAdContentRating = nil; + } + + if ( _targetingEmail ) + { + _sdk.targetingData.email = _targetingEmail; + _targetingEmail = nil; + } + + if ( _targetingPhoneNumber ) + { + _sdk.targetingData.phoneNumber = _targetingPhoneNumber; + _targetingPhoneNumber = nil; + } + + if ( _targetingKeywords ) + { + _sdk.targetingData.keywords = _targetingKeywords; + _targetingKeywords = nil; + } + + if ( _targetingInterests ) + { + _sdk.targetingData.interests = _targetingInterests; + _targetingInterests = nil; + } + } + + bool _MaxIsInitialized() + { + return _isPluginInitialized && _isSdkInitialized; + } + + const char * _MaxGetAvailableMediatedNetworks() + { + 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(@""); + } + + NSArray *availableMediatedNetworks = [_sdk availableMediatedNetworks]; + + // Create array of serialized network strings + NSMutableArray *> *serializedNetworks = [NSMutableArray arrayWithCapacity: availableMediatedNetworks.count]; + for ( MAMediatedNetworkInfo *mediatedNetwork in availableMediatedNetworks ) + { + NSDictionary *mediatedNetworkDictionary = @{@"name" : mediatedNetwork.name, + @"adapterClassName" : mediatedNetwork.adapterClassName, + @"adapterVersion" : mediatedNetwork.adapterVersion, + @"sdkVersion" : mediatedNetwork.sdkVersion}; + [serializedNetworks addObject: mediatedNetworkDictionary]; + } + + NSData *jsonData = [NSJSONSerialization dataWithJSONObject: serializedNetworks options: 0 error: nil]; + return cStringCopy([[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding]); + } + + void _MaxShowMediationDebugger() + { + if ( !_sdk ) + { + NSLog(@"[%@] Failed to show mediation debugger - please ensure the AppLovin MAX Unity Plugin has been initialized by calling 'MaxSdk.InitializeSdk();'!", TAG); + return; + } + + [_sdk showMediationDebugger]; + } + + void _MaxShowCreativeDebugger() + { + if ( !_sdk ) + { + NSLog(@"[%@] Failed to show creative debugger - please ensure the AppLovin MAX Unity Plugin has been initialized by calling 'MaxSdk.InitializeSdk();'!", TAG); + return; + } + + [_sdk showCreativeDebugger]; + } + + void _MaxShowConsentDialog() + { + NSLog(@"[%@] Failed to show consent dialog - Unavailable on iOS, please use the consent flow: https://dash.applovin.com/documentation/mediation/unity/getting-started/consent-flow", TAG); + } + + int _MaxConsentDialogState() + { + if (!isPluginInitialized()) return ALConsentDialogStateUnknown; + + return (int) _sdkConfiguration.consentDialogState; + } + + void _MaxSetUserId(const char *userId) + { + if ( _sdk ) + { + _sdk.userIdentifier = NSSTRING(userId); + } + else + { + _userIdentifierToSet = NSSTRING(userId); + } + } + + void _MaxSetUserSegmentField(const char *serializedKey, const char *serializedValue) + { + // NSString *key = NSSTRING(serializedKey); // To be ignored until we add more properties + NSString *value = NSSTRING(serializedValue); + + if ( _sdk ) + { + _sdk.userSegment.name = value; + } + else + { + _userSegmentNameToSet = value; + } + } + + void _MaxSetTargetingDataYearOfBirth(const int yearOfBirth) + { + if ( !_sdk ) + { + _targetingYearOfBirth = @(yearOfBirth); + return; + } + + _sdk.targetingData.yearOfBirth = yearOfBirth <= 0 ? nil : @(yearOfBirth); + } + + void _MaxSetTargetingDataGender(char *gender) + { + if ( !_sdk ) + { + _targetingGender = NSSTRING(gender); + return; + } + + NSString *genderString = NSSTRING(gender); + _sdk.targetingData.gender = getAppLovinGender(genderString); + } + + void _MaxSetTargetingDataMaximumAdContentRating(const int maximumAdContentRating) + { + if ( !_sdk ) + { + _targetingMaximumAdContentRating = @(maximumAdContentRating); + return; + } + + _sdk.targetingData.maximumAdContentRating = getAppLovinAdContentRating(maximumAdContentRating); + } + + void _MaxSetTargetingDataEmail(char *email) + { + if ( !_sdk ) + { + _targetingEmail = NSSTRING(email); + return; + } + + _sdk.targetingData.email = NSSTRING(email); + } + + void _MaxSetTargetingDataPhoneNumber(char *phoneNumber) + { + if ( !_sdk ) + { + _targetingPhoneNumber = NSSTRING(phoneNumber); + return; + } + + _sdk.targetingData.phoneNumber = NSSTRING(phoneNumber); + } + + void _MaxSetTargetingDataKeywords(char **keywords, int size) + { + NSArray *keywordsArray = keywords ? toStringArray(keywords, size) : nil; + if ( !_sdk ) + { + _targetingKeywords = keywordsArray; + return; + } + + _sdk.targetingData.keywords = keywordsArray; + } + + void _MaxSetTargetingDataInterests(char **interests, int size) + { + NSArray *interestsArray = interests ? toStringArray(interests, size) : nil; + if ( !_sdk ) + { + _targetingInterests = interestsArray; + return; + } + + _sdk.targetingData.interests = interestsArray; + } + + void _MaxClearAllTargetingData() + { + if ( !_sdk ) + { + _targetingYearOfBirth = nil; + _targetingGender = nil; + _targetingMaximumAdContentRating = nil; + _targetingEmail = nil; + _targetingPhoneNumber = nil; + _targetingKeywords = nil; + _targetingInterests = nil; + return; + } + + [_sdk.targetingData clearAll]; + } + + const char * _MaxGetSdkConfiguration() + { + if ( !_sdk ) + { + logUninitializedAccessError("_MaxGetSdkConfiguration"); + return cStringCopy(@""); + } + + 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, + @"countryCode" : _sdk.configuration.countryCode, + @"appTrackingStatus" : appTrackingStatus, + @"isSuccessfullyInitialized" : @([_sdk isInitialized]), + @"isTestModeEnabled" : @([_sdk.configuration isTestModeEnabled])}]); + } + + void _MaxSetHasUserConsent(bool hasUserConsent) + { + [ALPrivacySettings setHasUserConsent: hasUserConsent]; + } + + bool _MaxHasUserConsent() + { + return [ALPrivacySettings hasUserConsent]; + } + + bool _MaxIsUserConsentSet() + { + return [ALPrivacySettings isUserConsentSet]; + } + + void _MaxSetIsAgeRestrictedUser(bool isAgeRestrictedUser) + { + [ALPrivacySettings setIsAgeRestrictedUser: isAgeRestrictedUser]; + } + + bool _MaxIsAgeRestrictedUser() + { + return [ALPrivacySettings isAgeRestrictedUser]; + } + + bool _MaxIsAgeRestrictedUserSet() + { + return [ALPrivacySettings isAgeRestrictedUserSet]; + } + + void _MaxSetDoNotSell(bool doNotSell) + { + [ALPrivacySettings setDoNotSell: doNotSell]; + } + + bool _MaxIsDoNotSell() + { + return [ALPrivacySettings isDoNotSell]; + } + + bool _MaxIsDoNotSellSet() + { + return [ALPrivacySettings isDoNotSellSet]; + } + + void _MaxCreateBanner(const char *adUnitIdentifier, const char *bannerPosition) + { + if (!isPluginInitialized()) return; + + [_adManager createBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) atPosition: NSSTRING(bannerPosition)]; + } + + void _MaxCreateBannerXY(const char *adUnitIdentifier, const float x, const float y) + { + if (!isPluginInitialized()) return; + + [_adManager createBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) x: x y: y]; + } + + void _MaxLoadBanner(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager loadBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetBannerBackgroundColor(const char *adUnitIdentifier, const char *hexColorCode) + { + if (!isPluginInitialized()) return; + + [_adManager setBannerBackgroundColorForAdUnitIdentifier: NSSTRING(adUnitIdentifier) hexColorCode: NSSTRING(hexColorCode)]; + } + + void _MaxSetBannerPlacement(const char *adUnitIdentifier, const char *placement) + { + [_adManager setBannerPlacement: NSSTRING(placement) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxStartBannerAutoRefresh(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager startBannerAutoRefreshForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxStopBannerAutoRefresh(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager stopBannerAutoRefreshForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetBannerExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + [_adManager setBannerExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetBannerLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + [_adManager setBannerLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id) value]; + } + + void _MaxSetBannerCustomData(const char *adUnitIdentifier, const char *customData) + { + [_adManager setBannerCustomData: NSSTRING(customData) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetBannerWidth(const char *adUnitIdentifier, const float width) + { + [_adManager setBannerWidth: width forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateBannerPosition(const char *adUnitIdentifier, const char *bannerPosition) + { + [_adManager updateBannerPosition: NSSTRING(bannerPosition) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateBannerPositionXY(const char *adUnitIdentifier, const float x, const float y) + { + [_adManager updateBannerPosition: x y: y forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowBanner(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager showBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxDestroyBanner(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager destroyBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxHideBanner(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager hideBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + const char * _MaxGetBannerLayout(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return cStringCopy(@""); + + return cStringCopy([_adManager bannerLayoutForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]); + } + + void _MaxCreateMRec(const char *adUnitIdentifier, const char *mrecPosition) + { + if (!isPluginInitialized()) return; + + [_adManager createMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) atPosition: NSSTRING(mrecPosition)]; + } + + void _MaxCreateMRecXY(const char *adUnitIdentifier, const float x, const float y) + { + if (!isPluginInitialized()) return; + + [_adManager createMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) x: x y: y]; + } + + void _MaxLoadMRec(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager loadMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetMRecPlacement(const char *adUnitIdentifier, const char *placement) + { + [_adManager setMRecPlacement: NSSTRING(placement) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxStartMRecAutoRefresh(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager startMRecAutoRefreshForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxStopMRecAutoRefresh(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager stopMRecAutoRefreshForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateMRecPosition(const char *adUnitIdentifier, const char *mrecPosition) + { + [_adManager updateMRecPosition: NSSTRING(mrecPosition) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateMRecPositionXY(const char *adUnitIdentifier, const float x, const float y) + { + [_adManager updateMRecPosition: x y: y forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowMRec(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager showMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxDestroyMRec(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager destroyMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxHideMRec(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager hideMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetMRecExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + [_adManager setMRecExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetMRecLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + [_adManager setMRecLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + void _MaxSetMRecCustomData(const char *adUnitIdentifier, const char *customData) + { + [_adManager setMRecCustomData: NSSTRING(customData) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + const char * _MaxGetMRecLayout(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return cStringCopy(@""); + + return cStringCopy([_adManager mrecLayoutForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]); + } + + void _MaxCreateCrossPromoAd(const char *adUnitIdentifier, const float x, const float y, const float width, const float height, const float rotation) + { + if (!isPluginInitialized()) return; + + [_adManager createCrossPromoAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) x: x y: y width: width height: height rotation: rotation]; + } + + void _MaxSetCrossPromoAdPlacement(const char *adUnitIdentifier, const char *placement) + { + [_adManager setCrossPromoAdPlacement: NSSTRING(placement) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateCrossPromoAdPosition(const char *adUnitIdentifier, const float x, const float y, const float width, const float height, const float rotation) + { + [_adManager updateCrossPromoAdPositionForAdUnitIdentifier: NSSTRING(adUnitIdentifier) x: x y: y width: width height: height rotation: rotation]; + } + + void _MaxShowCrossPromoAd(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager showCrossPromoAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxDestroyCrossPromoAd(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager destroyCrossPromoAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxHideCrossPromoAd(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager hideCrossPromoAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + const char * _MaxGetCrossPromoAdLayout(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return cStringCopy(@""); + + return cStringCopy([_adManager crossPromoAdLayoutForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]); + } + + void _MaxLoadInterstitial(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager loadInterstitialWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetInterstitialExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + [_adManager setInterstitialExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetInterstitialLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + [_adManager setInterstitialLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + bool _MaxIsInterstitialReady(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return false; + + return [_adManager isInterstitialReadyWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowInterstitial(const char *adUnitIdentifier, const char *placement, const char *customData) + { + if (!isPluginInitialized()) return; + + [_adManager showInterstitialWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) placement: NSSTRING(placement) customData: NSSTRING(customData)]; + } + + void _MaxLoadAppOpenAd(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager loadAppOpenAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetAppOpenAdExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + [_adManager setAppOpenAdExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetAppOpenAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + [_adManager setAppOpenAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + bool _MaxIsAppOpenAdReady(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return false; + + return [_adManager isAppOpenAdReadyWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowAppOpenAd(const char *adUnitIdentifier, const char *placement, const char *customData) + { + if (!isPluginInitialized()) return; + + [_adManager showAppOpenAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) placement: NSSTRING(placement) customData: NSSTRING(customData)]; + } + + void _MaxLoadRewardedAd(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager loadRewardedAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetRewardedAdExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + [_adManager setRewardedAdExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetRewardedAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + [_adManager setRewardedAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + bool _MaxIsRewardedAdReady(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return false; + + return [_adManager isRewardedAdReadyWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowRewardedAd(const char *adUnitIdentifier, const char *placement, const char *customData) + { + if (!isPluginInitialized()) return; + + [_adManager showRewardedAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) placement: NSSTRING(placement) customData: NSSTRING(customData)]; + } + + void _MaxLoadRewardedInterstitialAd(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return; + + [_adManager loadRewardedInterstitialAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetRewardedInterstitialAdExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + [_adManager setRewardedInterstitialAdExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetRewardedInterstitialAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + [_adManager setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + bool _MaxIsRewardedInterstitialAdReady(const char *adUnitIdentifier) + { + if (!isPluginInitialized()) return false; + + return [_adManager isRewardedInterstitialAdReadyWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowRewardedInterstitialAd(const char *adUnitIdentifier, const char *placement, const char *customData) + { + if (!isPluginInitialized()) return; + + [_adManager showRewardedInterstitialAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) placement: NSSTRING(placement) customData: NSSTRING(customData)]; + } + + void _MaxTrackEvent(const char *event, const char *parameters) + { + if (!isPluginInitialized()) return; + + [_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() + { + return [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad; + } + + bool _MaxIsPhysicalDevice() + { + return !ALUtils.simulator; + } + + static const char * cStringCopy(NSString *string) + { + const char *value = string.UTF8String; + return value ? strdup(value) : NULL; + } + + void _MaxSetMuted(bool muted) + { + if ( !_sdk ) return; + + _sdk.settings.muted = muted; + } + + bool _MaxIsMuted() + { + if ( !_sdk ) return false; + + return _sdk.settings.muted; + } + + float _MaxScreenDensity() + { + return [UIScreen.mainScreen nativeScale]; + } + + const char * _MaxGetAdInfo(const char *adUnitIdentifier) + { + return cStringCopy([_adManager adInfoForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]); + } + + const char * _MaxGetAdValue(const char *adUnitIdentifier, const char *key) + { + return cStringCopy([_adManager adValueForAdUnitIdentifier: NSSTRING(adUnitIdentifier) withKey: NSSTRING(key)]); + } + + void _MaxSetVerboseLogging(bool enabled) + { + if ( _sdk ) + { + _sdk.settings.verboseLoggingEnabled = enabled; + _verboseLoggingToSet = nil; + } + else + { + _verboseLoggingToSet = @(enabled); + } + } + + bool _MaxIsVerboseLoggingEnabled() + { + if ( _sdk ) + { + return [_sdk.settings isVerboseLoggingEnabled]; + } + else if ( _verboseLoggingToSet ) + { + return _verboseLoggingToSet; + } + + return false; + } + + void _MaxSetTestDeviceAdvertisingIdentifiers(char **advertisingIdentifiers, int size) + { + NSArray *advertisingIdentifiersArray = toStringArray(advertisingIdentifiers, size); + _testDeviceIdentifiersToSet = advertisingIdentifiersArray; + } + + void _MaxSetCreativeDebuggerEnabled(bool enabled) + { + if ( _sdk ) + { + _sdk.settings.creativeDebuggerEnabled = enabled; + _creativeDebuggerEnabledToSet = nil; + } + else + { + _creativeDebuggerEnabledToSet = @(enabled); + } + } + + void _MaxSetExceptionHandlerEnabled(bool enabled) + { + if ( _sdk ) + { + _sdk.settings.exceptionHandlerEnabled = enabled; + _exceptionHandlerEnabledToSet = nil; + } + else + { + _exceptionHandlerEnabledToSet = @(enabled); + } + } + + void _MaxSetLocationCollectionEnabled(bool enabled) + { + if ( _sdk ) + { + _sdk.settings.locationCollectionEnabled = enabled; + _locationCollectionEnabledToSet = nil; + } + else + { + _locationCollectionEnabledToSet = @(enabled); + } + } + + void _MaxSetExtraParameter(const char *key, const char *value) + { + NSString *stringKey = NSSTRING(key); + if ( ![stringKey al_isValidString] ) + { + NSLog(@"[%@] Failed to set extra parameter for nil or empty key: %@", TAG, stringKey); + return; + } + + if ( _sdk ) + { + ALSdkSettings *settings = _sdk.settings; + [settings setExtraParameterForKey: stringKey value: NSSTRING(value)]; + setPendingExtraParametersIfNeeded( settings ); + } + else + { + @synchronized ( _extraParametersToSetLock ) + { + _extraParametersToSet[stringKey] = NSSTRING(value); + } + } + } + + 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() + { + if (!isPluginInitialized()) + { + logUninitializedAccessError("_MaxStartConsentFlow"); + return; + } + + [_adManager startConsentFlow]; + } + + float _MaxGetAdaptiveBannerHeight(const float width) + { + return [MAUnityAdManager adaptiveBannerHeightForWidth: width]; + } + + void logUninitializedAccessError(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 new file mode 100644 index 0000000..5d8ad34 --- /dev/null +++ b/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta @@ -0,0 +1,109 @@ +fileFormatVersion: 2 +guid: 193b1bac1aa9a4e1292257dc02aa3ec5 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + Exclude tvOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/MaxSdk.asmdef b/MaxSdk/MaxSdk.asmdef new file mode 100644 index 0000000..3233bbd --- /dev/null +++ b/MaxSdk/MaxSdk.asmdef @@ -0,0 +1,14 @@ +{ + "name": "MaxSdk", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/MaxSdk/MaxSdk.asmdef.meta b/MaxSdk/MaxSdk.asmdef.meta new file mode 100644 index 0000000..07a056c --- /dev/null +++ b/MaxSdk/MaxSdk.asmdef.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8dec731b806064c17a9bb592f19aaed7 +labels: +- al_max +- al_max_export_path-MaxSdk/MaxSdk.asmdef +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation.meta b/MaxSdk/Mediation.meta new file mode 100644 index 0000000..1273617 --- /dev/null +++ b/MaxSdk/Mediation.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26bc0f0d9ea814ca5a40e91ea65c96c6 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/BidMachine.meta b/MaxSdk/Mediation/BidMachine.meta new file mode 100644 index 0000000..6022de6 --- /dev/null +++ b/MaxSdk/Mediation/BidMachine.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69da8ba8ffbea46879ec44f73e810a44 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/BidMachine +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/BidMachine/Editor.meta b/MaxSdk/Mediation/BidMachine/Editor.meta new file mode 100644 index 0000000..abeb810 --- /dev/null +++ b/MaxSdk/Mediation/BidMachine/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fff2bf51ca90b4a59a0f365cba5fd7d6 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/BidMachine/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml b/MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml new file mode 100644 index 0000000..3374645 --- /dev/null +++ b/MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + + https://artifactory.bidmachine.io/bidmachine + + + + + + + diff --git a/MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..a8a4500 --- /dev/null +++ b/MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 66c11df5800ec422d865b8235e00c2ec +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/BidMachine/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/ByteDance.meta b/MaxSdk/Mediation/ByteDance.meta new file mode 100644 index 0000000..de82633 --- /dev/null +++ b/MaxSdk/Mediation/ByteDance.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6eae354297b34f30adba6ab6a8959ec +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/ByteDance +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/ByteDance/Editor.meta b/MaxSdk/Mediation/ByteDance/Editor.meta new file mode 100644 index 0000000..e54a766 --- /dev/null +++ b/MaxSdk/Mediation/ByteDance/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef8467ffb0e4447b79a8804884a7520a +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/ByteDance/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml b/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml new file mode 100644 index 0000000..1fede9e --- /dev/null +++ b/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + + https://artifact.bytedance.com/repository/pangle + + + + + + + diff --git a/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..5205233 --- /dev/null +++ b/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0828555cb1ce94702a4af6f3dce3d735 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Chartboost.meta b/MaxSdk/Mediation/Chartboost.meta new file mode 100644 index 0000000..3830c59 --- /dev/null +++ b/MaxSdk/Mediation/Chartboost.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3b88946a22f14f0590892b9c77b9417 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Chartboost +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Chartboost/Editor.meta b/MaxSdk/Mediation/Chartboost/Editor.meta new file mode 100644 index 0000000..38bff8d --- /dev/null +++ b/MaxSdk/Mediation/Chartboost/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a90f13141c35746f5a2996c8ad068fe9 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Chartboost/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml b/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml new file mode 100644 index 0000000..eb84026 --- /dev/null +++ b/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml @@ -0,0 +1,14 @@ + + + + + + https://cboost.jfrog.io/artifactory/chartboost-ads/ + + + + + + + + diff --git a/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..02628eb --- /dev/null +++ b/MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 93b0a4618bd884871af0981a7867bb2f +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Chartboost/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Facebook.meta b/MaxSdk/Mediation/Facebook.meta new file mode 100644 index 0000000..2a9614d --- /dev/null +++ b/MaxSdk/Mediation/Facebook.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2dda6f77a7cd94cd2beb620614723a89 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Facebook +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Facebook/Editor.meta b/MaxSdk/Mediation/Facebook/Editor.meta new file mode 100644 index 0000000..4beff5e --- /dev/null +++ b/MaxSdk/Mediation/Facebook/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 28880992a399a48b7abe95b66649d711 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Facebook/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml b/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml new file mode 100644 index 0000000..6bf87ae --- /dev/null +++ b/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..69b5d2c --- /dev/null +++ b/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: aea9bdf974328420db5ae118ef0d2b87 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Facebook/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Fyber.meta b/MaxSdk/Mediation/Fyber.meta new file mode 100644 index 0000000..e968b9c --- /dev/null +++ b/MaxSdk/Mediation/Fyber.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a09f92129c68c4af99db09996deccfb1 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Fyber +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Fyber/Editor.meta b/MaxSdk/Mediation/Fyber/Editor.meta new file mode 100644 index 0000000..315e8c8 --- /dev/null +++ b/MaxSdk/Mediation/Fyber/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e076e4ef7e2874ba69b108cc7a346c2a +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Fyber/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml b/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml new file mode 100644 index 0000000..4634674 --- /dev/null +++ b/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..fd0bbbf --- /dev/null +++ b/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 5e123cdc08e804dffb2c40c4fbc83caf +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Fyber/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Google.meta b/MaxSdk/Mediation/Google.meta new file mode 100644 index 0000000..4a28091 --- /dev/null +++ b/MaxSdk/Mediation/Google.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 203368966db594fea8801e6e57c12155 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Google +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Google/Editor.meta b/MaxSdk/Mediation/Google/Editor.meta new file mode 100644 index 0000000..ea8dd55 --- /dev/null +++ b/MaxSdk/Mediation/Google/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8015bd045cea462c8f39c8a05867d08 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Google/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Google/Editor/Dependencies.xml b/MaxSdk/Mediation/Google/Editor/Dependencies.xml new file mode 100644 index 0000000..e46e764 --- /dev/null +++ b/MaxSdk/Mediation/Google/Editor/Dependencies.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/MaxSdk/Mediation/Google/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Google/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..36bef72 --- /dev/null +++ b/MaxSdk/Mediation/Google/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 053b810d3594744e38b6fd0fa378fb57 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Google/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/GoogleAdManager.meta b/MaxSdk/Mediation/GoogleAdManager.meta new file mode 100644 index 0000000..878b8e0 --- /dev/null +++ b/MaxSdk/Mediation/GoogleAdManager.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70dad35ac3b354fde8433584e42101b9 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/GoogleAdManager +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/GoogleAdManager/Editor.meta b/MaxSdk/Mediation/GoogleAdManager/Editor.meta new file mode 100644 index 0000000..7b0912c --- /dev/null +++ b/MaxSdk/Mediation/GoogleAdManager/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e1635bfb5b164c389d38eb1e5e6e909 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/GoogleAdManager/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml b/MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml new file mode 100644 index 0000000..189df74 --- /dev/null +++ b/MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..71b0087 --- /dev/null +++ b/MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: aebbf5e9af66e431fa6078021b2f762f +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/HyprMX.meta b/MaxSdk/Mediation/HyprMX.meta new file mode 100644 index 0000000..f95858b --- /dev/null +++ b/MaxSdk/Mediation/HyprMX.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf0afb8e951e8480ca25f3cfcb37d90f +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/HyprMX +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/HyprMX/Editor.meta b/MaxSdk/Mediation/HyprMX/Editor.meta new file mode 100644 index 0000000..0a147cb --- /dev/null +++ b/MaxSdk/Mediation/HyprMX/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9b86cecea77d4c0aa832581652a1a13 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/HyprMX/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml b/MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml new file mode 100644 index 0000000..1aedbe4 --- /dev/null +++ b/MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..d8dd898 --- /dev/null +++ b/MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 1d2e714409297495f810bf46ddacdeb1 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/HyprMX/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/InMobi.meta b/MaxSdk/Mediation/InMobi.meta new file mode 100644 index 0000000..973d673 --- /dev/null +++ b/MaxSdk/Mediation/InMobi.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1c324c1af651642beb5f9dbffdddbc48 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/InMobi +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/InMobi/Editor.meta b/MaxSdk/Mediation/InMobi/Editor.meta new file mode 100644 index 0000000..a998cfd --- /dev/null +++ b/MaxSdk/Mediation/InMobi/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a141703acd55a48c2a3e6e6599f90c64 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/InMobi/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml b/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml new file mode 100644 index 0000000..2a89899 --- /dev/null +++ b/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..1b62e82 --- /dev/null +++ b/MaxSdk/Mediation/InMobi/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: bc66a0ef4503843ee9b1bf1b1e867367 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/InMobi/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/IronSource.meta b/MaxSdk/Mediation/IronSource.meta new file mode 100644 index 0000000..8b50611 --- /dev/null +++ b/MaxSdk/Mediation/IronSource.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ffdad724a353a435f8e37fee99aeea5d +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/IronSource +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/IronSource/Editor.meta b/MaxSdk/Mediation/IronSource/Editor.meta new file mode 100644 index 0000000..327f5d6 --- /dev/null +++ b/MaxSdk/Mediation/IronSource/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 531d860cac61f47d19e32f526470ae43 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/IronSource/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml b/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml new file mode 100644 index 0000000..80ca59a --- /dev/null +++ b/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + + https://android-sdk.is.com/ + + + + + + + diff --git a/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..f77e6f0 --- /dev/null +++ b/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 19262406303f04f05b14b31b3c734d35 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/IronSource/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/MediationAdapters.txt b/MaxSdk/Mediation/MediationAdapters.txt new file mode 100644 index 0000000..40f94d0 --- /dev/null +++ b/MaxSdk/Mediation/MediationAdapters.txt @@ -0,0 +1,2 @@ +A placeholder file to make sure that the Mediation folder asset is exported with the base plugin. +This ensures that the adapters are imported into this directory even when the plugin has been moved to a different folder. diff --git a/MaxSdk/Mediation/MediationAdapters.txt.meta b/MaxSdk/Mediation/MediationAdapters.txt.meta new file mode 100644 index 0000000..41fb994 --- /dev/null +++ b/MaxSdk/Mediation/MediationAdapters.txt.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: 9a8f83e97729443c86120be3bb24190d +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/MediationAdapters.txt +timeCreated: 1609308536 diff --git a/MaxSdk/Mediation/Mintegral.meta b/MaxSdk/Mediation/Mintegral.meta new file mode 100644 index 0000000..2a5200d --- /dev/null +++ b/MaxSdk/Mediation/Mintegral.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 899cf5ba8faee45ce9b0adbf6582f05c +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Mintegral +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Mintegral/Editor.meta b/MaxSdk/Mediation/Mintegral/Editor.meta new file mode 100644 index 0000000..d189ce0 --- /dev/null +++ b/MaxSdk/Mediation/Mintegral/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: db1de4066dc4e4290b3879b34fa87de2 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Mintegral/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml b/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml new file mode 100644 index 0000000..e4a4162 --- /dev/null +++ b/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml @@ -0,0 +1,14 @@ + + + + + + https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea + + + + + + + + diff --git a/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..415c4ab --- /dev/null +++ b/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 221b2a20a58a04f2cb4afb0779587206 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/MobileFuse.meta b/MaxSdk/Mediation/MobileFuse.meta new file mode 100644 index 0000000..98f7455 --- /dev/null +++ b/MaxSdk/Mediation/MobileFuse.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e99dd70183ac444e94d3c68ab6ea60e +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/MobileFuse +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/MobileFuse/Editor.meta b/MaxSdk/Mediation/MobileFuse/Editor.meta new file mode 100644 index 0000000..400af93 --- /dev/null +++ b/MaxSdk/Mediation/MobileFuse/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 25eec4f6b8a3242d1932b3f0fa9a92c5 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/MobileFuse/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml b/MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml new file mode 100644 index 0000000..e866bcf --- /dev/null +++ b/MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..d75a676 --- /dev/null +++ b/MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0f67d70f213fa445692afd2124c81471 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/MobileFuse/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/OguryPresage.meta b/MaxSdk/Mediation/OguryPresage.meta new file mode 100644 index 0000000..04542a9 --- /dev/null +++ b/MaxSdk/Mediation/OguryPresage.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7a900f2caf094a7495765a10f86543e +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/OguryPresage +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/OguryPresage/Editor.meta b/MaxSdk/Mediation/OguryPresage/Editor.meta new file mode 100644 index 0000000..af2d23b --- /dev/null +++ b/MaxSdk/Mediation/OguryPresage/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: deb1bc473b7934f93b82938ea36d0878 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/OguryPresage/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml b/MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml new file mode 100644 index 0000000..2d5d6e4 --- /dev/null +++ b/MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + + https://maven.ogury.co + + + + + + + diff --git a/MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..1b56b07 --- /dev/null +++ b/MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 4733055cb7d01490e9c36862b7d10163 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/OguryPresage/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Smaato.meta b/MaxSdk/Mediation/Smaato.meta new file mode 100644 index 0000000..d92f812 --- /dev/null +++ b/MaxSdk/Mediation/Smaato.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd68da9eb37a54d2b81ac5a53d44e167 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Smaato +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Smaato/Editor.meta b/MaxSdk/Mediation/Smaato/Editor.meta new file mode 100644 index 0000000..48d1804 --- /dev/null +++ b/MaxSdk/Mediation/Smaato/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d6ab91d259c064997b6b26c1739ef87d +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Smaato/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Smaato/Editor/Dependencies.xml b/MaxSdk/Mediation/Smaato/Editor/Dependencies.xml new file mode 100644 index 0000000..81ac4c0 --- /dev/null +++ b/MaxSdk/Mediation/Smaato/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + + https://s3.amazonaws.com/smaato-sdk-releases/ + + + + + + + diff --git a/MaxSdk/Mediation/Smaato/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Smaato/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..c76c78b --- /dev/null +++ b/MaxSdk/Mediation/Smaato/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: f6c345cc57a514902ba5fb68436f852f +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Smaato/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/UnityAds.meta b/MaxSdk/Mediation/UnityAds.meta new file mode 100644 index 0000000..78b3e47 --- /dev/null +++ b/MaxSdk/Mediation/UnityAds.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0a62ae2d1fc164dbf950cc85a47b18b3 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/UnityAds +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/UnityAds/Editor.meta b/MaxSdk/Mediation/UnityAds/Editor.meta new file mode 100644 index 0000000..b66e846 --- /dev/null +++ b/MaxSdk/Mediation/UnityAds/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30751f2dc322a40e588edfb7c978c9c0 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/UnityAds/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml b/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml new file mode 100644 index 0000000..1e7791d --- /dev/null +++ b/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..937df6e --- /dev/null +++ b/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 9950f1cb0da1e43efbeca604db142076 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Verve.meta b/MaxSdk/Mediation/Verve.meta new file mode 100644 index 0000000..0cc9190 --- /dev/null +++ b/MaxSdk/Mediation/Verve.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0dc83ab4933b14c1ebdebbe4a1f5a32e +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Verve +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Verve/Editor.meta b/MaxSdk/Mediation/Verve/Editor.meta new file mode 100644 index 0000000..9ddb48f --- /dev/null +++ b/MaxSdk/Mediation/Verve/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 942a73b8f38284e55849bd9986aefee8 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Verve/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Verve/Editor/Dependencies.xml b/MaxSdk/Mediation/Verve/Editor/Dependencies.xml new file mode 100644 index 0000000..3bf7c22 --- /dev/null +++ b/MaxSdk/Mediation/Verve/Editor/Dependencies.xml @@ -0,0 +1,12 @@ + + + + + + https://verve.jfrog.io/artifactory/verve-gradle-release + + + + + + diff --git a/MaxSdk/Mediation/Verve/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Verve/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..7edac19 --- /dev/null +++ b/MaxSdk/Mediation/Verve/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: bce11a786f6b54963a8085520a643ce8 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Verve/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Vungle.meta b/MaxSdk/Mediation/Vungle.meta new file mode 100644 index 0000000..97b6bac --- /dev/null +++ b/MaxSdk/Mediation/Vungle.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fbf60d55c441946c9804dffe8a676f79 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Vungle +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Vungle/Editor.meta b/MaxSdk/Mediation/Vungle/Editor.meta new file mode 100644 index 0000000..1ea75cc --- /dev/null +++ b/MaxSdk/Mediation/Vungle/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 77b6ea05736a9458f8ef8762ee9b64bb +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Vungle/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml b/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml new file mode 100644 index 0000000..6cf8c87 --- /dev/null +++ b/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..7038186 --- /dev/null +++ b/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0d8ad3a6ddc4f44fab2efe607fe14f26 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Vungle/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Yandex.meta b/MaxSdk/Mediation/Yandex.meta new file mode 100644 index 0000000..c72df25 --- /dev/null +++ b/MaxSdk/Mediation/Yandex.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ab645d4ad41a4b2a812a4d23108ec04 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Yandex +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Yandex/Editor.meta b/MaxSdk/Mediation/Yandex/Editor.meta new file mode 100644 index 0000000..96a880c --- /dev/null +++ b/MaxSdk/Mediation/Yandex/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 277e2383262e844708fc74a6104f4985 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Yandex/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Mediation/Yandex/Editor/Dependencies.xml b/MaxSdk/Mediation/Yandex/Editor/Dependencies.xml new file mode 100644 index 0000000..ac5cd5a --- /dev/null +++ b/MaxSdk/Mediation/Yandex/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/MaxSdk/Mediation/Yandex/Editor/Dependencies.xml.meta b/MaxSdk/Mediation/Yandex/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..495dede --- /dev/null +++ b/MaxSdk/Mediation/Yandex/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a77aaf886990c4e6ba469a4f083b9284 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Yandex/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Prefabs.meta b/MaxSdk/Prefabs.meta new file mode 100644 index 0000000..83cc3ce --- /dev/null +++ b/MaxSdk/Prefabs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f02c68646b3246d1822c96d17458b4d +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Prefabs/BannerBottom.prefab b/MaxSdk/Prefabs/BannerBottom.prefab new file mode 100644 index 0000000..bba7ac6 --- /dev/null +++ b/MaxSdk/Prefabs/BannerBottom.prefab @@ -0,0 +1,402 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3149432657757030138 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5965516886513985157} + - component: {fileID: 3167928293195730454} + - component: {fileID: 6048907697713132302} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5965516886513985157 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4118862295226300947} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 84} + m_SizeDelta: {x: 0, y: 168} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3167928293195730454 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_CullTransparentMesh: 0 +--- !u!114 &6048907697713132302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &3829518492429360636 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4118862295226300947} + - component: {fileID: 5582763645243389146} + - component: {fileID: 1436650035481827287} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4118862295226300947 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5084927109723455527} + - {fileID: 8189983859356672495} + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 1} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: -50} + m_SizeDelta: {x: 640, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5582763645243389146 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_CullTransparentMesh: 0 +--- !u!114 &1436650035481827287 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &4772536868390647122 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8189983859356672495} + - component: {fileID: 7216515036998124610} + - component: {fileID: 3801875349924125266} + m_Layer: 5 + m_Name: InfoText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8189983859356672495 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4772536868390647122} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4118862295226300947} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 3} + m_SizeDelta: {x: 0, y: -6} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7216515036998124610 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4772536868390647122} + m_CullTransparentMesh: 0 +--- !u!114 &3801875349924125266 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4772536868390647122} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.29411766, g: 0.29411766, b: 0.29411766, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 7 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Actual banner size may vary on mobile devices +--- !u!1 &7742712311334970126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3413013686078446151} + - component: {fileID: 2511819091764556577} + - component: {fileID: 2638196187645015298} + - component: {fileID: 633018877563332563} + m_Layer: 5 + m_Name: BannerBottom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3413013686078446151 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 5965516886513985157} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &2511819091764556577 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 500 + m_TargetDisplay: 0 +--- !u!114 &2638196187645015298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &633018877563332563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &8436952342056443077 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5084927109723455527} + - component: {fileID: 7267203896389005665} + - component: {fileID: 5500603550844857255} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5084927109723455527 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4118862295226300947} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -4} + m_SizeDelta: {x: 0, y: -8} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7267203896389005665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_CullTransparentMesh: 0 +--- !u!114 &5500603550844857255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 26 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 71 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: MAX Banner Ad diff --git a/MaxSdk/Prefabs/BannerBottom.prefab.meta b/MaxSdk/Prefabs/BannerBottom.prefab.meta new file mode 100644 index 0000000..fc73161 --- /dev/null +++ b/MaxSdk/Prefabs/BannerBottom.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: c40cd08161edf43b49140ec091e9f067 +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs/BannerBottom.prefab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Prefabs/BannerTop.prefab b/MaxSdk/Prefabs/BannerTop.prefab new file mode 100644 index 0000000..25d5f49 --- /dev/null +++ b/MaxSdk/Prefabs/BannerTop.prefab @@ -0,0 +1,402 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3149432657757030138 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5965516886513985157} + - component: {fileID: 3167928293195730454} + - component: {fileID: 6048907697713132302} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5965516886513985157 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4118862295226300947} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -50} + m_SizeDelta: {x: 0, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3167928293195730454 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_CullTransparentMesh: 0 +--- !u!114 &6048907697713132302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &3829518492429360636 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4118862295226300947} + - component: {fileID: 5582763645243389146} + - component: {fileID: 1436650035481827287} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4118862295226300947 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5084927109723455527} + - {fileID: 7429934296583149777} + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 640, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5582763645243389146 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_CullTransparentMesh: 0 +--- !u!114 &1436650035481827287 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &5625059666589051168 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7429934296583149777} + - component: {fileID: 6576623406533516677} + - component: {fileID: 5405475098690228567} + m_Layer: 5 + m_Name: InfoText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7429934296583149777 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5625059666589051168} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4118862295226300947} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 3} + m_SizeDelta: {x: 0, y: -6} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6576623406533516677 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5625059666589051168} + m_CullTransparentMesh: 0 +--- !u!114 &5405475098690228567 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5625059666589051168} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.29411766, g: 0.29411766, b: 0.29411766, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 7 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Actual banner size may vary on mobile devices +--- !u!1 &7742712311334970126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3413013686078446151} + - component: {fileID: 2511819091764556577} + - component: {fileID: 2638196187645015298} + - component: {fileID: 633018877563332563} + m_Layer: 5 + m_Name: BannerTop + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3413013686078446151 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 5965516886513985157} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &2511819091764556577 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 500 + m_TargetDisplay: 0 +--- !u!114 &2638196187645015298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &633018877563332563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &8436952342056443077 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5084927109723455527} + - component: {fileID: 7267203896389005665} + - component: {fileID: 5500603550844857255} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5084927109723455527 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4118862295226300947} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -4} + m_SizeDelta: {x: 0, y: -8} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7267203896389005665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_CullTransparentMesh: 0 +--- !u!114 &5500603550844857255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 26 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 71 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: MAX Banner Ad diff --git a/MaxSdk/Prefabs/BannerTop.prefab.meta b/MaxSdk/Prefabs/BannerTop.prefab.meta new file mode 100644 index 0000000..c1e2ca1 --- /dev/null +++ b/MaxSdk/Prefabs/BannerTop.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 9b4937edd18714f3ebeb656de6e4d54b +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs/BannerTop.prefab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Prefabs/Interstitial.prefab b/MaxSdk/Prefabs/Interstitial.prefab new file mode 100644 index 0000000..10c7c7b --- /dev/null +++ b/MaxSdk/Prefabs/Interstitial.prefab @@ -0,0 +1,523 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3149432657757030138 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5965516886513985157} + - component: {fileID: 3167928293195730454} + - component: {fileID: 6048907697713132302} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5965516886513985157 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5084927109723455527} + - {fileID: 8681486192829137138} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3167928293195730454 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_CullTransparentMesh: 0 +--- !u!114 &6048907697713132302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.88235295, g: 0.88235295, b: 0.88235295, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &5668641863723001099 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8681486192829137138} + - component: {fileID: 8217482188885705039} + - component: {fileID: 3177344817093501532} + - component: {fileID: 4415703054918645549} + m_Layer: 5 + m_Name: MaxInterstitialCloseButton + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8681486192829137138 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 763654547095120985} + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -200, y: -100} + m_SizeDelta: {x: 250, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8217482188885705039 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_CullTransparentMesh: 0 +--- !u!114 &3177344817093501532 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!114 &4415703054918645549 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 3177344817093501532} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &6155160063690407013 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1672649117655046507} + - component: {fileID: 2484422763836779945} + - component: {fileID: 1332063313327512547} + - component: {fileID: 9160434328933334999} + m_Layer: 5 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1672649117655046507 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6155160063690407013} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2484422763836779945 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6155160063690407013} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!114 &1332063313327512547 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6155160063690407013} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &9160434328933334999 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6155160063690407013} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e0acf281ba86b4929a6942ecd998395b, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &6462551400748024402 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 763654547095120985} + - component: {fileID: 6719360953530842803} + - component: {fileID: 4616290306121202327} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &763654547095120985 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 8681486192829137138} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6719360953530842803 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_CullTransparentMesh: 0 +--- !u!114 &4616290306121202327 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 40 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 4 + m_MaxSize: 47 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Close +--- !u!1 &7742712311334970126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3413013686078446151} + - component: {fileID: 2511819091764556577} + - component: {fileID: 2638196187645015298} + - component: {fileID: 633018877563332563} + m_Layer: 5 + m_Name: Interstitial + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3413013686078446151 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 5965516886513985157} + - {fileID: 1672649117655046507} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &2511819091764556577 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 999 + m_TargetDisplay: 0 +--- !u!114 &2638196187645015298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &633018877563332563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &8436952342056443077 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5084927109723455527} + - component: {fileID: 7267203896389005665} + - component: {fileID: 5500603550844857255} + m_Layer: 5 + m_Name: MaxInterstitialTitle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5084927109723455527 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 300} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7267203896389005665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_CullTransparentMesh: 0 +--- !u!114 &5500603550844857255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 50 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 71 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: MAX Interstitial Ad diff --git a/MaxSdk/Prefabs/Interstitial.prefab.meta b/MaxSdk/Prefabs/Interstitial.prefab.meta new file mode 100644 index 0000000..d8b7b5b --- /dev/null +++ b/MaxSdk/Prefabs/Interstitial.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 06407a673b7194053b3fb593a9933c95 +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs/Interstitial.prefab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Prefabs/Rewarded.prefab b/MaxSdk/Prefabs/Rewarded.prefab new file mode 100644 index 0000000..dd3457e --- /dev/null +++ b/MaxSdk/Prefabs/Rewarded.prefab @@ -0,0 +1,795 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &288832541099509301 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6736833388881778366} + - component: {fileID: 738723989743429661} + - component: {fileID: 3366016410383180441} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6736833388881778366 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 288832541099509301} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2219183527695013266} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &738723989743429661 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 288832541099509301} + m_CullTransparentMesh: 0 +--- !u!114 &3366016410383180441 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 288832541099509301} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 35 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 3 + m_MaxSize: 48 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'Grant Reward + + (5 coins)' +--- !u!1 &2620135977249264498 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3035265698078104281} + - component: {fileID: 7277178523579209441} + - component: {fileID: 8085319417655039649} + m_Layer: 5 + m_Name: MaxRewardStatus + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3035265698078104281 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2620135977249264498} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: -250} + m_SizeDelta: {x: 0, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7277178523579209441 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2620135977249264498} + m_CullTransparentMesh: 0 +--- !u!114 &8085319417655039649 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2620135977249264498} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 40 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 69 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Reward not yet granted. +--- !u!1 &3096027301306273604 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2219183527695013266} + - component: {fileID: 3687429596110321440} + - component: {fileID: 3757577222601629632} + - component: {fileID: 87227930114769318} + m_Layer: 5 + m_Name: MaxRewardButton + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2219183527695013266 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096027301306273604} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 6736833388881778366} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -150} + m_SizeDelta: {x: 300, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3687429596110321440 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096027301306273604} + m_CullTransparentMesh: 0 +--- !u!114 &3757577222601629632 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096027301306273604} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!114 &87227930114769318 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096027301306273604} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 3757577222601629632} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &3149432657757030138 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5965516886513985157} + - component: {fileID: 3167928293195730454} + - component: {fileID: 6048907697713132302} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5965516886513985157 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5084927109723455527} + - {fileID: 8681486192829137138} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3167928293195730454 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_CullTransparentMesh: 0 +--- !u!114 &6048907697713132302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.88235295, g: 0.88235295, b: 0.88235295, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &4010021198786516228 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3074011789293951898} + - component: {fileID: 301935380126337495} + - component: {fileID: 535359239537776472} + - component: {fileID: 1463999766055390634} + m_Layer: 5 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3074011789293951898 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4010021198786516228} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &301935380126337495 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4010021198786516228} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!114 &535359239537776472 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4010021198786516228} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1463999766055390634 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4010021198786516228} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e0acf281ba86b4929a6942ecd998395b, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &5668641863723001099 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8681486192829137138} + - component: {fileID: 8217482188885705039} + - component: {fileID: 3177344817093501532} + - component: {fileID: 4415703054918645549} + m_Layer: 5 + m_Name: MaxRewardedCloseButton + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8681486192829137138 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 763654547095120985} + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -200, y: -100} + m_SizeDelta: {x: 250, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8217482188885705039 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_CullTransparentMesh: 0 +--- !u!114 &3177344817093501532 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!114 &4415703054918645549 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 3177344817093501532} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &6462551400748024402 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 763654547095120985} + - component: {fileID: 6719360953530842803} + - component: {fileID: 4616290306121202327} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &763654547095120985 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 8681486192829137138} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6719360953530842803 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_CullTransparentMesh: 0 +--- !u!114 &4616290306121202327 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 40 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 4 + m_MaxSize: 47 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Close +--- !u!1 &7742712311334970126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3413013686078446151} + - component: {fileID: 2511819091764556577} + - component: {fileID: 2638196187645015298} + - component: {fileID: 633018877563332563} + m_Layer: 5 + m_Name: Rewarded + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3413013686078446151 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 5965516886513985157} + - {fileID: 3035265698078104281} + - {fileID: 2219183527695013266} + - {fileID: 3074011789293951898} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &2511819091764556577 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 999 + m_TargetDisplay: 0 +--- !u!114 &2638196187645015298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &633018877563332563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &8436952342056443077 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5084927109723455527} + - component: {fileID: 7267203896389005665} + - component: {fileID: 5500603550844857255} + m_Layer: 5 + m_Name: MaxRewardTitle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5084927109723455527 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 300} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7267203896389005665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_CullTransparentMesh: 0 +--- !u!114 &5500603550844857255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 50 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 71 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: MAX Rewarded Ad diff --git a/MaxSdk/Prefabs/Rewarded.prefab.meta b/MaxSdk/Prefabs/Rewarded.prefab.meta new file mode 100644 index 0000000..503754d --- /dev/null +++ b/MaxSdk/Prefabs/Rewarded.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 72244923a898c463c912b2675256c85c +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs/Rewarded.prefab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/README.md b/MaxSdk/README.md new file mode 100644 index 0000000..788effd --- /dev/null +++ b/MaxSdk/README.md @@ -0,0 +1,91 @@ +# Guru Ads Mediation + + + + + + + +## 开发注意事项 + +### Android 构建文件配置 + +- 项目 `BuildSettings/Player Settings/Publishing Settings` 中需要开启 + - [x] Custom Main Manifest + - Assets/Plugins/Android/AndroidManifest.xml + - [x] Custom Main Gradle Template + - Assets/Plugins/Android/mainTemplate.gradle + - [x] Custom Launcher Gradle Template + - Assets/Plugins/Android/launcherTemplate.gradle + - [x] Custom Gradle Properties Template + - Assets/Plugins/Android/gradleTemplate.properties + +
+ + +- 项目中 AndroidManifest.xml 更新需求: + - 在 `最后添加 APPLICATION_ID` 数据 + ```xml + + + + // Example APP_ID : ca-app-pub-2436733915645843~5500018314 + + ``` + - 在 最后添加 + ```xml + + + ``` +
+ + - 项目的 launcherTemplate.gradle + - 添加如下代码解决打包报错问题 + - 替换 `**PACKAGING_OPTIONS**` 为以下指定的内容 (Amazon的接入指南) + ```groovy + // 加入以下修改 + android { + ... + + configurations { + all*.exclude module: 'okio' // 修复okio库声明重复的问题 + } + + lintOptions { + abortOnError false + checkReleaseBuilds false // 修复Lint报错的问题 + } + + packagingOptions { + exclude("META-INF/DEPENDENCIES") + exclude("META-INF/LICENSE") + exclude("META-INF/LICENSE.txt") + exclude("META-INF/license.txt") + exclude("META-INF/NOTICE") + exclude("META-INF/NOTICE.txt") + exclude("META-INF/notice.txt") + exclude("META-INF/ASL2.0") + exclude("META-INF/*.kotlin_module") + } + **PLAY_ASSET_PACKS****SPLITS** + + ... + + + + ``` + + - 项目的 mainTemplate.gradle + - 添加如下代码解决打包报错问题 + + ```groovy + + android { + ... + + configurations { + all*.exclude module: 'okio' + } + + ``` diff --git a/MaxSdk/README.md.meta b/MaxSdk/README.md.meta new file mode 100644 index 0000000..46a5f07 --- /dev/null +++ b/MaxSdk/README.md.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 3800df16f199140559d3ab93da02f544 +labels: +- al_max +- al_max_export_path-MaxSdk/README.md +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Resources.meta b/MaxSdk/Resources.meta new file mode 100644 index 0000000..85845f7 --- /dev/null +++ b/MaxSdk/Resources.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1858b796f36642b8bcdcd9e7e3499e4 +labels: +- al_max +- al_max_export_path-MaxSdk/Resources +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Resources/Images.meta b/MaxSdk/Resources/Images.meta new file mode 100644 index 0000000..557d3a8 --- /dev/null +++ b/MaxSdk/Resources/Images.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afea262d96e02419e89cbd76ec9c309b +labels: +- al_max +- al_max_export_path-MaxSdk/Resources/Images +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Resources/Images/alert_icon.png b/MaxSdk/Resources/Images/alert_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..16519508598871e52f379050d7075a4aff309327 GIT binary patch literal 1154 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+SzC{oH>NS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5sCVBk9f!i-b3`J@>bnBzTN978hhy`6c`|8juL@%{VP-R?MeIDntc;3Jc_*$WSG zTjxD1#BFsXE*^2wWAXUI-g8mny_>s=${dBj4+}c0jQ%jDnMOZ%5#w_U_kPX)$zAL8O-&9QpEobK zvFN8F^L7T7IW{Z|vl-NwH`Qzpz8v;S&Y}P4I^oa447z+r%Mb1GI^Ypf%-g%~0EGDo4E2_C=)s)SYo(^v^$+n9F7|>>evu?f2}s z&O77cvclifx$W%<=tYwS6{F3PO?=x>I$ zvwpMcm}kCwXO=v{Nxa~~xP7X;YR15M@%7e~qD(I~^D->jaedLWoVBK_*b^2U&i41Nf97|a zVawJ@Rx3hw%>3&%JNv~6?Y`?m5B49@Ik4+`Q0R}nza5UobTp0S0S zc8_Xg^WJdzY)O!2IHS4Vb**s7u22>Y=Hj^OC`G~09iciI5)&2aoD!#L)D)}B~JUHh_*wHr&0u1J870;A4$(lMjE;`@& zfQ!!LpNWO%=ESI63YzwmwPNpz^f=xhe-l@`?tL1fH0ktO!Ots}e`1K3)V4~rcJ;Z| z9;eqk(my$DvYtC{?X_cNM&|b~8uC1t%Kk4u+9a*$ym_7+oHME8nbONG&yJbB7Ic>>`^TV_uBge}XWIqL zf2t*}5hW>!C8<`)MX5lF!N|bKK-bVf*T^Wuz|hLX(8|N&PEETh{4m<&t;uc GLK6TeaNqp^ literal 0 HcmV?d00001 diff --git a/MaxSdk/Resources/Images/alert_icon.png.meta b/MaxSdk/Resources/Images/alert_icon.png.meta new file mode 100644 index 0000000..b3b2d45 --- /dev/null +++ b/MaxSdk/Resources/Images/alert_icon.png.meta @@ -0,0 +1,94 @@ +fileFormatVersion: 2 +guid: 39fa469b3fe3544888d5f706a27da06f +labels: +- al_max +- al_max_export_path-MaxSdk/Resources/Images/alert_icon.png +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Resources/Images/uninstall_icon.png b/MaxSdk/Resources/Images/uninstall_icon.png new file mode 100755 index 0000000000000000000000000000000000000000..3b55354103e9a1717b1056e56871a667a98d106b GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeG3?%1&o4*=JaR&H=xB_ViXik240LWr03GxeO z$X`8g<3}LR+0(@_q=GS7fw_liWvIgjmTng@k0jM)7LTNS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5r1(g|SvA=~LZ0|V1RPZ!6KjC*gVpUoC_lxdrP(`4&0lT_d+t_+ABB_LE;hGkN#|ah@PEPoRu6AGE-s}gTTz>i1sp+Zmfie#!R^ws z>`m5_t8P5E*nRW+_jA&1l?RU>KQ6ITWbsY$Ip!-BeQGN-eK$P$Aja`U%(5t9(tWiO zonSVZc25PSmi^^MiC)J&n7GYqWj_es*u3*gu!W4w%m>|hy2_j-2NridWGu55O-q9PtC{%DT#=}A_BPU9de8TAmO^$hr^VF=Qzy5Y6waM> zt1S5==R${$?+5m&t*^Ux_3Xmr>5*3#uGVdI=-AD5n3-qY+M?*`>!z`6l4Nt8$j`A$ zwEk1}-Xjlhl!ooe%Jy_vV|@3}2Zn_WN0W7L#n}gJ=(PNB>g@KGCudGr=B_5R3u^wGuVawhZoI=!VfGSt zj(62J8+iF`YW_~yn`^Gnq|(5+o~>b@ee9j=)s06j4=woErL!Z@LojnT<7p+%k}P8e zN6m_BV$8s>WIC5ABgep*e)r1xX*@bhIhAHyv#pU-ocVXklG8I9yJlr{O?$n3QzPqa zyUyR2og_V#?3dT=(v)5iDC~PN=x@j_CX*GN%L3NT_u_;ye0eplxCColJ>SL`4V21= zvX{Q+24sb5+;y8Byl#GHmHw5#+^NPqN;{wCJ>F83{;=||@0#obuD&L&hkr$0b~vcU z7IWj}$xbbmVer+%bBsJbJ>bj^ZyG)%u$xvP|<#GS!&ZFRm-ZR zIjJi=4mkLlw7&lJ^6}%xi|6mp__9IhU+COsV5(Lvag8WRNi0dVN-jzTQVd20Muxfu zCb~xEAx6el#->)r#@Yr3Rt5&{g7sD?8glbfGSez?YcTUU-Uigb;OXk;vd$@?2>{z) BiL?L! literal 0 HcmV?d00001 diff --git a/MaxSdk/Resources/Images/warning_icon.png.meta b/MaxSdk/Resources/Images/warning_icon.png.meta new file mode 100644 index 0000000..d74ff37 --- /dev/null +++ b/MaxSdk/Resources/Images/warning_icon.png.meta @@ -0,0 +1,91 @@ +fileFormatVersion: 2 +guid: 966e6c9af57a640288672d89ee58a2fc +labels: +- al_max +- al_max_export_path-MaxSdk/Resources/Images/warning_icon.png +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts.meta b/MaxSdk/Scripts.meta new file mode 100644 index 0000000..befb8c9 --- /dev/null +++ b/MaxSdk/Scripts.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da3d2b54764a24ac0a8ce8394b67467f +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/Editor.meta b/MaxSdk/Scripts/Editor.meta new file mode 100644 index 0000000..15aed79 --- /dev/null +++ b/MaxSdk/Scripts/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b64bca2685cb419f847736eb5a1ac92 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/Editor/MaxInitialization.cs b/MaxSdk/Scripts/Editor/MaxInitialization.cs new file mode 100644 index 0000000..16c0ccb --- /dev/null +++ b/MaxSdk/Scripts/Editor/MaxInitialization.cs @@ -0,0 +1,129 @@ +// +// MaxInitialization.cs +// AppLovin MAX Unity Plugin +// +// Created by Thomas So on 5/24/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using AppLovinMax.Scripts.IntegrationManager.Editor; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; + +namespace AppLovinMax.Scripts.Editor +{ + [InitializeOnLoad] + public class MaxInitialize + { + private static readonly List ObsoleteNetworks = new List + { + "Snap", + "VerizonAds", + "VoodooAds" + }; + +#if UNITY_2018_2_OR_NEWER + private static readonly List ObsoleteFileExportPathsToDelete = new List + { + // The `EventSystemChecker` has been renamed to `MaxEventSystemChecker`. + "MaxSdk/Scripts/EventSystemChecker.cs", + "MaxSdk/Scripts/EventSystemChecker.cs.meta", + + // Google AdMob adapter pre/post process scripts. The logic has been migrated to the main plugin. + "MaxSdk/Mediation/Google/Editor/MaxGoogleInitialize.cs", + "MaxSdk/Mediation/Google/Editor/MaxGoogleInitialize.cs.meta", + "MaxSdk/Mediation/Google/Editor/MaxMediationGoogleUtils.cs", + "MaxSdk/Mediation/Google/Editor/MaxMediationGoogleUtils.cs.meta", + "MaxSdk/Mediation/Google/Editor/PostProcessor.cs", + "MaxSdk/Mediation/Google/Editor/PostProcessor.cs.meta", + "MaxSdk/Mediation/Google/Editor/PreProcessor.cs", + "MaxSdk/Mediation/Google/Editor/PreProcessor.cs.meta", + "MaxSdk/Mediation/Google/Editor/MaxSdk.Mediation.Google.Editor.asmdef", + "MaxSdk/Mediation/Google/MaxSdk.Mediation.Google.Editor.asmdef.meta", + "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 + "MaxSdk/Mediation/GoogleAdManager/Editor/MaxGoogleAdManagerInitialize.cs", + "MaxSdk/Mediation/GoogleAdManager/Editor/MaxGoogleAdManagerInitialize.cs.meta", + "MaxSdk/Mediation/GoogleAdManager/Editor/PostProcessor.cs", + "MaxSdk/Mediation/GoogleAdManager/Editor/PostProcessor.cs.meta", + "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" + }; +#endif + + static MaxInitialize() + { +#if UNITY_IOS + // Check that the publisher is targeting iOS 9.0+ + if (!PlayerSettings.iOS.targetOSVersionString.StartsWith("9.") && !PlayerSettings.iOS.targetOSVersionString.StartsWith("1")) + { + MaxSdkLogger.UserError("Detected iOS project version less than iOS 9 - The AppLovin MAX SDK WILL NOT WORK ON < iOS9!!!"); + } +#endif + + var pluginParentDir = AppLovinIntegrationManager.PluginParentDirectory; + var isPluginOutsideAssetsDir = AppLovinIntegrationManager.IsPluginOutsideAssetsDirectory; + var changesMade = AppLovinIntegrationManager.MovePluginFilesIfNeeded(pluginParentDir, isPluginOutsideAssetsDir); + if (isPluginOutsideAssetsDir) + { + // If the plugin is not under the assets folder, delete the MaxSdk/Mediation folder in the plugin, so that the adapters are not imported at that location and imported to the default location. + var mediationDir = Path.Combine(pluginParentDir, "MaxSdk/Mediation"); + if (Directory.Exists(mediationDir)) + { + FileUtil.DeleteFileOrDirectory(mediationDir); + FileUtil.DeleteFileOrDirectory(mediationDir + ".meta"); + changesMade = true; + } + } + + AppLovinIntegrationManager.AddLabelsToAssetsIfNeeded(pluginParentDir, isPluginOutsideAssetsDir); + +#if UNITY_2018_2_OR_NEWER + foreach (var obsoleteFileExportPathToDelete in ObsoleteFileExportPathsToDelete) + { + var pathToDelete = MaxSdkUtils.GetAssetPathForExportPath(obsoleteFileExportPathToDelete); + if (CheckExistence(pathToDelete)) + { + MaxSdkLogger.UserDebug("Deleting obsolete file '" + pathToDelete + "' that are no longer needed."); + FileUtil.DeleteFileOrDirectory(pathToDelete); + changesMade = true; + } + } +#endif + + // Check if any obsolete networks are installed + foreach (var obsoleteNetwork in ObsoleteNetworks) + { + var networkDir = Path.Combine(pluginParentDir, "MaxSdk/Mediation/" + obsoleteNetwork); + if (CheckExistence(networkDir)) + { + MaxSdkLogger.UserDebug("Deleting obsolete network " + obsoleteNetwork + " from path " + networkDir + "..."); + FileUtil.DeleteFileOrDirectory(networkDir); + changesMade = true; + } + } + + // Refresh UI + if (changesMade) + { + AssetDatabase.Refresh(); + MaxSdkLogger.UserDebug("AppLovin MAX Migration completed"); + } + + AppLovinAutoUpdater.Update(); + } + + private static bool CheckExistence(string location) + { + return File.Exists(location) || + Directory.Exists(location) || + (location.EndsWith("/*") && Directory.Exists(Path.GetDirectoryName(location))); + } + } +} diff --git a/MaxSdk/Scripts/Editor/MaxInitialization.cs.meta b/MaxSdk/Scripts/Editor/MaxInitialization.cs.meta new file mode 100644 index 0000000..aaafdd0 --- /dev/null +++ b/MaxSdk/Scripts/Editor/MaxInitialization.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 512169ab4bfaf406c81d28878b456b30 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/Editor/MaxInitialization.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs b/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs new file mode 100644 index 0000000..8ad8aee --- /dev/null +++ b/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs @@ -0,0 +1,272 @@ +// +// MaxPostProcessBuildAndroid.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 4/10/20. +// Copyright © 2020 AppLovin. All rights reserved. +// + +#if UNITY_ANDROID && UNITY_2018_2_OR_NEWER +using AppLovinMax.Scripts.IntegrationManager.Editor; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using AppLovinMax.ThirdParty.MiniJson; +using UnityEditor; +using UnityEditor.Android; +using UnityEngine; + +namespace AppLovinMax.Scripts.Editor +{ + /// + /// A post processor used to update the Android project once it is generated. + /// + public class MaxPostProcessBuildAndroid : IPostGenerateGradleAndroidProject + { +#if UNITY_2019_3_OR_NEWER + private const string PropertyAndroidX = "android.useAndroidX"; + private const string PropertyJetifier = "android.enableJetifier"; + private const string EnableProperty = "=true"; +#endif + private const string PropertyDexingArtifactTransform = "android.enableDexingArtifactTransform"; + private const string DisableProperty = "=false"; + + private const string KeyMetaDataAppLovinSdkKey = "applovin.sdk.key"; + private const string KeyMetaDataAppLovinVerboseLoggingOn = "applovin.sdk.verbose_logging"; + private const string KeyMetaDataGoogleApplicationId = "com.google.android.gms.ads.APPLICATION_ID"; + private const string KeyMetaDataGoogleAdManagerApp = "com.google.android.gms.ads.AD_MANAGER_APP"; + + private static readonly XNamespace AndroidNamespace = "http://schemas.android.com/apk/res/android"; + + private static string PluginMediationDirectory + { + get + { + var pluginParentDir = AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; + return Path.Combine(pluginParentDir, "MaxSdk/Mediation/"); + } + } + + public void OnPostGenerateGradleAndroidProject(string path) + { +#if UNITY_2019_3_OR_NEWER + var gradlePropertiesPath = Path.Combine(path, "../gradle.properties"); +#else + var gradlePropertiesPath = Path.Combine(path, "gradle.properties"); +#endif + var gradlePropertiesUpdated = new List(); + + // If the gradle properties file already exists, make sure to add any previous properties. + if (File.Exists(gradlePropertiesPath)) + { + var lines = File.ReadAllLines(gradlePropertiesPath); + +#if UNITY_2019_3_OR_NEWER + // Add all properties except AndroidX, Jetifier, and DexingArtifactTransform since they may already exist. We will re-add them below. + gradlePropertiesUpdated.AddRange(lines.Where(line => !line.Contains(PropertyAndroidX) && !line.Contains(PropertyJetifier) && !line.Contains(PropertyDexingArtifactTransform))); +#else + // Add all properties except DexingArtifactTransform since it may already exist. We will re-add it below. + gradlePropertiesUpdated.AddRange(lines.Where(line => !line.Contains(PropertyDexingArtifactTransform))); +#endif + } + +#if UNITY_2019_3_OR_NEWER + // Enable AndroidX and Jetifier properties + gradlePropertiesUpdated.Add(PropertyAndroidX + EnableProperty); + gradlePropertiesUpdated.Add(PropertyJetifier + EnableProperty); +#endif + // Disable dexing using artifact transform (it causes issues for ExoPlayer with Gradle plugin 3.5.0+) + gradlePropertiesUpdated.Add(PropertyDexingArtifactTransform + DisableProperty); + + try + { + File.WriteAllText(gradlePropertiesPath, string.Join("\n", gradlePropertiesUpdated.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to enable AndroidX and Jetifier. gradle.properties file write failed."); + Console.WriteLine(exception); + } + + ProcessAndroidManifest(path); + + var rawResourceDirectory = Path.Combine(path, "src/main/res/raw"); + if (AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager) + { + // For Unity 2018.1 or older, the consent flow is enabled in AppLovinPreProcessAndroid. + AppLovinPreProcessAndroid.EnableConsentFlowIfNeeded(rawResourceDirectory); + } + else + { + AppLovinPreProcessAndroid.EnableTermsFlowIfNeeded(rawResourceDirectory); + } + } + + public int callbackOrder + { + get { return int.MaxValue; } + } + + private static void ProcessAndroidManifest(string path) + { + var manifestPath = Path.Combine(path, "src/main/AndroidManifest.xml"); + XDocument manifest; + try + { + manifest = XDocument.Load(manifestPath); + } +#pragma warning disable 0168 + catch (IOException exception) +#pragma warning restore 0168 + { + MaxSdkLogger.UserWarning("[AppLovin MAX] AndroidManifest.xml is missing."); + return; + } + + // Get the `manifest` element. + var elementManifest = manifest.Element("manifest"); + if (elementManifest == null) + { + MaxSdkLogger.UserWarning("[AppLovin MAX] AndroidManifest.xml is invalid."); + return; + } + + var elementApplication = elementManifest.Element("application"); + if (elementApplication == null) + { + MaxSdkLogger.UserWarning("[AppLovin MAX] AndroidManifest.xml is invalid."); + return; + } + + var metaDataElements = elementApplication.Descendants().Where(element => element.Name.LocalName.Equals("meta-data")); + + AddSdkKeyIfNeeded(elementApplication); + EnableVerboseLoggingIfNeeded(elementApplication); + AddGoogleApplicationIdIfNeeded(elementApplication, metaDataElements); + + // Save the updated manifest file. + manifest.Save(manifestPath); + } + + private static void AddSdkKeyIfNeeded(XElement elementApplication) + { + var sdkKey = AppLovinSettings.Instance.SdkKey; + if (string.IsNullOrEmpty(sdkKey)) return; + + var descendants = elementApplication.Descendants(); + var sdkKeyMetaData = descendants.FirstOrDefault(descendant => descendant.FirstAttribute != null && + descendant.FirstAttribute.Name.LocalName.Equals("name") && + descendant.FirstAttribute.Value.Equals(KeyMetaDataAppLovinSdkKey) && + descendant.LastAttribute != null && + descendant.LastAttribute.Name.LocalName.Equals("value")); + + // check if applovin.sdk.key meta data exists. + if (sdkKeyMetaData != null) + { + sdkKeyMetaData.LastAttribute.Value = sdkKey; + } + else + { + // add applovin.sdk.key meta data if it does not exist. + var metaData = CreateMetaDataElement(KeyMetaDataAppLovinSdkKey, sdkKey); + elementApplication.Add(metaData); + } + } + + private static void EnableVerboseLoggingIfNeeded(XElement elementApplication) + { + var enabled = EditorPrefs.GetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, false); + + var descendants = elementApplication.Descendants(); + var verboseLoggingMetaData = descendants.FirstOrDefault(descendant => descendant.FirstAttribute != null && + descendant.FirstAttribute.Name.LocalName.Equals("name") && + descendant.FirstAttribute.Value.Equals(KeyMetaDataAppLovinVerboseLoggingOn) && + descendant.LastAttribute != null && + descendant.LastAttribute.Name.LocalName.Equals("value")); + + // check if applovin.sdk.verbose_logging meta data exists. + if (verboseLoggingMetaData != null) + { + if (enabled) + { + // update applovin.sdk.verbose_logging meta data value. + verboseLoggingMetaData.LastAttribute.Value = enabled.ToString(); + } + else + { + // remove applovin.sdk.verbose_logging meta data. + verboseLoggingMetaData.Remove(); + } + } + else + { + if (enabled) + { + // add applovin.sdk.verbose_logging meta data if it does not exist. + var metaData = CreateMetaDataElement(KeyMetaDataAppLovinVerboseLoggingOn, enabled.ToString()); + elementApplication.Add(metaData); + } + } + } + + private static void AddGoogleApplicationIdIfNeeded(XElement elementApplication, IEnumerable metaDataElements) + { + if (!AppLovinIntegrationManager.IsAdapterInstalled("Google") && !AppLovinIntegrationManager.IsAdapterInstalled("GoogleAdManager")) return; + + var googleApplicationIdMetaData = GetMetaDataElement(metaDataElements, KeyMetaDataGoogleApplicationId); + var appId = AppLovinSettings.Instance.AdMobAndroidAppId; + // Log error if the App ID is not set. + if (string.IsNullOrEmpty(appId) || !appId.StartsWith("ca-app-pub-")) + { + MaxSdkLogger.UserError("Google App ID is not set. Please enter a valid app ID within the AppLovin Integration Manager window."); + return; + } + + // Check if the Google App ID meta data already exists. Update if it already exists. + if (googleApplicationIdMetaData != null) + { + googleApplicationIdMetaData.SetAttributeValue(AndroidNamespace + "value", appId); + } + // Meta data doesn't exist, add it. + else + { + elementApplication.Add(CreateMetaDataElement(KeyMetaDataGoogleApplicationId, appId)); + } + } + + /// + /// Creates and returns a meta-data element with the given name and value. + /// + private static XElement CreateMetaDataElement(string name, object value) + { + var metaData = new XElement("meta-data"); + metaData.Add(new XAttribute(AndroidNamespace + "name", name)); + metaData.Add(new XAttribute(AndroidNamespace + "value", value)); + + return metaData; + } + + /// + /// Looks through all the given meta-data elements to check if the required one exists. Returns null if it doesn't exist. + /// + private static XElement GetMetaDataElement(IEnumerable metaDataElements, string metaDataName) + { + foreach (var metaDataElement in metaDataElements) + { + var attributes = metaDataElement.Attributes(); + if (attributes.Any(attribute => attribute.Name.Namespace.Equals(AndroidNamespace) + && attribute.Name.LocalName.Equals("name") + && attribute.Value.Equals(metaDataName))) + { + return metaDataElement; + } + } + + return null; + } + } +} + +#endif diff --git a/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs.meta b/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs.meta new file mode 100644 index 0000000..80d55e9 --- /dev/null +++ b/MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 87732883951bc404e85f2a223d3bd7c8 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/Editor/MaxPostProcessBuildAndroid.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs b/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs new file mode 100644 index 0000000..9dd3d7d --- /dev/null +++ b/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs @@ -0,0 +1,690 @@ +// +// MaxPostProcessBuildiOS.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 8/5/20. +// Copyright © 2020 AppLovin. All rights reserved. +// + +#if UNITY_IOS || UNITY_IPHONE + +using AppLovinMax.Scripts.IntegrationManager.Editor; +#if UNITY_2019_3_OR_NEWER +using UnityEditor.iOS.Xcode.Extensions; +#endif +using UnityEngine.Networking; +using System; +using System.Linq; +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEditor.iOS.Xcode; +using UnityEngine; + +namespace AppLovinMax.Scripts.Editor +{ + [Serializable] + public class SkAdNetworkData + { + [SerializeField] public string[] SkAdNetworkIds; + } + + public class MaxPostProcessBuildiOS + { +#if !UNITY_2019_3_OR_NEWER + private const string UnityMainTargetName = "Unity-iPhone"; +#endif + private const string TargetUnityIphonePodfileLine = "target 'Unity-iPhone' do"; + private const string LegacyResourcesDirectoryName = "Resources"; + private const string AppLovinMaxResourcesDirectoryName = "AppLovinMAXResources"; + private const string AppLovinAdvertisingAttributionEndpoint = "https://postbacks-app.com"; + + private const string AppLovinSettingsPlistFileName = "AppLovin-Settings.plist"; + private const string KeyConsentFlowInfo = "ConsentFlowInfo"; + 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 static readonly List DynamicLibrariesToEmbed = new List + { + "DTBiOSSDK.xcframework", + "FBSDKCoreKit_Basics.xcframework", + "HyprMX.xcframework", + "IASDKCore.xcframework", + "MobileFuseSDK.xcframework", + "OMSDK_Appodeal.xcframework", + "OMSDK_Ogury.xcframework", + "OMSDK_Pubnativenet.xcframework", + "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 + { + var pluginParentDir = AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; + return Path.Combine(pluginParentDir, "MaxSdk/Mediation/"); + } + } + + [PostProcessBuildAttribute(int.MaxValue)] + public static void MaxPostProcessPbxProject(BuildTarget buildTarget, string buildPath) + { + var projectPath = PBXProject.GetPBXProjectPath(buildPath); + var project = new PBXProject(); + project.ReadFromFile(projectPath); + +#if UNITY_2019_3_OR_NEWER + var unityMainTargetGuid = project.GetUnityMainTargetGuid(); + var unityFrameworkTargetGuid = project.GetUnityFrameworkTargetGuid(); +#else + var unityMainTargetGuid = project.TargetGuidByName(UnityMainTargetName); + var unityFrameworkTargetGuid = project.TargetGuidByName(UnityMainTargetName); +#endif + EmbedDynamicLibrariesIfNeeded(buildPath, project, unityMainTargetGuid); + + var internalSettingsEnabled = AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager; + var userTrackingUsageDescriptionDe = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe : AppLovinSettings.Instance.UserTrackingUsageDescriptionDe; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionDe, "de", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionEn = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn : AppLovinSettings.Instance.UserTrackingUsageDescriptionEn; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionEn, "en", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionEs = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs : AppLovinSettings.Instance.UserTrackingUsageDescriptionEs; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionEs, "es", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionFr = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr : AppLovinSettings.Instance.UserTrackingUsageDescriptionFr; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionFr, "fr", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionJa = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa : AppLovinSettings.Instance.UserTrackingUsageDescriptionJa; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionJa, "ja", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionKo = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo : AppLovinSettings.Instance.UserTrackingUsageDescriptionKo; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionKo, "ko", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionZhHans = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans : AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHans; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionZhHans, "zh-Hans", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionZhHant = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant : AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHant; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionZhHant, "zh-Hant", buildPath, project, unityMainTargetGuid); + + AddSwiftSupportIfNeeded(buildPath, project, unityFrameworkTargetGuid); + EmbedSwiftStandardLibrariesIfNeeded(buildPath, project, unityMainTargetGuid); + AddYandexSettingsIfNeeded(project, unityMainTargetGuid); + + project.WriteToFile(projectPath); + } + + private static void EmbedDynamicLibrariesIfNeeded(string buildPath, PBXProject project, string targetGuid) + { + // Check that the Pods directory exists (it might not if a publisher is building with Generate Podfile setting disabled in EDM). + var podsDirectory = Path.Combine(buildPath, "Pods"); + if (!Directory.Exists(podsDirectory)) return; + + var dynamicLibraryPathsPresentInProject = new List(); + foreach (var dynamicLibraryToSearch in DynamicLibrariesToEmbed) + { + // both .framework and .xcframework are directories, not files + var directories = Directory.GetDirectories(podsDirectory, dynamicLibraryToSearch, SearchOption.AllDirectories); + if (directories.Length <= 0) continue; + + var dynamicLibraryAbsolutePath = directories[0]; + var index = dynamicLibraryAbsolutePath.LastIndexOf("Pods"); + var relativePath = dynamicLibraryAbsolutePath.Substring(index); + dynamicLibraryPathsPresentInProject.Add(relativePath); + } + + if (dynamicLibraryPathsPresentInProject.Count <= 0) return; + +#if UNITY_2019_3_OR_NEWER + // Embed framework only if the podfile does not contain target `Unity-iPhone`. + if (!ContainsUnityIphoneTargetInPodfile(buildPath)) + { + foreach (var dynamicLibraryPath in dynamicLibraryPathsPresentInProject) + { + var fileGuid = project.AddFile(dynamicLibraryPath, dynamicLibraryPath); + project.AddFileToEmbedFrameworks(targetGuid, fileGuid); + } + } +#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. + if (runpathSearchPaths.Contains("@executable_path/Frameworks")) return; + + runpathSearchPaths += "@executable_path/Frameworks"; + project.SetBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", runpathSearchPaths); +#endif + } + + private static void LocalizeUserTrackingDescriptionIfNeeded(string localizedUserTrackingDescription, string localeCode, string buildPath, PBXProject project, string targetGuid) + { + // Use the legacy resources directory name if the build is being appended (the "Resources" directory already exists if it is an incremental build). + var resourcesDirectoryName = Directory.Exists(Path.Combine(buildPath, LegacyResourcesDirectoryName)) ? LegacyResourcesDirectoryName : AppLovinMaxResourcesDirectoryName; + var resourcesDirectoryPath = Path.Combine(buildPath, resourcesDirectoryName); + var localeSpecificDirectoryName = localeCode + ".lproj"; + var localeSpecificDirectoryPath = Path.Combine(resourcesDirectoryPath, localeSpecificDirectoryName); + var infoPlistStringsFilePath = Path.Combine(localeSpecificDirectoryPath, "InfoPlist.strings"); + + // Check if localization has been disabled between builds, and remove them as needed. + if (ShouldRemoveLocalization(localizedUserTrackingDescription)) + { + if (!File.Exists(infoPlistStringsFilePath)) return; + + File.Delete(infoPlistStringsFilePath); + return; + } + + // Create intermediate directories as needed. + if (!Directory.Exists(resourcesDirectoryPath)) + { + Directory.CreateDirectory(resourcesDirectoryPath); + } + + if (!Directory.Exists(localeSpecificDirectoryPath)) + { + Directory.CreateDirectory(localeSpecificDirectoryPath); + } + + var localizedDescriptionLine = "\"NSUserTrackingUsageDescription\" = \"" + localizedUserTrackingDescription + "\";\n"; + // File already exists, update it in case the value changed between builds. + if (File.Exists(infoPlistStringsFilePath)) + { + var output = new List(); + var lines = File.ReadAllLines(infoPlistStringsFilePath); + var keyUpdated = false; + foreach (var line in lines) + { + if (line.Contains("NSUserTrackingUsageDescription")) + { + output.Add(localizedDescriptionLine); + keyUpdated = true; + } + else + { + output.Add(line); + } + } + + if (!keyUpdated) + { + output.Add(localizedDescriptionLine); + } + + File.WriteAllText(infoPlistStringsFilePath, string.Join("\n", output.ToArray()) + "\n"); + } + // File doesn't exist, create one. + else + { + File.WriteAllText(infoPlistStringsFilePath, "/* Localized versions of Info.plist keys - Generated by AL MAX plugin */\n" + localizedDescriptionLine); + } + + var localeSpecificDirectoryRelativePath = Path.Combine(resourcesDirectoryName, localeSpecificDirectoryName); + var guid = project.AddFolderReference(localeSpecificDirectoryRelativePath, localeSpecificDirectoryRelativePath); + project.AddFileToBuild(targetGuid, guid); + } + + private static bool ShouldRemoveLocalization(string localizedUserTrackingDescription) + { + 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; + } + + return !settings.ConsentFlowEnabled || !settings.UserTrackingUsageLocalizationEnabled; + } + + private static void AddSwiftSupportIfNeeded(string buildPath, PBXProject project, string targetGuid) + { + 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); + + // 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 + if (string.IsNullOrEmpty(swiftVersion)) + { + project.SetBuildProperty(targetGuid, "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"); + } + + private static void CreateSwiftFile(string swiftFilePath) + { + if (File.Exists(swiftFilePath)) return; + + // Create a file to write to. + using (var writer = File.CreateText(swiftFilePath)) + { + writer.WriteLine("//\n// MAXSwiftSupport.swift\n//"); + writer.WriteLine("\nimport Foundation\n"); + writer.WriteLine("// This file ensures the project includes Swift support."); + writer.WriteLine("// It is automatically generated by the MAX Unity Plugin."); + writer.Close(); + } + } + + [PostProcessBuildAttribute(int.MaxValue)] + public static void MaxPostProcessPlist(BuildTarget buildTarget, string path) + { + var plistPath = Path.Combine(path, "Info.plist"); + var plist = new PlistDocument(); + plist.ReadFromFile(plistPath); + + SetSdkKeyIfNeeded(plist); + SetAttributionReportEndpointIfNeeded(plist); + +#if UNITY_2018_2_OR_NEWER + EnableVerboseLoggingIfNeeded(plist); + AddGoogleApplicationIdIfNeeded(plist); +#endif + + AddSdkSettingsIfNeeded(plist, path); + EnableTermsFlowIfNeeded(plist); + AddSkAdNetworksInfoIfNeeded(plist); + + plist.WriteToFile(plistPath); + } + + private static void SetSdkKeyIfNeeded(PlistDocument plist) + { + var sdkKey = AppLovinSettings.Instance.SdkKey; + if (string.IsNullOrEmpty(sdkKey)) return; + + const string AppLovinVerboseLoggingOnKey = "AppLovinSdkKey"; + plist.root.SetString(AppLovinVerboseLoggingOnKey, sdkKey); + } + + private static void SetAttributionReportEndpointIfNeeded(PlistDocument plist) + { + if (AppLovinSettings.Instance.SetAttributionReportEndpoint) + { + plist.root.SetString("NSAdvertisingAttributionReportEndpoint", AppLovinAdvertisingAttributionEndpoint); + } + else + { + PlistElement attributionReportEndPoint; + plist.root.values.TryGetValue("NSAdvertisingAttributionReportEndpoint", out attributionReportEndPoint); + + // Check if we had previously set the attribution endpoint and un-set it. + if (attributionReportEndPoint != null && AppLovinAdvertisingAttributionEndpoint.Equals(attributionReportEndPoint.AsString())) + { + plist.root.values.Remove("NSAdvertisingAttributionReportEndpoint"); + } + } + } + +#if UNITY_2018_2_OR_NEWER + private static void EnableVerboseLoggingIfNeeded(PlistDocument plist) + { + if (!EditorPrefs.HasKey(MaxSdkLogger.KeyVerboseLoggingEnabled)) return; + + var enabled = EditorPrefs.GetBool(MaxSdkLogger.KeyVerboseLoggingEnabled); + const string AppLovinVerboseLoggingOnKey = "AppLovinVerboseLoggingOn"; + if (enabled) + { + plist.root.SetBoolean(AppLovinVerboseLoggingOnKey, enabled); + } + else + { + plist.root.values.Remove(AppLovinVerboseLoggingOnKey); + } + } + + private static void AddGoogleApplicationIdIfNeeded(PlistDocument plist) + { + if (!AppLovinIntegrationManager.IsAdapterInstalled("Google") && !AppLovinIntegrationManager.IsAdapterInstalled("GoogleAdManager")) return; + + const string googleApplicationIdentifier = "GADApplicationIdentifier"; + var appId = AppLovinSettings.Instance.AdMobIosAppId; + // Log error if the App ID is not set. + if (string.IsNullOrEmpty(appId) || !appId.StartsWith("ca-app-pub-")) + { + Debug.LogError("[AppLovin MAX] Google App ID is not set. Please enter a valid app ID within the AppLovin Integration Manager window."); + return; + } + + plist.root.SetString(googleApplicationIdentifier, appId); + } +#endif + + private static void AddYandexSettingsIfNeeded(PBXProject project, string unityMainTargetGuid) + { + if (!AppLovinIntegrationManager.IsAdapterInstalled("Yandex")) return; + + if (MaxSdkUtils.CompareVersions(PlayerSettings.iOS.targetOSVersionString, "12.0") == MaxSdkUtils.VersionComparisonResult.Lesser) + { + Debug.LogWarning("Your iOS target version is under the minimum required version by Yandex. Please update it to 12.0 or newer in your ProjectSettings and rebuild your project."); + return; + } + + project.SetBuildProperty(unityMainTargetGuid, "GENERATE_INFOPLIST_FILE", "NO"); + } + + 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; + + var sdkSettingsPlistPath = Path.Combine(buildPath, AppLovinSettingsPlistFileName); + var sdkSettingsPlist = new PlistDocument(); + if (File.Exists(sdkSettingsPlistPath)) + { + sdkSettingsPlist.ReadFromFile(sdkSettingsPlistPath); + } + + EnableConsentFlowIfNeeded(sdkSettingsPlist, infoPlist); + + sdkSettingsPlist.WriteToFile(sdkSettingsPlistPath); + + var projectPath = PBXProject.GetPBXProjectPath(buildPath); + var project = new PBXProject(); + project.ReadFromFile(projectPath); + +#if UNITY_2019_3_OR_NEWER + var unityMainTargetGuid = project.GetUnityMainTargetGuid(); +#else + var unityMainTargetGuid = project.TargetGuidByName(UnityMainTargetName); +#endif + + var guid = project.AddFile(AppLovinSettingsPlistFileName, AppLovinSettingsPlistFileName, PBXSourceTree.Source); + project.AddFileToBuild(unityMainTargetGuid, guid); + project.WriteToFile(projectPath); + } + + private static void EnableConsentFlowIfNeeded(PlistDocument applovinSettingsPlist, PlistDocument infoPlist) + { + var consentFlowEnabled = AppLovinInternalSettings.Instance.ConsentFlowEnabled; + var userTrackingUsageDescription = AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn; + var privacyPolicyUrl = AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl; + if (string.IsNullOrEmpty(userTrackingUsageDescription) || string.IsNullOrEmpty(privacyPolicyUrl)) + { + AppLovinIntegrationManager.ShowBuildFailureDialog("You cannot use the AppLovin SDK's consent flow without defining a Privacy Policy URL and the `User Tracking Usage Description` in the AppLovin Integration Manager. \n\n" + + "Both values must be included to enable the SDK's consent flow."); + + // No need to update the info.plist here. Default consent flow state will be determined on the SDK side. + return; + } + + var consentFlowInfoRoot = applovinSettingsPlist.root.CreateDict(KeyConsentFlowInfo); + consentFlowInfoRoot.SetBoolean(KeyConsentFlowEnabled, consentFlowEnabled); + consentFlowInfoRoot.SetString(KeyConsentFlowPrivacyPolicy, privacyPolicyUrl); + + var termsOfServiceUrl = AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl; + if (!string.IsNullOrEmpty(termsOfServiceUrl)) + { + consentFlowInfoRoot.SetString(KeyConsentFlowTermsOfService, termsOfServiceUrl); + } + + var advertisingPartnerUrls = AppLovinInternalSettings.Instance.ConsentFlowAdvertisingPartnerUrls; + if (MaxSdkUtils.IsValidString(advertisingPartnerUrls)) + { + var advertisingPartnerUrlsList = advertisingPartnerUrls.Split(','); + var advertisingPartnersArray = consentFlowInfoRoot.CreateArray(KeyConsentFlowAdvertisingPartners); + foreach (var advertisingPartner in advertisingPartnerUrlsList) + { + advertisingPartnersArray.AddString(advertisingPartner); + } + } + + 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; + + // Check if terms flow is enabled for this format. + var consentFlowPlatform = AppLovinSettings.Instance.ConsentFlowPlatform; + if (consentFlowPlatform != Platform.All && consentFlowPlatform != Platform.iOS) return; + + var userTrackingUsageDescription = AppLovinSettings.Instance.UserTrackingUsageDescriptionEn; + var privacyPolicyUrl = AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl; + if (string.IsNullOrEmpty(userTrackingUsageDescription) || string.IsNullOrEmpty(privacyPolicyUrl)) + { + AppLovinIntegrationManager.ShowBuildFailureDialog("You cannot use the AppLovin SDK's consent flow without defining a Privacy Policy URL and the `User Tracking Usage Description` in the AppLovin Integration Manager. \n\n" + + "Both values must be included to enable the SDK's consent flow."); + + // No need to update the info.plist here. Default consent flow state will be determined on the SDK side. + return; + } + + var consentFlowInfoRoot = plist.root.CreateDict("AppLovinConsentFlowInfo"); + consentFlowInfoRoot.SetBoolean("AppLovinConsentFlowEnabled", consentFlowEnabled); + consentFlowInfoRoot.SetString("AppLovinConsentFlowPrivacyPolicy", privacyPolicyUrl); + + var termsOfServiceUrl = AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl; + if (!string.IsNullOrEmpty(termsOfServiceUrl)) + { + consentFlowInfoRoot.SetString("AppLovinConsentFlowTermsOfService", termsOfServiceUrl); + } + + plist.root.SetString("NSUserTrackingUsageDescription", userTrackingUsageDescription); + } + + private static void AddSkAdNetworksInfoIfNeeded(PlistDocument plist) + { + var skAdNetworkData = GetSkAdNetworkData(); + var skAdNetworkIds = skAdNetworkData.SkAdNetworkIds; + // Check if we have a valid list of SKAdNetworkIds that need to be added. + if (skAdNetworkIds == null || skAdNetworkIds.Length < 1) return; + + // + // Add the SKAdNetworkItems to the plist. It should look like following: + // + // SKAdNetworkItems + // + // + // SKAdNetworkIdentifier + // ABC123XYZ.skadnetwork + // + // + // SKAdNetworkIdentifier + // 123QWE456.skadnetwork + // + // + // SKAdNetworkIdentifier + // 987XYZ123.skadnetwork + // + // + // + PlistElement skAdNetworkItems; + plist.root.values.TryGetValue("SKAdNetworkItems", out skAdNetworkItems); + var existingSkAdNetworkIds = new HashSet(); + // Check if SKAdNetworkItems array is already in the Plist document and collect all the IDs that are already present. + if (skAdNetworkItems != null && skAdNetworkItems.GetType() == typeof(PlistElementArray)) + { + var plistElementDictionaries = skAdNetworkItems.AsArray().values.Where(plistElement => plistElement.GetType() == typeof(PlistElementDict)); + foreach (var plistElement in plistElementDictionaries) + { + PlistElement existingId; + plistElement.AsDict().values.TryGetValue("SKAdNetworkIdentifier", out existingId); + if (existingId == null || existingId.GetType() != typeof(PlistElementString) || string.IsNullOrEmpty(existingId.AsString())) continue; + + existingSkAdNetworkIds.Add(existingId.AsString()); + } + } + // Else, create an array of SKAdNetworkItems into which we will add our IDs. + else + { + skAdNetworkItems = plist.root.CreateArray("SKAdNetworkItems"); + } + + foreach (var skAdNetworkId in skAdNetworkIds) + { + // Skip adding IDs that are already in the array. + if (existingSkAdNetworkIds.Contains(skAdNetworkId)) continue; + + var skAdNetworkItemDict = skAdNetworkItems.AsArray().AddDict(); + skAdNetworkItemDict.SetString("SKAdNetworkIdentifier", skAdNetworkId); + } + } + + private static SkAdNetworkData GetSkAdNetworkData() + { + var uriBuilder = new UriBuilder("https://dash.applovin.com/docs/v1/unity_integration_manager/sk_ad_networks_info"); + + // 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); + if (!string.IsNullOrEmpty(adNetworks)) + { + uriBuilder.Query += string.Format("adnetworks={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) +#endif + { + MaxSdkLogger.UserError("Failed to retrieve SKAdNetwork IDs with error: " + unityWebRequest.error); + return new SkAdNetworkData(); + } + + try + { + return JsonUtility.FromJson(unityWebRequest.downloadHandler.text); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to parse data '" + unityWebRequest.downloadHandler.text + "' with exception: " + exception); + return new SkAdNetworkData(); + } + } + } + +#if UNITY_2019_3_OR_NEWER + private static bool ContainsUnityIphoneTargetInPodfile(string buildPath) + { + var podfilePath = Path.Combine(buildPath, "Podfile"); + if (!File.Exists(podfilePath)) return false; + + var lines = File.ReadAllLines(podfilePath); + return lines.Any(line => line.Contains(TargetUnityIphonePodfileLine)); + } +#endif + } +} + +#endif diff --git a/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs.meta b/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs.meta new file mode 100644 index 0000000..0c510bc --- /dev/null +++ b/MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: e71caf465f5b24f848fa05c337203e79 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/Editor/MaxPostProcessBuildiOS.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef b/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef new file mode 100644 index 0000000..e4bb2e0 --- /dev/null +++ b/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef @@ -0,0 +1,11 @@ +{ + "name": "MaxSdk.Scripts.Editor", + "references": [ + "MaxSdk.Scripts", + "MaxSdk.Scripts.IntegrationManager.Editor" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [] +} diff --git a/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef.meta b/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef.meta new file mode 100644 index 0000000..690992a --- /dev/null +++ b/MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: 75f93d930c51d43579f691746bd04a70 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/Editor/MaxSdk.Scripts.Editor.asmdef +timeCreated: 1591749791 diff --git a/MaxSdk/Scripts/IntegrationManager.meta b/MaxSdk/Scripts/IntegrationManager.meta new file mode 100644 index 0000000..054e7b9 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9903db0d6994746d4bee2e4ac615e8ef +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor.meta b/MaxSdk/Scripts/IntegrationManager/Editor.meta new file mode 100644 index 0000000..06993c4 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 735b8675e6ac746d0ac244312653f7f2 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs new file mode 100644 index 0000000..01cc639 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs @@ -0,0 +1,195 @@ +// +// AppLovinAutoUpdater.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 1/27/20. +// Copyright © 2020 AppLovin. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// Handles auto updates for AppLovin MAX plugin. + /// + 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; + + // TODO: Make this list dynamic. + public static readonly Dictionary MinAdapterVersions = new Dictionary() + { + {"ADCOLONY_NETWORK", "android_4.2.3.1_ios_4.3.1.1"}, + {"ADMOB_NETWORK", "android_19.3.0.3_ios_7.65.0.0"}, + {"CHARTBOOST_NETWORK", "android_8.1.0.7_ios_8.2.1.3"}, + {"FACEBOOK_MEDIATE", "android_6.0.0.1_ios_6.0.0.3"}, + {"FYBER_NETWORK", "android_7.7.0.1_ios_7.6.4.1"}, + {"GOOGLE_AD_MANAGER_NETWORK", "android_19.3.0.3_ios_7.65.0.0"}, + {"INMOBI_NETWORK", "android_9.0.9.2_ios_9.0.7.9"}, + {"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"}, + {"VUNGLE_NETWORK", "android_6.7.1.2_ios_6.7.1.3"}, + {"YANDEX_NETWORK", "android_2.170.2_ios_2.18.0.1"} + }; + + /// + /// Checks if a new version of the plugin is available and prompts the user to update if one is available. + /// + public static void Update() + { + var now = (int) (DateTime.UtcNow - EpochTime).TotalSeconds; + if (EditorPrefs.HasKey(KeyLastUpdateCheckTime)) + { + var elapsedTime = now - EditorPrefs.GetInt(KeyLastUpdateCheckTime); + + // Check if we have checked for a new version in the last 24 hrs and skip update if we have. + if (elapsedTime < SecondsInADay) return; + } + + // 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 => + { + if (data == null) return; + + ShowPluginUpdateDialogIfNeeded(data); + ShowNetworkAdaptersUpdateDialogIfNeeded(data.MediatedNetworks); + ShowGoogleNetworkAdaptersUpdateDialogIfNeeded(data.MediatedNetworks); + })); + } + + private static void ShowPluginUpdateDialogIfNeeded(PluginData data) + { + // Check if publisher has disabled auto update. + if (!EditorPrefs.GetBool(KeyAutoUpdateEnabled, true)) return; + + // Check if the current and latest version are the same or if the publisher is on a newer version (on beta). If so, skip update. + var comparison = data.AppLovinMax.CurrentToLatestVersionComparisonResult; + if (comparison == MaxSdkUtils.VersionComparisonResult.Equal || comparison == MaxSdkUtils.VersionComparisonResult.Greater) return; + + // A new version of the plugin is available. Show a dialog to the publisher. + var option = EditorUtility.DisplayDialogComplex( + "AppLovin MAX Plugin Update", + "A new version of AppLovin MAX plugin is available for download. Update now?", + "Download", + "Not Now", + "Don't Ask Again"); + + if (option == 0) // Download + { + MaxSdkLogger.UserDebug("Downloading plugin..."); + AppLovinIntegrationManager.downloadPluginProgressCallback = AppLovinIntegrationManagerWindow.OnDownloadPluginProgress; + AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.DownloadPlugin(data.AppLovinMax)); + } + else if (option == 1) // Not Now + { + // Do nothing + MaxSdkLogger.UserDebug("Update postponed."); + } + else if (option == 2) // Don't Ask Again + { + MaxSdkLogger.UserDebug("Auto Update disabled. You can enable it again from the AppLovin Integration Manager"); + EditorPrefs.SetBool(KeyAutoUpdateEnabled, false); + } + } + + private static void ShowNetworkAdaptersUpdateDialogIfNeeded(Network[] networks) + { + var networksToUpdate = networks.Where(network => network.RequiresUpdate).ToList(); + + // If all networks are above the required version, do nothing. + if (networksToUpdate.Count <= 0) return; + + // We found a few adapters that are not compatible with the current SDK, show alert. + var message = "The following network adapters are not compatible with the current version of AppLovin MAX Plugin:\n"; + foreach (var networkName in networksToUpdate) + { + message += "\n- "; + message += networkName.DisplayName + " (Requires " + MinAdapterVersions[networkName.Name] + " or newer)"; + } + + message += "\n\nPlease update them to the latest versions to avoid any issues."; + + AppLovinIntegrationManager.ShowBuildFailureDialog(message); + } + + private static void ShowGoogleNetworkAdaptersUpdateDialogIfNeeded(Network[] networks) + { + // AdMob and GAM use the same SDKs so their adapters should use the same underlying SDK version. + var googleNetwork = networks.FirstOrDefault(network => network.Name.Equals("ADMOB_NETWORK")); + var googleAdManagerNetwork = networks.FirstOrDefault(network => network.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")); + + // If both AdMob and GAM are not integrated, do nothing. + if (googleNetwork == null || string.IsNullOrEmpty(googleNetwork.CurrentVersions.Unity) || + googleAdManagerNetwork == null || string.IsNullOrEmpty(googleAdManagerNetwork.CurrentVersions.Unity)) return; + + var isAndroidVersionCompatible = GoogleNetworkAdaptersCompatible(googleNetwork.CurrentVersions.Android, googleAdManagerNetwork.CurrentVersions.Android, "19.8.0.0"); + var isIosVersionCompatible = GoogleNetworkAdaptersCompatible(googleNetwork.CurrentVersions.Ios, googleAdManagerNetwork.CurrentVersions.Ios, "8.0.0.0"); + + if (isAndroidVersionCompatible && isIosVersionCompatible) return; + + var message = "You may see unexpected errors if you use different versions of the AdMob and Google Ad Manager adapter SDKs. " + + "AdMob and Google Ad Manager share the same SDKs.\n\n" + + "You can be sure that you are using the same SDK for both if the first three numbers in each adapter version match."; + + 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); + var googleAdManagerResult = MaxSdkUtils.CompareVersions(googleAdManagerVersion, breakingVersion); + + // If one is less than the breaking version and the other is not, they are not compatible. + if (googleResult == MaxSdkUtils.VersionComparisonResult.Lesser && + googleAdManagerResult != MaxSdkUtils.VersionComparisonResult.Lesser) return false; + + if (googleAdManagerResult == MaxSdkUtils.VersionComparisonResult.Lesser && + googleResult != MaxSdkUtils.VersionComparisonResult.Lesser) return false; + + return true; + } + } +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta new file mode 100644 index 0000000..33f843c --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: cad9b94a708924ff0a04401d8fe8f91e +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs new file mode 100644 index 0000000..c9cd21f --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs @@ -0,0 +1,94 @@ +// +// AppLovinBuildPostProcessor.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 10/30/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_IOS || UNITY_IPHONE + +using System.Diagnostics; +using System.IO; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// A helper class to run command line tools. + /// + /// TODO: Currently only supports shell (Linux). Add support for Windows machines. + /// + public class AppLovinCommandLine + { + /// + /// Result obtained by running a command line command. + /// + public class Result + { + /// + /// Standard output stream from command line. + /// + public string StandardOutput; + + /// + /// Standard error stream from command line. + /// + public string StandardError; + + /// + /// Exit code returned from command line. + /// + public int ExitCode; + + /// + /// The description of the result that can be used for error logging. + /// + public string Message; + } + + /// + /// Runs a command line tool using the provided and . + /// + /// The tool path to run + /// The arguments to be passed to the command line tool + /// The directory from which to run this command. + /// + public static Result Run(string toolPath, string arguments, string workingDirectory) + { + var stdoutFileName = Path.GetTempFileName(); + var stderrFileName = Path.GetTempFileName(); + + var process = new Process(); + process.StartInfo.UseShellExecute = true; + process.StartInfo.CreateNoWindow = false; + process.StartInfo.RedirectStandardInput = false; + process.StartInfo.RedirectStandardOutput = false; + process.StartInfo.RedirectStandardError = false; + + process.StartInfo.WorkingDirectory = workingDirectory; + process.StartInfo.FileName = "bash"; + process.StartInfo.Arguments = string.Format("-l -c '\"{0}\" {1} 1> {2} 2> {3}'", toolPath, arguments, stdoutFileName, stderrFileName); + process.Start(); + + process.WaitForExit(); + + var stdout = File.ReadAllText(stdoutFileName); + var stderr = File.ReadAllText(stderrFileName); + + File.Delete(stdoutFileName); + File.Delete(stderrFileName); + + var result = new Result(); + result.StandardOutput = stdout; + result.StandardError = stderr; + result.ExitCode = process.ExitCode; + + var messagePrefix = result.ExitCode == 0 ? "Command executed successfully" : "Failed to run command"; + result.Message = string.Format("{0}: '{1} {2}'\nstdout: {3}\nstderr: {4}\nExit code: {5}", messagePrefix, toolPath, arguments, stdout, stderr, process.ExitCode); + + return result; + } + } +} + +#endif diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta new file mode 100644 index 0000000..8b9aea2 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 869a2cef2a7a64292929ad064f924d02 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs new file mode 100644 index 0000000..75f359a --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs @@ -0,0 +1,75 @@ +// +// 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/AppLovinDownloadHandler.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs.meta new file mode 100644 index 0000000..b6e7d3c --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 4ed678026df674e9d8df1cd02e2469e4 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinDownloadHandler.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs new file mode 100644 index 0000000..f5be939 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs @@ -0,0 +1,91 @@ +// +// AppLovinEditorCoroutine.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 7/25/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using System.Collections; +using System.Collections.Generic; +using UnityEditor; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// A coroutine that can update based on editor application update. + /// + public class AppLovinEditorCoroutine + { + /// + /// Keeps track of the coroutine currently running. + /// + private IEnumerator enumerator; + + /// + /// Keeps track of coroutines that have yielded to the current enumerator. + /// + private readonly List history = new List(); + + private AppLovinEditorCoroutine(IEnumerator enumerator) + { + this.enumerator = enumerator; + } + + /// + /// Creates and starts a coroutine. + /// + /// The coroutine to be started + /// The coroutine that has been started. + public static AppLovinEditorCoroutine StartCoroutine(IEnumerator enumerator) + { + var coroutine = new AppLovinEditorCoroutine(enumerator); + coroutine.Start(); + return coroutine; + } + + private void Start() + { + EditorApplication.update += OnEditorUpdate; + } + + /// + /// Stops the coroutine. + /// + public void Stop() + { + if (EditorApplication.update == null) return; + + EditorApplication.update -= OnEditorUpdate; + } + + private void OnEditorUpdate() + { + if (enumerator.MoveNext()) + { + // If there is a coroutine to yield for inside the coroutine, add the initial one to history and continue the second one + if (enumerator.Current is IEnumerator) + { + history.Add(enumerator); + enumerator = (IEnumerator) enumerator.Current; + } + } + else + { + // Current coroutine has ended, check if we have more coroutines in history to be run. + if (history.Count == 0) + { + // No more coroutines to run, stop updating. + Stop(); + } + // Step out and finish the code in the coroutine that yielded to it + else + { + var index = history.Count - 1; + enumerator = history[index]; + history.RemoveAt(index); + } + } + } + } +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta new file mode 100644 index 0000000..8c0e60e --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 3c817f90804464e0b85d008d27c91f9e +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs new file mode 100644 index 0000000..1b328e1 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs @@ -0,0 +1,814 @@ +// +// MaxIntegrationManager.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 6/1/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; +using VersionComparisonResult = MaxSdkUtils.VersionComparisonResult; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + [Serializable] + public class PluginData + { + public Network AppLovinMax; + public Network[] MediatedNetworks; + } + + [Serializable] + public class Network + { + // + // Sample network data: + // + // { + // "Name": "adcolony", + // "DisplayName": "AdColony", + // "DownloadUrl": "https://bintray.com/applovin/Unity-Mediation-Packages/download_file?file_path=AppLovin-AdColony-Adapters-Android-3.3.10.1-iOS-3.3.7.2.unitypackage", + // "PluginFileName": "AppLovin-AdColony-Adapters-Android-3.3.10.1-iOS-3.3.7.2.unitypackage", + // "DependenciesFilePath": "MaxSdk/Mediation/AdColony/Editor/Dependencies.xml", + // "LatestVersions" : { + // "Unity": "android_3.3.10.1_ios_3.3.7.2", + // "Android": "3.3.10.1", + // "Ios": "3.3.7.2" + // } + // } + // + + public string Name; + public string DisplayName; + public string DownloadUrl; + public string DependenciesFilePath; + public string[] PluginFilePaths; + public Versions LatestVersions; + [NonSerialized] public Versions CurrentVersions; + [NonSerialized] public VersionComparisonResult CurrentToLatestVersionComparisonResult = VersionComparisonResult.Lesser; + [NonSerialized] public bool RequiresUpdate; + } + + /// + /// A helper data class used to get current versions from Dependency.xml files. + /// + [Serializable] + public class Versions + { + public string Unity; + public string Android; + public string Ios; + + public override bool Equals(object value) + { + var versions = value as Versions; + + return versions != null + && Unity.Equals(versions.Unity) + && (Android == null || Android.Equals(versions.Android)) + && (Ios == null || Ios.Equals(versions.Ios)); + } + + public bool HasEqualSdkVersions(Versions versions) + { + return versions != null + && AdapterSdkVersion(Android).Equals(AdapterSdkVersion(versions.Android)) + && AdapterSdkVersion(Ios).Equals(AdapterSdkVersion(versions.Ios)); + } + + public override int GetHashCode() + { + return new {Unity, Android, Ios}.GetHashCode(); + } + + private static string AdapterSdkVersion(string adapterVersion) + { + var index = adapterVersion.LastIndexOf("."); + return index > 0 ? adapterVersion.Substring(0, index) : adapterVersion; + } + } + + /// + /// A manager class for MAX integration manager window. + /// + /// TODO: Decide if we should namespace these classes. + /// + public class AppLovinIntegrationManager + { + /// + /// Delegate to be called when downloading a plugin with the progress percentage. + /// + /// The name of the plugin being downloaded. + /// Percentage downloaded. + /// Whether or not the download is complete. + public delegate void DownloadPluginProgressCallback(string pluginName, float progress, bool done); + + /// + /// Delegate to be called when a plugin package is imported. + /// + /// The network data for which the package is imported. + public delegate void ImportPackageCompletedCallback(Network network); + + private static readonly AppLovinIntegrationManager instance = new AppLovinIntegrationManager(); + + public static readonly string GradleTemplatePath = Path.Combine("Assets/Plugins/Android", "mainTemplate.gradle"); + public static readonly string DefaultPluginExportPath = Path.Combine("Assets", "MaxSdk"); + private const string MaxSdkAssetExportPath = "MaxSdk/Scripts/MaxSdk.cs"; + + /// + /// Some publishers might re-export our plugin via Unity Package Manager and the plugin will not be under the Assets folder. This means that the mediation adapters, settings files should not be moved to the packages folder, + /// since they get overridden when the package is updated. These are the files that should not be moved, if the plugin is not under the Assets/ folder. + /// + /// Note: When we distribute the plugin via Unity Package Manager, we need to distribute the adapters as separate packages, and the adapters won't be in the MaxSdk folder. So we need to take that into account. + /// + private static readonly List PluginPathsToIgnoreMoveWhenPluginOutsideAssetsDirectory = new List + { + "MaxSdk/Mediation", + "MaxSdk/Mediation.meta", + "MaxSdk/Resources.meta", + AppLovinSettings.SettingsExportPath, + AppLovinSettings.SettingsExportPath + ".meta" + }; + + private static string externalDependencyManagerVersion; + + public static DownloadPluginProgressCallback downloadPluginProgressCallback; + public static ImportPackageCompletedCallback importPackageCompletedCallback; + + private UnityWebRequest webRequest; + private Network importingNetwork; + + /// + /// An Instance of the Integration manager. + /// + public static AppLovinIntegrationManager Instance + { + get { return instance; } + } + + /// + /// The parent directory path where the MaxSdk plugin directory is placed. + /// + public static string PluginParentDirectory + { + get + { + // Search for the asset with the default exported path first, In most cases, we should be able to find the asset. + // In some cases where we don't, use the platform specific export path to search for the asset (in case of migrating a project from Windows to Mac or vice versa). + var maxSdkScriptAssetPath = MaxSdkUtils.GetAssetPathForExportPath(MaxSdkAssetExportPath); + + // maxSdkScriptAssetPath will always have AltDirectorySeparatorChar (/) as the path separator. Convert to platform specific path. + return maxSdkScriptAssetPath.Replace(MaxSdkAssetExportPath, "") + .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + } + + /// + /// When the base plugin is outside the Assets/ directory, the mediation plugin files are still imported to the default location under Assets/. + /// Returns the parent directory where the mediation adapter plugins are imported. + /// + public static string MediationSpecificPluginParentDirectory + { + get { return IsPluginOutsideAssetsDirectory ? "Assets" : PluginParentDirectory; } + } + + /// + /// 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"); } +// } + + + /// + /// Whether or not gradle build system is enabled. + /// + public static bool GradleBuildEnabled + { + get { return GetEditorUserBuildSetting("androidBuildSystem", "").ToString().Equals("Gradle"); } + } + + /// + /// Whether or not Gradle template is enabled. + /// + public static bool GradleTemplateEnabled + { + get { return GradleBuildEnabled && File.Exists(GradleTemplatePath); } + } + + /// + /// Whether or not the Quality Service settings can be processed which requires Gradle template enabled or Unity IDE newer than version 2018_2. + /// + public static bool CanProcessAndroidQualityServiceSettings + { + get { return GradleTemplateEnabled || (GradleBuildEnabled && IsUnity2018_2OrNewer()); } + } + + /// + /// The External Dependency Manager version obtained dynamically. + /// + public static string ExternalDependencyManagerVersion + { + get + { + if (!string.IsNullOrEmpty(externalDependencyManagerVersion)) return externalDependencyManagerVersion; + + try + { + var versionHandlerVersionNumberType = Type.GetType("Google.VersionHandlerVersionNumber, Google.VersionHandlerImpl"); + externalDependencyManagerVersion = versionHandlerVersionNumberType.GetProperty("Value").GetValue(null, null).ToString(); + } +#pragma warning disable 0168 + catch (Exception ignored) +#pragma warning restore 0168 + { + externalDependencyManagerVersion = "Failed to get version."; + } + + return externalDependencyManagerVersion; + } + } + + private AppLovinIntegrationManager() + { + // Add asset import callbacks. + AssetDatabase.importPackageCompleted += packageName => + { + if (!IsImportingNetwork(packageName)) return; + + var pluginParentDir = PluginParentDirectory; + var isPluginOutsideAssetsDir = IsPluginOutsideAssetsDirectory; + MovePluginFilesIfNeeded(pluginParentDir, isPluginOutsideAssetsDir); + AddLabelsToAssetsIfNeeded(pluginParentDir, isPluginOutsideAssetsDir); + AssetDatabase.Refresh(); + + CallImportPackageCompletedCallback(importingNetwork); + importingNetwork = null; + }; + + AssetDatabase.importPackageCancelled += packageName => + { + if (!IsImportingNetwork(packageName)) return; + + MaxSdkLogger.UserDebug("Package import cancelled."); + importingNetwork = null; + }; + + AssetDatabase.importPackageFailed += (packageName, errorMessage) => + { + if (!IsImportingNetwork(packageName)) return; + + MaxSdkLogger.UserError(errorMessage); + importingNetwork = null; + }; + } + + static AppLovinIntegrationManager() { } + + /// + /// Loads the plugin data to be display by integration manager window. + /// + /// 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()); + 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) +#endif + { + callback(null); + } + else + { + PluginData pluginData; + try + { + pluginData = JsonUtility.FromJson(www.downloadHandler.text); + } + catch (Exception exception) + { + Console.WriteLine(exception); + pluginData = null; + } + + if (pluginData != null) + { + // Get current version of the plugin + var appLovinMax = pluginData.AppLovinMax; + UpdateCurrentVersions(appLovinMax, PluginParentDirectory); + + // Get current versions for all the mediation networks. + var mediationPluginParentDirectory = MediationSpecificPluginParentDirectory; + foreach (var network in pluginData.MediatedNetworks) + { + UpdateCurrentVersions(network, mediationPluginParentDirectory); + } + } + + callback(pluginData); + } + } + } + + /// + /// Updates the CurrentVersion fields for a given network data object. + /// + /// Network for which to update the current versions. + /// The parent directory of where the mediation adapter plugins are imported to. + public static void UpdateCurrentVersions(Network network, string mediationPluginParentDirectory) + { + var dependencyFilePath = Path.Combine(mediationPluginParentDirectory, network.DependenciesFilePath); + var currentVersions = GetCurrentVersions(dependencyFilePath); + + network.CurrentVersions = currentVersions; + + // If AppLovin mediation plugin, get the version from MaxSdk and the latest and current version comparison. + if (network.Name.Equals("APPLOVIN_NETWORK")) + { + network.CurrentVersions.Unity = MaxSdk.Version; + + var unityVersionComparison = MaxSdkUtils.CompareVersions(network.CurrentVersions.Unity, network.LatestVersions.Unity); + var androidVersionComparison = MaxSdkUtils.CompareVersions(network.CurrentVersions.Android, network.LatestVersions.Android); + var iosVersionComparison = MaxSdkUtils.CompareVersions(network.CurrentVersions.Ios, network.LatestVersions.Ios); + + // Overall version is same if all the current and latest (from db) versions are same. + if (unityVersionComparison == VersionComparisonResult.Equal && + androidVersionComparison == VersionComparisonResult.Equal && + iosVersionComparison == VersionComparisonResult.Equal) + { + network.CurrentToLatestVersionComparisonResult = VersionComparisonResult.Equal; + } + // One of the installed versions is newer than the latest versions which means that the publisher is on a beta version. + else if (unityVersionComparison == VersionComparisonResult.Greater || + androidVersionComparison == VersionComparisonResult.Greater || + iosVersionComparison == VersionComparisonResult.Greater) + { + network.CurrentToLatestVersionComparisonResult = VersionComparisonResult.Greater; + } + // We have a new version available if all Android, iOS and Unity has a newer version available in db. + else + { + network.CurrentToLatestVersionComparisonResult = VersionComparisonResult.Lesser; + } + } + // For all other mediation adapters, get the version comparison using their Unity versions. + else + { + // If adapter is indeed installed, compare the current (installed) and the latest (from db) versions, so that we can determine if the publisher is on an older, current or a newer version of the adapter. + // If the publisher is on a newer version of the adapter than the db version, that means they are on a beta version. + if (!string.IsNullOrEmpty(currentVersions.Unity)) + { + network.CurrentToLatestVersionComparisonResult = MaxSdkUtils.CompareUnityMediationVersions(currentVersions.Unity, network.LatestVersions.Unity); + } + + if (!string.IsNullOrEmpty(network.CurrentVersions.Unity) && AppLovinAutoUpdater.MinAdapterVersions.ContainsKey(network.Name)) + { + var comparisonResult = MaxSdkUtils.CompareUnityMediationVersions(network.CurrentVersions.Unity, AppLovinAutoUpdater.MinAdapterVersions[network.Name]); + // Requires update if current version is lower than the min required version. + network.RequiresUpdate = comparisonResult < 0; + } + else + { + // Reset value so that the Integration manager can hide the alert icon once adapter is updated. + network.RequiresUpdate = false; + } + } + } + + /// + /// Downloads the plugin file for a given network. + /// + /// Network for which to download the current version. + /// Whether or not to show the import window when downloading. Defaults to true. + /// + 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. + CallDownloadPluginProgressCallback(network.DisplayName, operation.progress, operation.isDone); + } + +#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) +#endif + { + MaxSdkLogger.UserError(webRequest.error); + } + else + { + importingNetwork = network; + AssetDatabase.ImportPackage(path, showImport); + } + + webRequest.Dispose(); + webRequest = null; + } + + /// + /// Cancels the plugin download if one is in progress. + /// + public void CancelDownload() + { + if (webRequest == null) return; + + webRequest.Abort(); + } + + /// + /// Shows a dialog to the user with the given message and logs the error message to console. + /// + /// The failure message to be shown to the user. + public static void ShowBuildFailureDialog(string message) + { + var openIntegrationManager = EditorUtility.DisplayDialog("AppLovin MAX", message, "Open Integration Manager", "Dismiss"); + if (openIntegrationManager) + { + AppLovinIntegrationManagerWindow.ShowManager(); + } + + MaxSdkLogger.UserError(message); + } + + /// + /// Checks whether or not an adapter with the given version or newer exists. + /// + /// The name of the network (the root adapter folder name in "MaxSdk/Mediation/" folder. + /// The min adapter version to check for. Can be null if we want to check for any version. + /// true if an adapter with the min version is installed. + public static bool IsAdapterInstalled(string adapterName, string version = null) + { + var dependencyFilePath = MaxSdkUtils.GetAssetPathForExportPath("MaxSdk/Mediation/" + adapterName + "/Editor/Dependencies.xml"); + if (!File.Exists(dependencyFilePath)) return false; + + // If version is null, we just need the adapter installed. We don't have to check for a specific version. + if (version == null) return true; + + var currentVersion = AppLovinIntegrationManager.GetCurrentVersions(dependencyFilePath); + var iosVersionComparison = MaxSdkUtils.CompareVersions(currentVersion.Ios, version); + return iosVersionComparison != MaxSdkUtils.VersionComparisonResult.Lesser; + } + + #region Utility Methods + + /// + /// Gets the current versions for a given network's dependency file path. + /// + /// A dependency file path that from which to extract current versions. + /// Current versions of a given network's dependency file. + public static Versions GetCurrentVersions(string dependencyPath) + { + XDocument dependency; + try + { + dependency = XDocument.Load(dependencyPath); + } +#pragma warning disable 0168 + catch (IOException exception) +#pragma warning restore 0168 + { + // Couldn't find the dependencies file. The plugin is not installed. + return new Versions(); + } + + // + // + // + // + // + // + // + // + string androidVersion = null; + string iosVersion = null; + var dependenciesElement = dependency.Element("dependencies"); + if (dependenciesElement != null) + { + var androidPackages = dependenciesElement.Element("androidPackages"); + if (androidPackages != null) + { + var adapterPackage = androidPackages.Descendants().FirstOrDefault(element => element.Name.LocalName.Equals("androidPackage") + && element.FirstAttribute.Name.LocalName.Equals("spec") + && element.FirstAttribute.Value.StartsWith("com.applovin")); + if (adapterPackage != null) + { + androidVersion = adapterPackage.FirstAttribute.Value.Split(':').Last(); + // Hack alert: Some Android versions might have square brackets to force a specific version. Remove them if they are detected. + if (androidVersion.StartsWith("[")) + { + androidVersion = androidVersion.Trim('[', ']'); + } + } + } + + var iosPods = dependenciesElement.Element("iosPods"); + if (iosPods != null) + { + var adapterPod = iosPods.Descendants().FirstOrDefault(element => element.Name.LocalName.Equals("iosPod") + && element.FirstAttribute.Name.LocalName.Equals("name") + && element.FirstAttribute.Value.StartsWith("AppLovin")); + if (adapterPod != null) + { + iosVersion = adapterPod.Attributes().First(attribute => attribute.Name.LocalName.Equals("version")).Value; + } + } + } + + var currentVersions = new Versions(); + if (androidVersion != null && iosVersion != null) + { + currentVersions.Unity = string.Format("android_{0}_ios_{1}", androidVersion, iosVersion); + currentVersions.Android = androidVersion; + currentVersions.Ios = iosVersion; + } + else if (androidVersion != null) + { + currentVersions.Unity = string.Format("android_{0}", androidVersion); + currentVersions.Android = androidVersion; + } + else if (iosVersion != null) + { + currentVersions.Unity = string.Format("ios_{0}", iosVersion); + currentVersions.Ios = iosVersion; + } + + return currentVersions; + } + + /// + /// Checks whether or not the given package name is the currently importing package. + /// + /// The name of the package that needs to be checked. + /// true if the importing package matches the given package name. + private bool IsImportingNetwork(string packageName) + { + // Note: The pluginName doesn't have the '.unitypacakge' extension included in its name but the pluginFileName does. So using Contains instead of Equals. + 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. + /// + /// The MAX Unity plugin's parent directory. + /// Whether or not the plugin is outside the Assets directory. + public static void AddLabelsToAssetsIfNeeded(string pluginParentDir, bool isPluginOutsideAssetsDirectory) + { + if (isPluginOutsideAssetsDirectory) + { + var defaultPluginLocation = Path.Combine("Assets", "MaxSdk"); + if (Directory.Exists(defaultPluginLocation)) + { + AddLabelsToAssets(defaultPluginLocation, "Assets"); + } + } + + var pluginDir = Path.Combine(pluginParentDir, "MaxSdk"); + AddLabelsToAssets(pluginDir, pluginParentDir); + } + + private static void AddLabelsToAssets(string directoryPath, string pluginParentDir) + { + var files = Directory.GetFiles(directoryPath); + foreach (var file in files) + { + if (file.EndsWith(".meta")) continue; + + UpdateAssetLabelsIfNeeded(file, pluginParentDir); + } + + var directories = Directory.GetDirectories(directoryPath); + foreach (var directory in directories) + { + // Add labels to this directory asset. + UpdateAssetLabelsIfNeeded(directory, pluginParentDir); + + // Recursively add labels to all files under this directory. + AddLabelsToAssets(directory, pluginParentDir); + } + } + + private static void UpdateAssetLabelsIfNeeded(string assetPath, string pluginParentDir) + { + var asset = AssetDatabase.LoadAssetAtPath(assetPath); + var labels = AssetDatabase.GetLabels(asset); + + var labelsToAdd = labels.ToList(); + var didAddLabels = false; + if (!labels.Contains("al_max")) + { + labelsToAdd.Add("al_max"); + didAddLabels = true; + } + + var exportPathLabel = "al_max_export_path-" + assetPath.Replace(pluginParentDir, "").Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + if (!labels.Contains(exportPathLabel)) + { + labelsToAdd.Add(exportPathLabel); + didAddLabels = true; + } + + // We only need to set the labels if they changed. + if (!didAddLabels) return; + + AssetDatabase.SetLabels(asset, labelsToAdd.ToArray()); + } + + /// + /// Moves the imported plugin files to the MaxSdk directory if the publisher has moved the plugin to a different directory. This is a failsafe for when some plugin files are not imported to the new location. + /// + /// True if the adapters have been moved. + public static bool MovePluginFilesIfNeeded(string pluginParentDirectory, bool isPluginOutsideAssetsDirectory) + { + var pluginDir = Path.Combine(pluginParentDirectory, "MaxSdk"); + + // Check if the user has moved the Plugin and if new assets have been imported to the default directory. + if (DefaultPluginExportPath.Equals(pluginDir) || !Directory.Exists(DefaultPluginExportPath)) return false; + + MovePluginFiles(DefaultPluginExportPath, pluginDir, isPluginOutsideAssetsDirectory); + if (!isPluginOutsideAssetsDirectory) + { + FileUtil.DeleteFileOrDirectory(DefaultPluginExportPath + ".meta"); + } + + AssetDatabase.Refresh(); + return true; + } + + /// + /// A helper function to move all the files recursively from the default plugin dir to a custom location the publisher moved the plugin to. + /// + private static void MovePluginFiles(string fromDirectory, string pluginRoot, bool isPluginOutsideAssetsDirectory) + { + var files = Directory.GetFiles(fromDirectory); + foreach (var file in files) + { + // We have to ignore some files, if the plugin is outside the Assets/ directory. + if (isPluginOutsideAssetsDirectory && PluginPathsToIgnoreMoveWhenPluginOutsideAssetsDirectory.Any(pluginPathsToIgnore => file.Contains(pluginPathsToIgnore))) continue; + + // Check if the destination folder exists and create it if it doesn't exist + var parentDirectory = Path.GetDirectoryName(file); + var destinationDirectoryPath = parentDirectory.Replace(DefaultPluginExportPath, pluginRoot); + if (!Directory.Exists(destinationDirectoryPath)) + { + Directory.CreateDirectory(destinationDirectoryPath); + } + + // If the meta file is of a folder asset and doesn't have labels (it is auto generated by Unity), just delete it. + if (IsAutoGeneratedFolderMetaFile(file)) + { + FileUtil.DeleteFileOrDirectory(file); + continue; + } + + var destinationPath = file.Replace(DefaultPluginExportPath, pluginRoot); + + // Check if the file is already present at the destination path and delete it. + if (File.Exists(destinationPath)) + { + FileUtil.DeleteFileOrDirectory(destinationPath); + } + + FileUtil.MoveFileOrDirectory(file, destinationPath); + } + + var directories = Directory.GetDirectories(fromDirectory); + foreach (var directory in directories) + { + // We might have to ignore some directories, if the plugin is outside the Assets/ directory. + if (isPluginOutsideAssetsDirectory && PluginPathsToIgnoreMoveWhenPluginOutsideAssetsDirectory.Any(pluginPathsToIgnore => directory.Contains(pluginPathsToIgnore))) continue; + + MovePluginFiles(directory, pluginRoot, isPluginOutsideAssetsDirectory); + } + + if (!isPluginOutsideAssetsDirectory) + { + FileUtil.DeleteFileOrDirectory(fromDirectory); + } + } + + private static bool IsAutoGeneratedFolderMetaFile(string assetPath) + { + // Check if it is a meta file. + if (!assetPath.EndsWith(".meta")) return false; + + var lines = File.ReadAllLines(assetPath); + var isFolderAsset = false; + var hasLabels = false; + foreach (var line in lines) + { + if (line.Contains("folderAsset: yes")) + { + isFolderAsset = true; + } + + if (line.Contains("labels:")) + { + hasLabels = true; + } + } + + // If it is a folder asset and doesn't have a label, the meta file is auto generated by + return isFolderAsset && !hasLabels; + } + + private static void CallDownloadPluginProgressCallback(string pluginName, float progress, bool isDone) + { + if (downloadPluginProgressCallback == null) return; + + downloadPluginProgressCallback(pluginName, progress, isDone); + } + + private static void CallImportPackageCompletedCallback(Network network) + { + if (importPackageCompletedCallback == null) return; + + importPackageCompletedCallback(network); + } + + private static object GetEditorUserBuildSetting(string name, object defaultValue) + { + var editorUserBuildSettingsType = typeof(EditorUserBuildSettings); + var property = editorUserBuildSettingsType.GetProperty(name); + if (property != null) + { + var value = property.GetValue(null, null); + if (value != null) return value; + } + + 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"; + } + + #endregion + } +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta new file mode 100644 index 0000000..b9938d2 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: da789f9f05f40451a9e20176746ee18d +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs new file mode 100644 index 0000000..59a3911 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs @@ -0,0 +1,1013 @@ +// +// MaxIntegrationManager.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 5/27/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using System; +using System.Collections; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using VersionComparisonResult = MaxSdkUtils.VersionComparisonResult; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public class AppLovinIntegrationManagerWindow : EditorWindow + { + private const string keyNewLocalizationsMarked = "com.applovin.new_localizations_marked_v0"; // Update the key version each time new localizations are added. + + private const string windowTitle = "AppLovin Integration Manager"; + + 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 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"; + private const string alertIconExportPath = "MaxSdk/Resources/Images/alert_icon.png"; + private const string warningIconExportPath = "MaxSdk/Resources/Images/warning_icon.png"; + + 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 Vector2 scrollPosition; + private static readonly Vector2 windowMinSize = new Vector2(750, 750); + private const float actionFieldWidth = 60f; + private const float upgradeAllButtonWidth = 80f; + private const float networkFieldMinWidth = 100f; + private const float versionFieldMinWidth = 190f; + private const float privacySettingLabelWidth = 250f; + private const float networkFieldWidthPercentage = 0.22f; + private const float versionFieldWidthPercentage = 0.36f; // There are two version fields. Each take 40% of the width, network field takes the remaining 20%. + private static float previousWindowWidth = windowMinSize.x; + private static GUILayoutOption networkWidthOption = GUILayout.Width(networkFieldMinWidth); + private static GUILayoutOption versionWidthOption = GUILayout.Width(versionFieldMinWidth); + + private static GUILayoutOption privacySettingFieldWidthOption = GUILayout.Width(400); + private static readonly GUILayoutOption fieldWidth = GUILayout.Width(actionFieldWidth); + private static readonly GUILayoutOption upgradeAllButtonFieldWidth = GUILayout.Width(upgradeAllButtonWidth); + + private static readonly Color darkModeTextColor = new Color(0.29f, 0.6f, 0.8f); + + private GUIStyle titleLabelStyle; + private GUIStyle headerLabelStyle; + private GUIStyle environmentValueStyle; + private GUIStyle wrapTextLabelStyle; + private GUIStyle linkLabelStyle; + private GUIStyle iconStyle; + + private PluginData pluginData; + private bool pluginDataLoadFailed; + private bool isPluginMoved; + private bool shouldShowGoogleWarning; + private bool networkButtonsEnabled = true; + + private AppLovinEditorCoroutine loadDataCoroutine; + private Texture2D uninstallIcon; + private Texture2D alertIcon; + private Texture2D warningIcon; + + public static void ShowManager() + { + var manager = GetWindow(utility: true, title: windowTitle, focus: true); + manager.minSize = windowMinSize; + } + + #region Editor Window Lifecyle Methods + + private void Awake() + { + titleLabelStyle = new GUIStyle(EditorStyles.label) + { + fontSize = 14, + fontStyle = FontStyle.Bold, + fixedHeight = 20 + }; + + headerLabelStyle = new GUIStyle(EditorStyles.label) + { + fontSize = 12, + fontStyle = FontStyle.Bold, + fixedHeight = 18 + }; + + environmentValueStyle = new GUIStyle(EditorStyles.label) + { + alignment = TextAnchor.MiddleRight + }; + + linkLabelStyle = new GUIStyle(EditorStyles.label) + { + wordWrap = true, + normal = {textColor = EditorGUIUtility.isProSkin ? darkModeTextColor : Color.blue} + }; + + wrapTextLabelStyle = new GUIStyle(EditorStyles.label) + { + wordWrap = true + }; + + iconStyle = new GUIStyle(EditorStyles.miniButton) + { + fixedWidth = 18, + fixedHeight = 18, + padding = new RectOffset(1, 1, 1, 1) + }; + + // Load uninstall icon texture. + var uninstallIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(uninstallIconExportPath)); + uninstallIcon = new Texture2D(0, 0, TextureFormat.RGBA32, false); // 1. Initial size doesn't matter here, will be automatically resized once the image asset is loaded. 2. Set mipChain to false, else the texture has a weird blurry effect. + uninstallIcon.LoadImage(uninstallIconData); + + // Load alert icon texture. + var alertIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(alertIconExportPath)); + alertIcon = new Texture2D(0, 0, TextureFormat.RGBA32, false); + alertIcon.LoadImage(alertIconData); + + // Load warning icon texture. + var warningIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(warningIconExportPath)); + warningIcon = new Texture2D(0, 0, TextureFormat.RGBA32, false); + warningIcon.LoadImage(warningIconData); + + var pluginPath = Path.Combine(AppLovinIntegrationManager.PluginParentDirectory, "MaxSdk"); + isPluginMoved = !AppLovinIntegrationManager.DefaultPluginExportPath.Equals(pluginPath); + } + + private void OnEnable() + { + AppLovinIntegrationManager.downloadPluginProgressCallback = OnDownloadPluginProgress; + + // 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) + { + AppLovinSettings.Instance.ConsentFlowEnabled = false; + } + + Load(); + } + + private void OnDisable() + { + if (loadDataCoroutine != null) + { + loadDataCoroutine.Stop(); + loadDataCoroutine = null; + } + + AppLovinIntegrationManager.Instance.CancelDownload(); + EditorUtility.ClearProgressBar(); + + // Saves the AppLovinSettings object if it has been changed. + AssetDatabase.SaveAssets(); + } + + private void OnGUI() + { + // OnGUI is called on each frame draw, so we don't want to do any unnecessary calculation if we can avoid it. So only calculate it when the width actually changed. + if (Math.Abs(previousWindowWidth - position.width) > 1) + { + previousWindowWidth = position.width; + CalculateFieldWidth(); + } + + using (var scrollView = new EditorGUILayout.ScrollViewScope(scrollPosition, false, false)) + { + scrollPosition = scrollView.scrollPosition; + + GUILayout.Space(5); + + // Draw AppLovin MAX plugin details + EditorGUILayout.LabelField("AppLovin MAX Plugin Details", titleLabelStyle); + + DrawPluginDetails(); + + // Draw mediated networks + using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandHeight(false))) + { + EditorGUILayout.LabelField("Mediated Networks", titleLabelStyle); + DrawUpgradeAllButton(); + } + + DrawMediatedNetworks(); + + // Draw AppLovin Quality Service settings + EditorGUILayout.LabelField("SDK Settings", titleLabelStyle); + DrawQualityServiceSettings(); + + EditorGUILayout.LabelField("Privacy Settings", titleLabelStyle); + DrawPrivacySettings(); + + EditorGUILayout.LabelField("Other Settings", titleLabelStyle); + DrawOtherSettings(); + + // Draw Unity environment details + EditorGUILayout.LabelField("Unity Environment Details", titleLabelStyle); + DrawUnityEnvironmentDetails(); + + // Draw documentation notes + EditorGUILayout.LabelField(new GUIContent(documentationNote), wrapTextLabelStyle); + if (GUILayout.Button(new GUIContent(documentationAdaptersLink), linkLabelStyle)) + { + Application.OpenURL(documentationAdaptersLink); + } + } + + if (GUI.changed) + { + AppLovinSettings.Instance.SaveAsync(); + AppLovinInternalSettings.Instance.Save(); + } + } + + #endregion + + #region UI Methods + + /// + /// Shows failure or loading screen based on whether or not plugin data failed to load. + /// + private void DrawEmptyPluginData() + { + GUILayout.Space(5); + + // Plugin data failed to load. Show error and retry button. + if (pluginDataLoadFailed) + { + GUILayout.Space(10); + GUILayout.BeginHorizontal(); + GUILayout.Space(5); + EditorGUILayout.LabelField("Failed to load plugin data. Please click retry or restart the integration manager.", titleLabelStyle); + if (GUILayout.Button("Retry", fieldWidth)) + { + pluginDataLoadFailed = false; + Load(); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + GUILayout.Space(10); + } + // Still loading, show loading label. + else + { + GUILayout.Space(10); + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + EditorGUILayout.LabelField("Loading data...", titleLabelStyle); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + GUILayout.Space(10); + } + + GUILayout.Space(5); + } + + /// + /// Draws AppLovin MAX plugin details. + /// + private void DrawPluginDetails() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + // Draw plugin version details + DrawHeaders("Platform", false); + + // Immediately after downloading and importing a plugin the entire IDE reloads and current versions can be null in that case. Will just show loading text in that case. + if (pluginData == null || pluginData.AppLovinMax.CurrentVersions == null) + { + DrawEmptyPluginData(); + } + else + { + var appLovinMax = pluginData.AppLovinMax; + // Check if a newer version is available to enable the upgrade button. + var upgradeButtonEnabled = appLovinMax.CurrentToLatestVersionComparisonResult == VersionComparisonResult.Lesser; + DrawPluginDetailRow("Unity 3D", appLovinMax.CurrentVersions.Unity, appLovinMax.LatestVersions.Unity); + DrawPluginDetailRow("Android", appLovinMax.CurrentVersions.Android, appLovinMax.LatestVersions.Android); + DrawPluginDetailRow("iOS", appLovinMax.CurrentVersions.Ios, appLovinMax.LatestVersions.Ios); + + // BeginHorizontal combined with FlexibleSpace makes sure that the button is centered horizontally. + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + + GUI.enabled = upgradeButtonEnabled; + if (GUILayout.Button(new GUIContent("Upgrade"), fieldWidth)) + { + AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.DownloadPlugin(appLovinMax)); + } + + GUI.enabled = true; + GUILayout.Space(5); + GUILayout.EndHorizontal(); + + 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); + GUILayout.EndHorizontal(); + } + + /// + /// Draws the headers for a table. + /// + private void DrawHeaders(string firstColumnTitle, bool drawAction) + { + using (new EditorGUILayout.HorizontalScope()) + { + GUILayout.Space(5); + EditorGUILayout.LabelField(firstColumnTitle, headerLabelStyle, networkWidthOption); + EditorGUILayout.LabelField("Current Version", headerLabelStyle, versionWidthOption); + GUILayout.Space(3); + EditorGUILayout.LabelField("Latest Version", headerLabelStyle, versionWidthOption); + GUILayout.Space(3); + if (drawAction) + { + GUILayout.FlexibleSpace(); + GUILayout.Button("Actions", headerLabelStyle, fieldWidth); + GUILayout.Space(5); + } + } + + GUILayout.Space(4); + } + + /// + /// Draws the platform specific version details for AppLovin MAX plugin. + /// + private void DrawPluginDetailRow(string platform, string currentVersion, string latestVersion) + { + using (new EditorGUILayout.HorizontalScope()) + { + GUILayout.Space(5); + EditorGUILayout.LabelField(new GUIContent(platform), networkWidthOption); + EditorGUILayout.LabelField(new GUIContent(currentVersion), versionWidthOption); + GUILayout.Space(3); + EditorGUILayout.LabelField(new GUIContent(latestVersion), versionWidthOption); + GUILayout.Space(3); + } + + GUILayout.Space(4); + } + + /// + /// Draws mediated network details table. + /// + private void DrawMediatedNetworks() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + DrawHeaders("Network", true); + + // Immediately after downloading and importing a plugin the entire IDE reloads and current versions can be null in that case. Will just show loading text in that case. + if (pluginData == null || pluginData.AppLovinMax.CurrentVersions == null) + { + DrawEmptyPluginData(); + } + else + { + var networks = pluginData.MediatedNetworks; + foreach (var network in networks) + { + DrawNetworkDetailRow(network); + } + + GUILayout.Space(10); + } + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + /// + /// Draws the network specific details for a given network. + /// + private void DrawNetworkDetailRow(Network network) + { + string action; + var currentVersion = network.CurrentVersions.Unity; + var latestVersion = network.LatestVersions.Unity; + bool isActionEnabled; + bool isInstalled; + if (string.IsNullOrEmpty(currentVersion)) + { + action = "Install"; + currentVersion = "Not Installed"; + isActionEnabled = true; + isInstalled = false; + } + else + { + isInstalled = true; + + var comparison = network.CurrentToLatestVersionComparisonResult; + // A newer version is available + if (comparison == VersionComparisonResult.Lesser) + { + action = "Upgrade"; + isActionEnabled = true; + } + // Current installed version is newer than latest version from DB (beta version) + else if (comparison == VersionComparisonResult.Greater) + { + action = "Installed"; + isActionEnabled = false; + } + // Already on the latest version + else + { + action = "Installed"; + isActionEnabled = false; + } + } + + GUILayout.Space(4); + using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandHeight(false))) + { + GUILayout.Space(5); + EditorGUILayout.LabelField(new GUIContent(network.DisplayName), networkWidthOption); + EditorGUILayout.LabelField(new GUIContent(currentVersion), versionWidthOption); + GUILayout.Space(3); + EditorGUILayout.LabelField(new GUIContent(latestVersion), versionWidthOption); + GUILayout.Space(3); + GUILayout.FlexibleSpace(); + + if (network.RequiresUpdate) + { + GUILayout.Label(new GUIContent {image = alertIcon, tooltip = "Adapter not compatible, please update to the latest version."}, iconStyle); + } + else if ((network.Name.Equals("ADMOB_NETWORK") || network.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")) && shouldShowGoogleWarning) + { + GUILayout.Label(new GUIContent {image = warningIcon, tooltip = "You may see unexpected errors if you use different versions of the AdMob and Google Ad Manager adapter SDKs."}, iconStyle); + } + + GUI.enabled = networkButtonsEnabled && isActionEnabled; + if (GUILayout.Button(new GUIContent(action), fieldWidth)) + { + // Download the plugin. + AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.DownloadPlugin(network)); + } + + GUI.enabled = true; + GUILayout.Space(2); + + GUI.enabled = networkButtonsEnabled && isInstalled; + if (GUILayout.Button(new GUIContent {image = uninstallIcon, tooltip = "Uninstall"}, iconStyle)) + { + EditorUtility.DisplayProgressBar("Integration Manager", "Deleting " + network.Name + "...", 0.5f); + var pluginRoot = AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; + foreach (var pluginFilePath in network.PluginFilePaths) + { + FileUtil.DeleteFileOrDirectory(Path.Combine(pluginRoot, pluginFilePath)); + } + + AppLovinIntegrationManager.UpdateCurrentVersions(network, pluginRoot); + + // Refresh UI + AssetDatabase.Refresh(); + EditorUtility.ClearProgressBar(); + } + + GUI.enabled = true; + GUILayout.Space(5); + } + + if (isInstalled) + { + DrawGoogleAppIdTextBoxIfNeeded(network); + } + } + + private void DrawGoogleAppIdTextBoxIfNeeded(Network network) + { + // Custom integration for AdMob where the user can enter the Android and iOS App IDs. + if (network.Name.Equals("ADMOB_NETWORK")) + { + // Show only one set of text boxes if both ADMOB and GAM are installed + if (AppLovinIntegrationManager.IsAdapterInstalled("GoogleAdManager")) return; + + DrawGoogleAppIdTextBox(); + } + + // Custom integration for GAM where the user can enter the Android and iOS App IDs. + else if (network.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")) + { + DrawGoogleAppIdTextBox(); + } + } + + /// + /// Draws the text box for GAM or ADMOB to input the App ID + /// + private void DrawGoogleAppIdTextBox() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(20); + using (new EditorGUILayout.VerticalScope("box")) + { + GUILayout.Space(2); + AppLovinSettings.Instance.AdMobAndroidAppId = DrawTextField("App ID (Android)", AppLovinSettings.Instance.AdMobAndroidAppId, networkWidthOption); + AppLovinSettings.Instance.AdMobIosAppId = DrawTextField("App ID (iOS)", AppLovinSettings.Instance.AdMobIosAppId, networkWidthOption); + } + + GUILayout.EndHorizontal(); + } + + /// + /// Draws the upgrade all button + /// + private void DrawUpgradeAllButton() + { + GUI.enabled = NetworksRequireUpgrade(); + if (GUILayout.Button(new GUIContent("Upgrade All"), upgradeAllButtonFieldWidth)) + { + AppLovinEditorCoroutine.StartCoroutine(UpgradeAllNetworks()); + } + + GUI.enabled = true; + GUILayout.Space(10); + } + + private void DrawQualityServiceSettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + GUILayout.Space(4); + if (!AppLovinIntegrationManager.CanProcessAndroidQualityServiceSettings) + { + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox(qualityServiceRequiresGradleBuildErrorMsg, MessageType.Warning); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + + GUILayout.Space(4); + } + + AppLovinSettings.Instance.SdkKey = DrawTextField("AppLovin SDK Key", AppLovinSettings.Instance.SdkKey, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + GUILayout.Button("You can find your SDK key here: ", wrapTextLabelStyle, GUILayout.Width(185)); // Setting a fixed width since Unity adds arbitrary padding at the end leaving a space between link and text. + if (GUILayout.Button(new GUIContent(appLovinSdkKeyLink), linkLabelStyle)) + { + Application.OpenURL(appLovinSdkKeyLink); + } + + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinSettings.Instance.QualityServiceEnabled = GUILayout.Toggle(AppLovinSettings.Instance.QualityServiceEnabled, " Enable MAX Ad Review"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + GUILayout.Space(4); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private string DrawTextField(string fieldTitle, string text, GUILayoutOption labelWidth, GUILayoutOption textFieldWidthOption = null, bool isTextFieldEditable = true) + { + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.LabelField(new GUIContent(fieldTitle), labelWidth); + GUILayout.Space(4); + if (isTextFieldEditable) + { + text = (textFieldWidthOption == null) ? GUILayout.TextField(text) : GUILayout.TextField(text, textFieldWidthOption); + } + else + { + if (textFieldWidthOption == null) + { + GUILayout.Label(text); + } + else + { + GUILayout.Label(text, textFieldWidthOption); + } + } + + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + return text; + } + + private void DrawPrivacySettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + var shouldDrawInternalSettings = AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager; + if (shouldDrawInternalSettings) + { + DrawConsentFlowSettings(); + } + else + { + DrawTermsFlowSettings(); + } + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private void DrawTermsFlowSettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinSettings.Instance.ConsentFlowEnabled = GUILayout.Toggle(AppLovinSettings.Instance.ConsentFlowEnabled, " Enable Terms Flow"); + GUILayout.FlexibleSpace(); + GUI.enabled = AppLovinSettings.Instance.ConsentFlowEnabled; + AppLovinSettings.Instance.ConsentFlowPlatform = (Platform) EditorGUILayout.Popup((int) AppLovinSettings.Instance.ConsentFlowPlatform, termsFlowPlatforms); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl = DrawTextField("Privacy Policy URL", AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl = DrawTextField("Terms of Service URL (optional)", AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionEn = DrawTextField("User Tracking Usage Description (iOS only)", AppLovinSettings.Instance.UserTrackingUsageDescriptionEn, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinSettings.Instance.UserTrackingUsageLocalizationEnabled = GUILayout.Toggle(AppLovinSettings.Instance.UserTrackingUsageLocalizationEnabled, " Localize User Tracking Usage Description (iOS only)"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + if (AppLovinSettings.Instance.UserTrackingUsageLocalizationEnabled) + { + AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHans = DrawTextField("Chinese, Simplified (zh-Hans)", AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHans, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHant = DrawTextField("Chinese, Traditional (zh-Hant)", AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHant, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); // TODO: Remove new mark for next release. + AppLovinSettings.Instance.UserTrackingUsageDescriptionFr = DrawTextField("French (fr)", AppLovinSettings.Instance.UserTrackingUsageDescriptionFr, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionDe = DrawTextField("German (de)", AppLovinSettings.Instance.UserTrackingUsageDescriptionDe, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionJa = DrawTextField("Japanese (ja)", AppLovinSettings.Instance.UserTrackingUsageDescriptionJa, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionKo = DrawTextField("Korean (ko)", AppLovinSettings.Instance.UserTrackingUsageDescriptionKo, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionEs = DrawTextField("Spanish (es)", AppLovinSettings.Instance.UserTrackingUsageDescriptionEs, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox("MAX may add more localized strings to this list in the future, which will set the default value of the User Tracking Usage Description string for more locales. If you are overriding these with your own custom translations, you may want to review this list whenever you upgrade the plugin to see if there are new entries you may want to customize.", MessageType.Info); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox("If you have your own implementation of InfoPlist.strings localization implementation, please use that instead. Using both at the same time may cause conflicts.", MessageType.Info); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + } + + GUI.enabled = true; + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + GUILayout.Button("Click the link below for more information about User Tracking Usage Description: ", wrapTextLabelStyle); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + if (GUILayout.Button(new GUIContent(userTrackingUsageDescriptionDocsLink), linkLabelStyle)) + { + Application.OpenURL(userTrackingUsageDescriptionDocsLink); + } + + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + } + + private void DrawConsentFlowSettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinInternalSettings.Instance.ConsentFlowEnabled = GUILayout.Toggle(AppLovinInternalSettings.Instance.ConsentFlowEnabled, " Enable Consent Flow"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + GUI.enabled = true; + + if (!AppLovinInternalSettings.Instance.ConsentFlowEnabled) return; + + 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); + EditorGUILayout.LabelField("iOS specific settings:", headerLabelStyle); + GUILayout.EndHorizontal(); + + var isEditableTextField = AppLovinInternalSettings.Instance.OverrideDefaultUserTrackingUsageDescriptions; + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinInternalSettings.Instance.OverrideDefaultUserTrackingUsageDescriptions = GUILayout.Toggle(AppLovinInternalSettings.Instance.OverrideDefaultUserTrackingUsageDescriptions, " Override Default User Tracking Usage Description"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + GUILayout.Space(4); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn = DrawTextField("User Tracking Usage Description", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinInternalSettings.Instance.UserTrackingUsageLocalizationEnabled = GUILayout.Toggle(AppLovinInternalSettings.Instance.UserTrackingUsageLocalizationEnabled, " Localize User Tracking Usage Description"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + if (AppLovinInternalSettings.Instance.UserTrackingUsageLocalizationEnabled) + { + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans = DrawTextField("Chinese, Simplified (zh-Hans)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant = DrawTextField("Chinese, Traditional (zh-Hant)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr = DrawTextField("French (fr)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe = DrawTextField("German (de)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa = DrawTextField("Japanese (ja)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo = DrawTextField("Korean (ko)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs = DrawTextField("Spanish (es)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox("If you have your own implementation of InfoPlist.strings localization implementation, please use that instead. Using both at the same time may cause conflicts.", MessageType.Info); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + } + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + GUILayout.Button("Click the link below for more information about User Tracking Usage Description: ", wrapTextLabelStyle); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + if (GUILayout.Button(new GUIContent(userTrackingUsageDescriptionDocsLink), linkLabelStyle)) + { + Application.OpenURL(userTrackingUsageDescriptionDocsLink); + } + + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + } + + private void DrawOtherSettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + GUILayout.Space(5); + AppLovinSettings.Instance.SetAttributionReportEndpoint = DrawOtherSettingsToggle(AppLovinSettings.Instance.SetAttributionReportEndpoint, " Set Advertising Attribution Report Endpoint in Info.plist (iOS only)"); + 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 + ); + EditorPrefs.SetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, verboseLoggingEnabled); + GUILayout.Space(5); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private bool DrawOtherSettingsToggle(bool value, string text) + { + using (new EditorGUILayout.HorizontalScope()) + { + GUILayout.Space(4); + var toggleValue = GUILayout.Toggle(value, text); + GUILayout.Space(4); + + return toggleValue; + } + } + + private void DrawUnityEnvironmentDetails() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + DrawUnityEnvironmentDetailRow("Unity Version", Application.unityVersion); + GUILayout.Space(5); + DrawUnityEnvironmentDetailRow("Platform", Application.platform.ToString()); + GUILayout.Space(5); + DrawUnityEnvironmentDetailRow("External Dependency Manager Version", AppLovinIntegrationManager.ExternalDependencyManagerVersion); + GUILayout.Space(5); + DrawUnityEnvironmentDetailRow("Gradle Template Enabled", AppLovinIntegrationManager.GradleTemplateEnabled.ToString()); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private void DrawUnityEnvironmentDetailRow(string key, string value) + { + using (new EditorGUILayout.HorizontalScope()) + { + GUILayout.Space(5); + EditorGUILayout.LabelField(key, GUILayout.Width(250)); + GUILayout.FlexibleSpace(); + EditorGUILayout.LabelField(value, environmentValueStyle); + GUILayout.Space(5); + } + } + + /// + /// Calculates the fields width based on the width of the window. + /// + private void CalculateFieldWidth() + { + var currentWidth = position.width; + var availableWidth = currentWidth - actionFieldWidth - 80; // NOTE: Magic number alert. This is the sum of all the spacing the fields and other UI elements. + var networkLabelWidth = Math.Max(networkFieldMinWidth, availableWidth * networkFieldWidthPercentage); + networkWidthOption = GUILayout.Width(networkLabelWidth); + + var versionLabelWidth = Math.Max(versionFieldMinWidth, availableWidth * versionFieldWidthPercentage); + versionWidthOption = GUILayout.Width(versionLabelWidth); + + const int textFieldOtherUiElementsWidth = 45; // NOTE: Magic number alert. This is the sum of all the spacing the fields and other UI elements. + var availableUserDescriptionTextFieldWidth = currentWidth - privacySettingLabelWidth - textFieldOtherUiElementsWidth; + privacySettingFieldWidthOption = GUILayout.Width(availableUserDescriptionTextFieldWidth); + } + + #endregion + + #region Utility Methods + + /// + /// Loads the plugin data to be displayed by this window. + /// + private void Load() + { + loadDataCoroutine = AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.LoadPluginData(data => + { + if (data == null) + { + pluginDataLoadFailed = true; + } + else + { + pluginData = data; + pluginDataLoadFailed = false; + + UpdateShouldShowGoogleWarningIfNeeded(); + } + + CalculateFieldWidth(); + Repaint(); + })); + } + + /// + /// Callback method that will be called with progress updates when the plugin is being downloaded. + /// + public static void OnDownloadPluginProgress(string pluginName, float progress, bool done) + { + // Download is complete. Clear progress bar. + if (done) + { + EditorUtility.ClearProgressBar(); + } + // Download is in progress, update progress bar. + else + { + if (EditorUtility.DisplayCancelableProgressBar(windowTitle, string.Format("Downloading {0} plugin...", pluginName), progress)) + { + AppLovinIntegrationManager.Instance.CancelDownload(); + EditorUtility.ClearProgressBar(); + } + } + } + + private void OnImportPackageCompleted(Network network) + { + var parentDirectory = network.Name.Equals("APPLOVIN_NETWORK") ? AppLovinIntegrationManager.PluginParentDirectory : AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; + AppLovinIntegrationManager.UpdateCurrentVersions(network, parentDirectory); + + UpdateShouldShowGoogleWarningIfNeeded(); + } + + private void UpdateShouldShowGoogleWarningIfNeeded() + { + if (pluginData == null) + { + shouldShowGoogleWarning = false; + return; + } + + var networks = pluginData.MediatedNetworks; + var googleNetwork = networks.FirstOrDefault(foundNetwork => foundNetwork.Name.Equals("ADMOB_NETWORK")); + var googleAdManagerNetwork = networks.FirstOrDefault(foundNetwork => foundNetwork.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")); + + if (googleNetwork != null && googleAdManagerNetwork != null && + !string.IsNullOrEmpty(googleNetwork.CurrentVersions.Unity) && !string.IsNullOrEmpty(googleAdManagerNetwork.CurrentVersions.Unity) && + !googleNetwork.CurrentVersions.HasEqualSdkVersions(googleAdManagerNetwork.CurrentVersions)) + { + shouldShowGoogleWarning = true; + } + else + { + shouldShowGoogleWarning = false; + } + } + + /// + /// Upgrades all outdated networks + /// + private IEnumerator UpgradeAllNetworks() + { + networkButtonsEnabled = false; + EditorApplication.LockReloadAssemblies(); + var networks = pluginData.MediatedNetworks; + foreach (var network in networks) + { + var comparison = network.CurrentToLatestVersionComparisonResult; + // A newer version is available + if (!string.IsNullOrEmpty(network.CurrentVersions.Unity) && comparison == VersionComparisonResult.Lesser) + { + yield return AppLovinIntegrationManager.Instance.DownloadPlugin(network, false); + } + } + + EditorApplication.UnlockReloadAssemblies(); + networkButtonsEnabled = true; + + // The pluginData becomes stale after the networks have been updated, and we should re-load it. + Load(); + } + + /// + /// Returns whether any network adapter needs to be upgraded + /// + private bool NetworksRequireUpgrade() + { + if (pluginData == null || pluginData.AppLovinMax.CurrentVersions == null) return false; + + var networks = pluginData.MediatedNetworks; + return networks.Any(network => !string.IsNullOrEmpty(network.CurrentVersions.Unity) && network.CurrentToLatestVersionComparisonResult == VersionComparisonResult.Lesser); + } + + #endregion + } +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta new file mode 100644 index 0000000..4163743 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 2bb13a4fb97554d838321056d4d1f81b +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs new file mode 100644 index 0000000..61962f3 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs @@ -0,0 +1,329 @@ +// +// AppLovinInternalSettigns.cs +// AppLovin User Engagement Unity Plugin +// +// Created by Santosh Bagadi on 9/15/22. +// Copyright © 2022 AppLovin. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// A representing the AppLovin internal settings that can be set in the Integration Manager Window. + /// + /// The scriptable object asset is saved under ProjectSettings as AppLovinInternalSettings.json. + /// + public class AppLovinInternalSettings : ScriptableObject + { + private static AppLovinInternalSettings instance; + + public const string DefaultUserTrackingDescriptionEn = "This uses device info for more personalized ads and content"; + public const string DefaultUserTrackingDescriptionDe = "Dies benutzt Gerätinformationen für relevantere Werbeinhalte"; + public const string DefaultUserTrackingDescriptionEs = "Esto utiliza la información del dispositivo para anuncios y contenido más personalizados"; + public const string DefaultUserTrackingDescriptionFr = "Cela permet d'utiliser les informations du téléphone pour afficher des contenus publicitaires plus pertinents."; + public const string DefaultUserTrackingDescriptionJa = "これはユーザーデータをもとに、より関連性の高い広告コンテンツをお客様に提供します"; + public const string DefaultUserTrackingDescriptionKo = "보다 개인화된 광고 및 콘텐츠를 위해 기기 정보를 사용합니다."; + public const string DefaultUserTrackingDescriptionZhHans = "我们使用设备信息来提供个性化的广告和内容。"; + public const string DefaultUserTrackingDescriptionZhHant = "我們使用設備信息來提供個性化的廣告和內容。"; + + [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 string userTrackingUsageDescriptionEn = string.Empty; + [SerializeField] private bool userTrackingUsageLocalizationEnabled; + [SerializeField] private string userTrackingUsageDescriptionDe = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionEs = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionFr = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionJa = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionKo = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionZhHans = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionZhHant = string.Empty; + + private const string SettingsFilePath = "ProjectSettings/AppLovinInternalSettings.json"; + + public static AppLovinInternalSettings Instance + { + get + { + if (instance != null) return instance; + + instance = CreateInstance(); + + var projectRootPath = Path.GetDirectoryName(Application.dataPath); + var settingsFilePath = Path.Combine(projectRootPath, SettingsFilePath); + if (!File.Exists(settingsFilePath)) + { + instance.Save(); + return instance; + } + + var settingsJson = File.ReadAllText(settingsFilePath); + if (string.IsNullOrEmpty(settingsJson)) + { + instance.Save(); + return instance; + } + + JsonUtility.FromJsonOverwrite(settingsJson, instance); + return instance; + } + } + + public void Save() + { + var settingsJson = JsonUtility.ToJson(instance); + try + { + var projectRootPath = Path.GetDirectoryName(Application.dataPath); + var settingsFilePath = Path.Combine(projectRootPath, SettingsFilePath); + File.WriteAllText(settingsFilePath, settingsJson); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to save internal settings."); + Console.WriteLine(exception); + } + } + + /// + /// Whether or not AppLovin Consent Flow is enabled. + /// + public bool ConsentFlowEnabled + { + get { return consentFlowEnabled; } + set + { + var previousValue = consentFlowEnabled; + consentFlowEnabled = value; + + if (value) + { + // If the value didn't change, we don't need to update anything. + if (previousValue) return; + + UserTrackingUsageDescriptionEn = DefaultUserTrackingDescriptionEn; + UserTrackingUsageLocalizationEnabled = true; + } + else + { + ConsentFlowPrivacyPolicyUrl = string.Empty; + ConsentFlowTermsOfServiceUrl = string.Empty; + UserTrackingUsageDescriptionEn = string.Empty; + UserTrackingUsageLocalizationEnabled = false; + OverrideDefaultUserTrackingUsageDescriptions = false; + ConsentFlowIncludeDefaultAdvertisingPartnerUrls = true; + ConsentFlowIncludeDefaultAnalyticsPartnerUrls = true; + } + } + } + + /// + /// A URL pointing to the Privacy Policy for the app to be shown when prompting the user for consent. + /// + public string ConsentFlowPrivacyPolicyUrl + { + get { return consentFlowPrivacyPolicyUrl; } + set { consentFlowPrivacyPolicyUrl = value; } + } + + /// + /// An optional URL pointing to the Terms of Service for the app to be shown when prompting the user for consent. + /// + public string ConsentFlowTermsOfServiceUrl + { + get { return consentFlowTermsOfServiceUrl; } + 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. + /// + public string UserTrackingUsageDescriptionEn + { + get { return userTrackingUsageDescriptionEn; } + set { userTrackingUsageDescriptionEn = value; } + } + + public bool OverrideDefaultUserTrackingUsageDescriptions + { + get { return overrideDefaultUserTrackingUsageDescriptions; } + set + { + var previousValue = overrideDefaultUserTrackingUsageDescriptions; + overrideDefaultUserTrackingUsageDescriptions = value; + + if (!value) + { + if (!previousValue) return; + + UserTrackingUsageDescriptionEn = DefaultUserTrackingDescriptionEn; + UserTrackingUsageDescriptionDe = DefaultUserTrackingDescriptionDe; + UserTrackingUsageDescriptionEs = DefaultUserTrackingDescriptionEs; + UserTrackingUsageDescriptionFr = DefaultUserTrackingDescriptionFr; + UserTrackingUsageDescriptionJa = DefaultUserTrackingDescriptionJa; + UserTrackingUsageDescriptionKo = DefaultUserTrackingDescriptionKo; + UserTrackingUsageDescriptionZhHans = DefaultUserTrackingDescriptionZhHans; + UserTrackingUsageDescriptionZhHant = DefaultUserTrackingDescriptionZhHant; + } + } + } + + /// + /// Whether or not to localize User Tracking Usage Description. + /// For more information see Apple's documentation. + /// + public bool UserTrackingUsageLocalizationEnabled + { + get { return userTrackingUsageLocalizationEnabled; } + set + { + var previousValue = userTrackingUsageLocalizationEnabled; + userTrackingUsageLocalizationEnabled = value; + + if (value) + { + // If the value didn't change, don't do anything + if (previousValue) return; + + // Don't set the default values if they are being overriden. + if (OverrideDefaultUserTrackingUsageDescriptions) return; + + UserTrackingUsageDescriptionDe = DefaultUserTrackingDescriptionDe; + UserTrackingUsageDescriptionEs = DefaultUserTrackingDescriptionEs; + UserTrackingUsageDescriptionFr = DefaultUserTrackingDescriptionFr; + UserTrackingUsageDescriptionJa = DefaultUserTrackingDescriptionJa; + UserTrackingUsageDescriptionKo = DefaultUserTrackingDescriptionKo; + UserTrackingUsageDescriptionZhHans = DefaultUserTrackingDescriptionZhHans; + UserTrackingUsageDescriptionZhHant = DefaultUserTrackingDescriptionZhHant; + } + else + { + UserTrackingUsageDescriptionDe = string.Empty; + UserTrackingUsageDescriptionEs = string.Empty; + UserTrackingUsageDescriptionFr = string.Empty; + UserTrackingUsageDescriptionJa = string.Empty; + UserTrackingUsageDescriptionKo = string.Empty; + UserTrackingUsageDescriptionZhHans = string.Empty; + UserTrackingUsageDescriptionZhHant = string.Empty; + } + } + } + + /// + /// A User Tracking Usage Description in German to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionDe + { + get { return userTrackingUsageDescriptionDe; } + set { userTrackingUsageDescriptionDe = value; } + } + + /// + /// A User Tracking Usage Description in Spanish to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionEs + { + get { return userTrackingUsageDescriptionEs; } + set { userTrackingUsageDescriptionEs = value; } + } + + /// + /// A User Tracking Usage Description in French to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionFr + { + get { return userTrackingUsageDescriptionFr; } + set { userTrackingUsageDescriptionFr = value; } + } + + /// + /// A User Tracking Usage Description in Japanese to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionJa + { + get { return userTrackingUsageDescriptionJa; } + set { userTrackingUsageDescriptionJa = value; } + } + + /// + /// A User Tracking Usage Description in Korean to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionKo + { + get { return userTrackingUsageDescriptionKo; } + set { userTrackingUsageDescriptionKo = value; } + } + + /// + /// A User Tracking Usage Description in Chinese (Simplified) to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionZhHans + { + get { return userTrackingUsageDescriptionZhHans; } + set { userTrackingUsageDescriptionZhHans = value; } + } + + /// + /// A User Tracking Usage Description in Chinese (Traditional) to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionZhHant + { + get { return userTrackingUsageDescriptionZhHant; } + set { userTrackingUsageDescriptionZhHant = value; } + } + } +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta new file mode 100644 index 0000000..80da2bf --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 5a9f7c32d2d9e41e89f201dfc8770b13 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup new file mode 100644 index 0000000..5d6574e --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup @@ -0,0 +1,60 @@ +// +// MaxMenuItems.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 5/27/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using UnityEditor; +using UnityEngine; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public class AppLovinMenuItems + { + /** + * The special characters at the end represent a shortcut for this action. + * + * % - ctrl on Windows, cmd on macOS + * # - shift + * & - alt + * + * So, (shift + cmd/ctrl + i) will launch the integration manager + */ + [MenuItem("AppLovin/Integration Manager %#i")] + private static void IntegrationManager() + { + ShowIntegrationManager(); + } + + [MenuItem("AppLovin/Documentation")] + private static void Documentation() + { + Application.OpenURL("https://dash.applovin.com/documentation/mediation/unity/getting-started"); + } + + [MenuItem("AppLovin/Contact Us")] + private static void ContactUs() + { + Application.OpenURL("https://www.applovin.com/contact/"); + } + + [MenuItem("AppLovin/About")] + private static void About() + { + Application.OpenURL("https://www.applovin.com/about/"); + } + + [MenuItem("Assets/AppLovin Integration Manager")] + private static void AssetsIntegrationManager() + { + ShowIntegrationManager(); + } + + private static void ShowIntegrationManager() + { + AppLovinIntegrationManagerWindow.ShowManager(); + } + } +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup.meta new file mode 100644 index 0000000..0749642 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 028aec80942df459ab226487b786042c +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.backup +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs new file mode 100644 index 0000000..ad4b31c --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs @@ -0,0 +1,65 @@ +// +// AppLovinBuildPostProcessor.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 8/29/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_2018_2_OR_NEWER && UNITY_ANDROID + +using System.IO; +using UnityEditor.Android; +using UnityEngine; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// Adds Quality Service plugin to the Gradle project once the project has been exported. See for more details. + /// + public class AppLovinPostProcessGradleProject : AppLovinProcessGradleBuildFile, IPostGenerateGradleAndroidProject + { + public void OnPostGenerateGradleAndroidProject(string path) + { + if (!AppLovinSettings.Instance.QualityServiceEnabled) return; + +#if UNITY_2019_3_OR_NEWER + // On Unity 2019.3+, the path returned is the path to the unityLibrary's module. + // The AppLovin Quality Service buildscript closure related lines need to be added to the root build.gradle file. + var rootGradleBuildFilePath = Path.Combine(path, "../build.gradle"); +#if UNITY_2022_2_OR_NEWER + if (!AddPluginToRootGradleBuildFile(rootGradleBuildFilePath)) return; + + var rootSettingsGradleFilePath = Path.Combine(path, "../settings.gradle"); + if (!AddAppLovinRepository(rootSettingsGradleFilePath)) return; +#else + var buildScriptChangesAdded = AddQualityServiceBuildScriptLines(rootGradleBuildFilePath); + if (!buildScriptChangesAdded) return; +#endif + + // The plugin needs to be added to the application module (named launcher) + var applicationGradleBuildFilePath = Path.Combine(path, "../launcher/build.gradle"); +#else + // If Gradle template is enabled, we would have already updated the plugin. + if (AppLovinIntegrationManager.GradleTemplateEnabled) return; + + var applicationGradleBuildFilePath = Path.Combine(path, "build.gradle"); +#endif + + if (!File.Exists(applicationGradleBuildFilePath)) + { + MaxSdkLogger.UserWarning("Couldn't find build.gradle file. Failed to add AppLovin Quality Service plugin to the gradle project."); + return; + } + + AddAppLovinQualityServicePlugin(applicationGradleBuildFilePath); + } + + public int callbackOrder + { + get { return int.MaxValue; } + } + } +} + +#endif diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta new file mode 100644 index 0000000..25d8a71 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 6af46e436a4b44671b5320be741172db +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs new file mode 100644 index 0000000..078ae4a --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs @@ -0,0 +1,108 @@ +// +// MaxIntegrationManager.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 8/29/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_IOS || UNITY_IPHONE + +using System.Text; +using UnityEngine.Networking; +using Debug = UnityEngine.Debug; +using System.IO; +using UnityEditor; +using UnityEditor.Callbacks; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// Adds AppLovin Quality Service to the iOS project once the project has been exported. + /// + /// 1. Downloads the Quality Service ruby script. + /// 2. Runs the script using Ruby which integrates AppLovin Quality Service to the project. + /// + public class AppLovinPostProcessiOS + { + private const string OutputFileName = "AppLovinQualityServiceSetup.rb"; + + [PostProcessBuild(int.MaxValue)] // We want to run Quality Service script last. + public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath) + { + if (!AppLovinSettings.Instance.QualityServiceEnabled) return; + + var sdkKey = AppLovinSettings.Instance.SdkKey; + if (string.IsNullOrEmpty(sdkKey)) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. SDK Key is empty. Please enter the AppLovin SDK Key in the Integration Manager."); + return; + } + + var outputFilePath = Path.Combine(buildPath, OutputFileName); + + // Check if Quality Service is already installed. + if (File.Exists(outputFilePath) && Directory.Exists(Path.Combine(buildPath, "AppLovinQualityService"))) + { + // TODO: Check if there is a way to validate if the SDK key matches the script. Else the pub can't use append when/if they change the SDK Key. + return; + } + + // 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); + uploadHandler.contentType = "application/json"; + + using (var unityWebRequest = new UnityWebRequest("https://api2.safedk.com/v1/build/ios_setup2")) + { + 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) +#endif + { + MaxSdkLogger.UserError("AppLovin Quality Service installation failed. Failed to download script with error: " + unityWebRequest.error); + return; + } + + // Check if Ruby is installed + var rubyVersion = AppLovinCommandLine.Run("ruby", "--version", buildPath); + if (rubyVersion.ExitCode != 0) + { + MaxSdkLogger.UserError("AppLovin Quality Service installation requires Ruby. Please install Ruby, export it to your system PATH and re-export the project."); + return; + } + + // Ruby is installed, run `ruby AppLovinQualityServiceSetup.rb` + var result = AppLovinCommandLine.Run("ruby", OutputFileName, buildPath); + + // Check if we have an error. + if (result.ExitCode != 0) MaxSdkLogger.UserError("Failed to set up AppLovin Quality Service"); + + MaxSdkLogger.UserDebug(result.Message); + } + } + } +} + +#endif diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta new file mode 100644 index 0000000..7166385 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: cc867a09c5aa14978b1cf1d2522961ce +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs new file mode 100644 index 0000000..366288b --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs @@ -0,0 +1,216 @@ +// +// AppLovinBuildPreProcessor.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 8/27/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_ANDROID + +using System.Linq; +using System; +using System.Collections.Generic; +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 + { + private const string AppLovinSettingsFileName = "applovin_settings.json"; + + private const string KeyTermsFlowSettings = "terms_flow_settings"; + private const string KeyTermsFlowEnabled = "terms_flow_enabled"; + private const string KeyTermsFlowTermsOfService = "terms_flow_terms_of_service"; + private const string KeyTermsFlowPrivacyPolicy = "terms_flow_privacy_policy"; + + private const string KeyConsentFlowSettings = "consent_flow_settings"; + 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"; + +#if UNITY_2018_1_OR_NEWER + public void OnPreprocessBuild(BuildReport report) +#else + public void OnPreprocessBuild(BuildTarget target, string path) +#endif + { + // 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; + +#if UNITY_2019_3_OR_NEWER + // The publisher could be migrating from older Unity versions to 2019_3 or newer. + // If so, we should delete the plugin from the template. The plugin will be added to the project's application module in the post processing script (AppLovinPostProcessGradleProject). + RemoveAppLovinQualityServiceOrSafeDkPlugin(AppLovinIntegrationManager.GradleTemplatePath); +#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) + { + // Check if consent flow is enabled. No need to create the applovin_consent_flow_settings.json if consent flow is disabled. + var consentFlowEnabled = AppLovinInternalSettings.Instance.ConsentFlowEnabled; + if (!consentFlowEnabled) + { + RemoveAppLovinSettingsRawResourceFileIfNeeded(rawResourceDirectory); + return; + } + + var privacyPolicyUrl = AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl; + if (string.IsNullOrEmpty(privacyPolicyUrl)) + { + AppLovinIntegrationManager.ShowBuildFailureDialog("You cannot use the AppLovin SDK's consent flow without defining a Privacy Policy URL in the AppLovin Integration Manager."); + + // No need to update the applovin_consent_flow_settings.json here. Default consent flow state will be determined on the SDK side. + return; + } + + var consentFlowSettings = new Dictionary(); + consentFlowSettings[KeyConsentFlowEnabled] = consentFlowEnabled; + consentFlowSettings[KeyConsentFlowPrivacyPolicy] = privacyPolicyUrl; + + var termsOfServiceUrl = AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl; + if (MaxSdkUtils.IsValidString(termsOfServiceUrl)) + { + consentFlowSettings[KeyConsentFlowTermsOfService] = termsOfServiceUrl; + } + + consentFlowSettings[KeyConsentFlowIncludeDefaultAdvertisingPartners] = AppLovinInternalSettings.Instance.ConsentFlowIncludeDefaultAdvertisingPartnerUrls; + var advertisingPartnerUrls = AppLovinInternalSettings.Instance.ConsentFlowAdvertisingPartnerUrls; + if (MaxSdkUtils.IsValidString(advertisingPartnerUrls)) + { + 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; + } + + var applovinSdkSettings = new Dictionary(); + applovinSdkSettings[KeyConsentFlowSettings] = consentFlowSettings; + + var applovinSdkSettingsJson = Json.Serialize(applovinSdkSettings); + WriteAppLovinSettingsRawResourceFile(applovinSdkSettingsJson, rawResourceDirectory); + } + + public static void EnableTermsFlowIfNeeded(string rawResourceDirectory) + { + if (AppLovinSettings.Instance.ShowInternalSettingsInIntegrationManager) 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; + var consentFlowPlatform = AppLovinSettings.Instance.ConsentFlowPlatform; + if (!consentFlowEnabled || (consentFlowPlatform != Platform.All && consentFlowPlatform != Platform.Android)) + { + RemoveAppLovinSettingsRawResourceFileIfNeeded(rawResourceDirectory); + return; + } + + var privacyPolicyUrl = AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl; + if (string.IsNullOrEmpty(privacyPolicyUrl)) + { + AppLovinIntegrationManager.ShowBuildFailureDialog("You cannot use the AppLovin SDK's consent flow without defining a Privacy Policy URL in the AppLovin Integration Manager."); + + // No need to update the applovin_consent_flow_settings.json here. Default consent flow state will be determined on the SDK side. + return; + } + + var consentFlowSettings = new Dictionary(); + consentFlowSettings[KeyTermsFlowEnabled] = consentFlowEnabled; + consentFlowSettings[KeyTermsFlowPrivacyPolicy] = privacyPolicyUrl; + + var termsOfServiceUrl = AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl; + if (MaxSdkUtils.IsValidString(termsOfServiceUrl)) + { + consentFlowSettings[KeyTermsFlowTermsOfService] = termsOfServiceUrl; + } + + var applovinSdkSettings = new Dictionary(); + applovinSdkSettings[KeyTermsFlowSettings] = consentFlowSettings; + + var applovinSdkSettingsJson = Json.Serialize(applovinSdkSettings); + WriteAppLovinSettingsRawResourceFile(applovinSdkSettingsJson, rawResourceDirectory); + } + + private static void WriteAppLovinSettingsRawResourceFile(string applovinSdkSettingsJson, string rawResourceDirectory) + { + if (!Directory.Exists(rawResourceDirectory)) + { + Directory.CreateDirectory(rawResourceDirectory); + } + + var consentFlowSettingsFilePath = Path.Combine(rawResourceDirectory, AppLovinSettingsFileName); + try + { + File.WriteAllText(consentFlowSettingsFilePath, applovinSdkSettingsJson + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("applovin_settings.json file write failed due to: " + exception.Message); + Console.WriteLine(exception); + } + } + + /// + /// Removes the applovin_settings json file from the build if it exists. + /// + /// The raw resource directory that holds the json file + private static void RemoveAppLovinSettingsRawResourceFileIfNeeded(string rawResourceDirectory) + { + var consentFlowSettingsFilePath = Path.Combine(rawResourceDirectory, AppLovinSettingsFileName); + if (!File.Exists(consentFlowSettingsFilePath)) return; + + try + { + File.Delete(consentFlowSettingsFilePath); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Deleting applovin_settings.json failed due to: " + exception.Message); + Console.WriteLine(exception); + } + } + + public int callbackOrder + { + get { return int.MaxValue; } + } + } +} + +#endif diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta new file mode 100644 index 0000000..1446db4 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 0e2f9480fec024b45bb33af29d3022d6 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.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 new file mode 100644 index 0000000..1ad2a82 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs @@ -0,0 +1,583 @@ +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 9/3/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_ANDROID + +using System.Text; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.Networking; +using Debug = UnityEngine.Debug; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + [Serializable] + public class AppLovinQualityServiceData + { + public string api_key; + } + + /// + /// 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 + { + private static readonly Regex TokenBuildScriptRepositories = new Regex(".*repositories.*"); + private static readonly Regex TokenBuildScriptDependencies = new Regex(".*classpath \'com.android.tools.build:gradle.*"); + private static readonly Regex TokenApplicationPlugin = new Regex(".*apply plugin: \'com.android.application\'.*"); + private static readonly Regex TokenApiKey = new Regex(".*apiKey.*"); + private static readonly Regex TokenAppLovinPlugin = new Regex(".*apply plugin:.+?(?=applovin-quality-service).*"); + +#if UNITY_2022_2_OR_NEWER + private const string PluginsMatcher = "plugins"; + private const string PluginManagementMatcher = "pluginManagement"; + private const string QualityServicePluginRoot = " id 'com.applovin.quality' version '+' apply false // NOTE: Requires version 4.8.3+ for Gradle version 7.2+"; +#endif + + private const string BuildScriptMatcher = "buildscript"; + private const string QualityServiceMavenRepo = "maven { url 'https://artifacts.applovin.com/android'; content { includeGroupByRegex 'com.applovin.*' } }"; + private const string QualityServiceDependencyClassPath = "classpath 'com.applovin.quality:AppLovinQualityServiceGradlePlugin:+'"; + private const string QualityServiceApplyPlugin = "apply plugin: 'applovin-quality-service'"; + private const string QualityServicePlugin = "applovin {"; + private const string QualityServiceApiKey = " apiKey '{0}'"; + private const string QualityServiceBintrayMavenRepo = "https://applovin.bintray.com/Quality-Service"; + private const string QualityServiceNoRegexMavenRepo = "maven { url 'https://artifacts.applovin.com/android' }"; + + // Legacy plugin detection variables + private const string QualityServiceDependencyClassPathV3 = "classpath 'com.applovin.quality:AppLovinQualityServiceGradlePlugin:3.+'"; + private static readonly Regex TokenSafeDkLegacyApplyPlugin = new Regex(".*apply plugin:.+?(?=safedk).*"); + private const string SafeDkLegacyPlugin = "safedk {"; + private const string SafeDkLegacyMavenRepo = "http://download.safedk.com"; + private const string SafeDkLegacyDependencyClassPath = "com.safedk:SafeDKGradlePlugin:"; + + /// + /// Updates the provided Gradle script to add Quality Service plugin. + /// + /// The gradle file to update. + protected void AddAppLovinQualityServicePlugin(string applicationGradleBuildFilePath) + { + if (!AppLovinSettings.Instance.QualityServiceEnabled) return; + + var sdkKey = AppLovinSettings.Instance.SdkKey; + if (string.IsNullOrEmpty(sdkKey)) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. SDK Key is empty. Please enter the AppLovin SDK Key in the Integration Manager."); + return; + } + + // Retrieve the API Key using the SDK Key. + var qualityServiceData = RetrieveQualityServiceData(sdkKey); + var apiKey = qualityServiceData.api_key; + if (string.IsNullOrEmpty(apiKey)) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. API Key is empty."); + return; + } + + // Generate the updated Gradle file that needs to be written. + var lines = File.ReadAllLines(applicationGradleBuildFilePath).ToList(); + var sanitizedLines = RemoveLegacySafeDkPlugin(lines); + var outputLines = GenerateUpdatedBuildFileLines( + sanitizedLines, + apiKey, +#if UNITY_2019_3_OR_NEWER + false // On Unity 2019.3+, the buildscript closure related lines will to be added to the root build.gradle file. +#else + true +#endif + ); + // outputLines can be null if we couldn't add the plugin. + if (outputLines == null) return; + + try + { + File.WriteAllText(applicationGradleBuildFilePath, string.Join("\n", outputLines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. Gradle file write failed."); + Console.WriteLine(exception); + } + } +#if UNITY_2022_2_OR_NEWER + /// + /// Adds AppLovin Quality Service plugin DSL element to the project's root build.gradle file. + /// + /// The path to project's root build.gradle file. + /// true when the plugin was added successfully. + protected bool AddPluginToRootGradleBuildFile(string rootGradleBuildFile) + { + var lines = File.ReadAllLines(rootGradleBuildFile).ToList(); + + // Check if the plugin is already added to the file. + var pluginAdded = lines.Any(line => line.Contains(QualityServicePluginRoot)); + if (pluginAdded) return true; + + var outputLines = new List(); + var insidePluginsClosure = false; + foreach (var line in lines) + { + if (line.Contains(PluginsMatcher)) + { + insidePluginsClosure = true; + } + + if (!pluginAdded && insidePluginsClosure && line.Contains("}")) + { + outputLines.Add(QualityServicePluginRoot); + pluginAdded = true; + insidePluginsClosure = false; + } + + outputLines.Add(line); + } + + if (!pluginAdded) + { + MaxSdkLogger.UserError("Failed to add AppLovin Quality Service plugin to root gradle file."); + return false; + } + + try + { + File.WriteAllText(rootGradleBuildFile, string.Join("\n", outputLines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. Root Gradle file write failed."); + Console.WriteLine(exception); + return false; + } + + return true; + } + + /// + /// Adds the AppLovin maven repository to the project's settings.gradle file. + /// + /// The path to the project's settings.gradle file. + /// true if the repository was added successfully. + protected bool AddAppLovinRepository(string settingsGradleFile) + { + var lines = File.ReadLines(settingsGradleFile).ToList(); + var outputLines = new List(); + var mavenRepoAdded = false; + var pluginManagementClosureDepth = 0; + var insidePluginManagementClosure = false; + var pluginManagementMatched = false; + foreach (var line in lines) + { + outputLines.Add(line); + + if (!pluginManagementMatched && line.Contains(PluginManagementMatcher)) + { + pluginManagementMatched = true; + insidePluginManagementClosure = true; + } + + if (insidePluginManagementClosure) + { + if (line.Contains("{")) + { + pluginManagementClosureDepth++; + } + + if (line.Contains("}")) + { + pluginManagementClosureDepth--; + } + + if (pluginManagementClosureDepth == 0) + { + insidePluginManagementClosure = false; + } + } + + if (insidePluginManagementClosure) + { + if (!mavenRepoAdded && TokenBuildScriptRepositories.IsMatch(line)) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo)); + mavenRepoAdded = true; + } + } + } + + if (!mavenRepoAdded) + { + MaxSdkLogger.UserError("Failed to add AppLovin Quality Service plugin maven repo to settings gradle file."); + return false; + } + + try + { + File.WriteAllText(settingsGradleFile, string.Join("\n", outputLines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. Setting Gradle file write failed."); + Console.WriteLine(exception); + return false; + } + + return true; + } +#endif + +#if UNITY_2019_3_OR_NEWER + /// + /// Adds the necessary AppLovin Quality Service dependency and maven repo lines to the provided root build.gradle file. + /// + /// The root build.gradle file path + /// true if the build script lines were applied correctly. + protected bool AddQualityServiceBuildScriptLines(string rootGradleBuildFile) + { + var lines = File.ReadAllLines(rootGradleBuildFile).ToList(); + var outputLines = GenerateUpdatedBuildFileLines(lines, null, true); + + // outputLines will be null if we couldn't add the build script lines. + if (outputLines == null) return false; + + try + { + File.WriteAllText(rootGradleBuildFile, string.Join("\n", outputLines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. Root Gradle file write failed."); + Console.WriteLine(exception); + return false; + } + + return true; + } + + /// + /// Removes the AppLovin Quality Service Plugin or Legacy SafeDK plugin from the given gradle template file if either of them are present. + /// + /// The gradle template file from which to remove the plugin from + protected static void RemoveAppLovinQualityServiceOrSafeDkPlugin(string gradleTemplateFile) + { + var lines = File.ReadAllLines(gradleTemplateFile).ToList(); + lines = RemoveLegacySafeDkPlugin(lines); + lines = RemoveAppLovinQualityServicePlugin(lines); + + try + { + File.WriteAllText(gradleTemplateFile, string.Join("\n", lines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to remove AppLovin Quality Service Plugin from mainTemplate.gradle. Please remove the Quality Service plugin from the mainTemplate.gradle manually."); + Console.WriteLine(exception); + } + } +#endif + + private static AppLovinQualityServiceData RetrieveQualityServiceData(string sdkKey) + { + var postJson = string.Format("{{\"sdk_key\" : \"{0}\"}}", sdkKey); + var bodyRaw = Encoding.UTF8.GetBytes(postJson); + // Upload handler is automatically disposed when UnityWebRequest is disposed + var uploadHandler = new UploadHandlerRaw(bodyRaw); + uploadHandler.contentType = "application/json"; + + using (var unityWebRequest = new UnityWebRequest("https://api2.safedk.com/v1/build/cred")) + { + unityWebRequest.method = UnityWebRequest.kHttpVerbPOST; + 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) +#endif + { + MaxSdkLogger.UserError("Failed to retrieve API Key for SDK Key: " + sdkKey + "with error: " + unityWebRequest.error); + return new AppLovinQualityServiceData(); + } + + try + { + return JsonUtility.FromJson(unityWebRequest.downloadHandler.text); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to parse API Key." + exception); + return new AppLovinQualityServiceData(); + } + } + } + + private static List RemoveLegacySafeDkPlugin(List lines) + { + return RemovePlugin(lines, SafeDkLegacyPlugin, SafeDkLegacyMavenRepo, SafeDkLegacyDependencyClassPath, TokenSafeDkLegacyApplyPlugin); + } + + private static List RemoveAppLovinQualityServicePlugin(List lines) + { + return RemovePlugin(lines, QualityServicePlugin, QualityServiceMavenRepo, QualityServiceDependencyClassPath, TokenAppLovinPlugin); + } + + private static List RemovePlugin(List lines, string pluginLine, string mavenRepo, string dependencyClassPath, Regex applyPluginToken) + { + var sanitizedLines = new List(); + var legacyRepoRemoved = false; + var legacyDependencyClassPathRemoved = false; + var legacyPluginRemoved = false; + var legacyPluginMatched = false; + var insideLegacySafeDkClosure = false; + foreach (var line in lines) + { + if (!legacyPluginMatched && line.Contains(pluginLine)) + { + legacyPluginMatched = true; + insideLegacySafeDkClosure = true; + } + + if (insideLegacySafeDkClosure && line.Contains("}")) + { + insideLegacySafeDkClosure = false; + continue; + } + + if (insideLegacySafeDkClosure) + { + continue; + } + + if (!legacyRepoRemoved && line.Contains(mavenRepo)) + { + legacyRepoRemoved = true; + continue; + } + + if (!legacyDependencyClassPathRemoved && line.Contains(dependencyClassPath)) + { + legacyDependencyClassPathRemoved = true; + continue; + } + + if (!legacyPluginRemoved && applyPluginToken.IsMatch(line)) + { + legacyPluginRemoved = true; + continue; + } + + sanitizedLines.Add(line); + } + + return sanitizedLines; + } + + private static List GenerateUpdatedBuildFileLines(List lines, string apiKey, bool addBuildScriptLines) + { + var addPlugin = !string.IsNullOrEmpty(apiKey); + // A sample of the template file. + // ... + // allprojects { + // repositories {**ARTIFACTORYREPOSITORY** + // google() + // jcenter() + // flatDir { + // dirs 'libs' + // } + // } + // } + // + // apply plugin: 'com.android.application' + // **APPLY_PLUGINS** + // + // dependencies { + // implementation fileTree(dir: 'libs', include: ['*.jar']) + // **DEPS**} + // ... + var outputLines = new List(); + // Check if the plugin exists, if so, update the SDK Key. + var pluginExists = lines.Any(line => TokenAppLovinPlugin.IsMatch(line)); + if (pluginExists) + { + var pluginMatched = false; + var insideAppLovinClosure = false; + var updatedApiKey = false; + var mavenRepoUpdated = false; + var dependencyClassPathUpdated = false; + foreach (var line in lines) + { + // Bintray maven repo is no longer being used. Update to s3 maven repo with regex check + if (!mavenRepoUpdated && (line.Contains(QualityServiceBintrayMavenRepo) || line.Contains(QualityServiceNoRegexMavenRepo))) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo)); + mavenRepoUpdated = true; + continue; + } + + // We no longer use version specific dependency class path. Just use + for version to always pull the latest. + if (!dependencyClassPathUpdated && line.Contains(QualityServiceDependencyClassPathV3)) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceDependencyClassPath)); + dependencyClassPathUpdated = true; + continue; + } + + if (!pluginMatched && line.Contains(QualityServicePlugin)) + { + insideAppLovinClosure = true; + pluginMatched = true; + } + + if (insideAppLovinClosure && line.Contains("}")) + { + insideAppLovinClosure = false; + } + + // Update the API key. + if (insideAppLovinClosure && !updatedApiKey && TokenApiKey.IsMatch(line)) + { + outputLines.Add(string.Format(QualityServiceApiKey, apiKey)); + updatedApiKey = true; + } + // Keep adding the line until we find and update the plugin. + else + { + outputLines.Add(line); + } + } + } + // Plugin hasn't been added yet, add it. + else + { + var buildScriptClosureDepth = 0; + var insideBuildScriptClosure = false; + var buildScriptMatched = false; + var qualityServiceRepositoryAdded = false; + var qualityServiceDependencyClassPathAdded = false; + var qualityServicePluginAdded = false; + foreach (var line in lines) + { + // Add the line to the output lines. + outputLines.Add(line); + + // Check if we need to add the build script lines and add them. + if (addBuildScriptLines) + { + if (!buildScriptMatched && line.Contains(BuildScriptMatcher)) + { + buildScriptMatched = true; + insideBuildScriptClosure = true; + } + + // Match the parenthesis to track if we are still inside the buildscript closure. + if (insideBuildScriptClosure) + { + if (line.Contains("{")) + { + buildScriptClosureDepth++; + } + + if (line.Contains("}")) + { + buildScriptClosureDepth--; + } + + if (buildScriptClosureDepth == 0) + { + insideBuildScriptClosure = false; + + // There may be multiple buildscript closures and we need to keep looking until we added both the repository and classpath. + buildScriptMatched = qualityServiceRepositoryAdded && qualityServiceDependencyClassPathAdded; + } + } + + if (insideBuildScriptClosure) + { + // Add the build script dependency repositories. + if (!qualityServiceRepositoryAdded && TokenBuildScriptRepositories.IsMatch(line)) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo)); + qualityServiceRepositoryAdded = true; + } + // Add the build script dependencies. + else if (!qualityServiceDependencyClassPathAdded && TokenBuildScriptDependencies.IsMatch(line)) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceDependencyClassPath)); + qualityServiceDependencyClassPathAdded = true; + } + } + } + + // Check if we need to add the plugin and add it. + if (addPlugin) + { + // Add the plugin. + if (!qualityServicePluginAdded && TokenApplicationPlugin.IsMatch(line)) + { + outputLines.Add(QualityServiceApplyPlugin); + outputLines.AddRange(GenerateAppLovinPluginClosure(apiKey)); + qualityServicePluginAdded = true; + } + } + } + + if ((addBuildScriptLines && (!qualityServiceRepositoryAdded || !qualityServiceDependencyClassPathAdded)) || (addPlugin && !qualityServicePluginAdded)) + { + MaxSdkLogger.UserError("Failed to add AppLovin Quality Service plugin. Quality Service Plugin Added?: " + qualityServicePluginAdded + ", Quality Service Repo added?: " + qualityServiceRepositoryAdded + ", Quality Service dependency added?: " + qualityServiceDependencyClassPathAdded); + return null; + } + } + + return outputLines; + } + + private static string GetFormattedBuildScriptLine(string buildScriptLine) + { +#if UNITY_2022_2_OR_NEWER + return " " +#elif UNITY_2019_3_OR_NEWER + return " " +#else + return " " +#endif + + buildScriptLine; + } + + private static IEnumerable GenerateAppLovinPluginClosure(string apiKey) + { + // applovin { + // // NOTE: DO NOT CHANGE - this is NOT your AppLovin MAX SDK key - this is a derived key. + // apiKey "456...a1b" + // } + var linesToInject = new List(5); + linesToInject.Add(""); + linesToInject.Add("applovin {"); + linesToInject.Add(" // NOTE: DO NOT CHANGE - this is NOT your AppLovin MAX SDK key - this is a derived key."); + linesToInject.Add(string.Format(QualityServiceApiKey, apiKey)); + linesToInject.Add("}"); + + return linesToInject; + } + } +} + +#endif diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta new file mode 100644 index 0000000..3b9b19c --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: a25d66215002f4728b56848ff01f7424 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs new file mode 100644 index 0000000..94bc0d0 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs @@ -0,0 +1,390 @@ +// +// AppLovinSettings.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 1/27/20. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using AppLovinMax.Scripts.IntegrationManager.Editor; +using System.IO; +using UnityEditor; +using UnityEngine; +using UnityEngine.Serialization; + + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public enum Platform + { + All, + Android, + iOS + } +} + +/// +/// A representing the AppLovin Settings that can be set in the Integration Manager Window. +/// +/// The scriptable object asset is created with the name AppLovinSettings.asset and is placed under the directory Assets/MaxSdk/Resources. +/// +/// NOTE: Not name spacing this class since it is reflected upon by the Google adapter and will break compatibility. +/// +public class AppLovinSettings : ScriptableObject +{ + public const string SettingsExportPath = "MaxSdk/Resources/AppLovinSettings.asset"; + + public const string DefaultUserTrackingDescriptionEnV0 = "Pressing \\\"Allow\\\" uses device info for more relevant ad content"; + public const string DefaultUserTrackingDescriptionEnV1 = "This only uses device info for less annoying, more relevant ads"; + public const string DefaultUserTrackingDescriptionEnV2 = "This only uses device info for more interesting and relevant ads"; + public const string DefaultUserTrackingDescriptionEnV3 = "This uses device info for more personalized ads and content"; + + public const string DefaultUserTrackingDescriptionDe = "\\\"Erlauben\\\" drücken benutzt Gerätinformationen für relevantere Werbeinhalte"; + public const string DefaultUserTrackingDescriptionEs = "Presionando \\\"Permitir\\\", se usa la información del dispositivo para obtener contenido publicitario más relevante"; + public const string DefaultUserTrackingDescriptionFr = "\\\"Autoriser\\\" permet d'utiliser les infos du téléphone pour afficher des contenus publicitaires plus pertinents"; + public const string DefaultUserTrackingDescriptionJa = "\\\"許可\\\"をクリックすることで、デバイス情報を元により最適な広告を表示することができます"; + public const string DefaultUserTrackingDescriptionKo = "\\\"허용\\\"을 누르면 더 관련성 높은 광고 콘텐츠를 제공하기 위해 기기 정보가 사용됩니다"; + public const string DefaultUserTrackingDescriptionZhHans = "点击\\\"允许\\\"以使用设备信息获得更加相关的广告内容"; + public const string DefaultUserTrackingDescriptionZhHant = "點擊\\\"允許\\\"以使用設備信息獲得更加相關的廣告內容"; + + /// + /// A placeholder constant to be replaced with the actual default localization or an empty string based on whether or not localization is enabled when when the getter is called. + /// + protected const string DefaultLocalization = "default_localization"; + + private static AppLovinSettings instance; + + [SerializeField] private bool qualityServiceEnabled = true; + [SerializeField] private string sdkKey; + + [SerializeField] private bool setAttributionReportEndpoint; + + [SerializeField] private bool consentFlowEnabled; + [SerializeField] private Platform consentFlowPlatform; + [SerializeField] private string consentFlowPrivacyPolicyUrl = string.Empty; + [SerializeField] private string consentFlowTermsOfServiceUrl = string.Empty; + [FormerlySerializedAs("userTrackingUsageDescription")] [SerializeField] private string userTrackingUsageDescriptionEn = string.Empty; + [SerializeField] private bool userTrackingUsageLocalizationEnabled; + [SerializeField] private string userTrackingUsageDescriptionDe = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionEs = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionFr = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionJa = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionKo = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionZhHans = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionZhHant = DefaultLocalization; + + [SerializeField] private string adMobAndroidAppId = string.Empty; + [SerializeField] private string adMobIosAppId = string.Empty; + + [SerializeField] private bool showInternalSettingsInIntegrationManager; + + /// + /// An instance of AppLovin Setting. + /// + public static AppLovinSettings Instance + { + get + { + if (instance == null) + { + // Check for an existing AppLovinSettings somewhere in the project + var guids = AssetDatabase.FindAssets("AppLovinSettings t:ScriptableObject"); + if (guids.Length > 1) + { + MaxSdkLogger.UserWarning("Multiple AppLovinSettings found. This may cause unexpected results."); + } + + if (guids.Length != 0) + { + var path = AssetDatabase.GUIDToAssetPath(guids[0]); + instance = AssetDatabase.LoadAssetAtPath(path); + return instance; + } + + // If there is no existing AppLovinSettings asset, create one in the default location + string settingsFilePath; + // The settings file should be under the Assets/ folder so that it can be version controlled and cannot be overriden when updating. + // If the plugin is outside the Assets folder, create the settings asset at the default location. + if (AppLovinIntegrationManager.IsPluginOutsideAssetsDirectory) + { + // Note: Can't use absolute path when calling `CreateAsset`. Should use relative path to Assets/ directory. + settingsFilePath = Path.Combine("Assets", SettingsExportPath); + + var maxSdkDir = Path.Combine(Application.dataPath, "MaxSdk"); + if (!Directory.Exists(maxSdkDir)) + { + Directory.CreateDirectory(maxSdkDir); + } + } + else + { + settingsFilePath = Path.Combine(AppLovinIntegrationManager.PluginParentDirectory, SettingsExportPath); + } + + var settingsDir = Path.GetDirectoryName(settingsFilePath); + if (!Directory.Exists(settingsDir)) + { + Directory.CreateDirectory(settingsDir); + } + + instance = CreateInstance(); + AssetDatabase.CreateAsset(instance, settingsFilePath); + MaxSdkLogger.D("Creating new AppLovinSettings asset at path: " + settingsFilePath); + } + + return instance; + } + } + + /// + /// Whether or not to install Quality Service plugin. + /// + public bool QualityServiceEnabled + { + get { return Instance.qualityServiceEnabled; } + set { Instance.qualityServiceEnabled = value; } + } + + /// + /// AppLovin SDK Key. + /// + public string SdkKey + { + get { return Instance.sdkKey; } + set { Instance.sdkKey = value; } + } + + /// + /// Whether or not to set `NSAdvertisingAttributionReportEndpoint` in Info.plist. + /// + public bool SetAttributionReportEndpoint + { + get { return Instance.setAttributionReportEndpoint; } + set { Instance.setAttributionReportEndpoint = value; } + } + + /// + /// Whether or not AppLovin Consent Flow is enabled. + /// + public bool ConsentFlowEnabled + { + get + { + // Update the default EN description if an old version of the description is still being used. + if (DefaultUserTrackingDescriptionEnV0.Equals(Instance.UserTrackingUsageDescriptionEn) + || DefaultUserTrackingDescriptionEnV1.Equals(Instance.UserTrackingUsageDescriptionEn) + || DefaultUserTrackingDescriptionEnV2.Equals(Instance.UserTrackingUsageDescriptionEn)) + { + Instance.UserTrackingUsageDescriptionEn = DefaultUserTrackingDescriptionEnV3; + } + + return Instance.consentFlowEnabled; + } + set + { + var previousValue = Instance.consentFlowEnabled; + Instance.consentFlowEnabled = value; + + if (value) + { + // If the value didn't change, we don't need to update anything. + if (previousValue) return; + + Instance.UserTrackingUsageDescriptionEn = DefaultUserTrackingDescriptionEnV3; + Instance.UserTrackingUsageLocalizationEnabled = true; + } + else + { + Instance.ConsentFlowPlatform = Platform.All; + Instance.ConsentFlowPrivacyPolicyUrl = string.Empty; + Instance.ConsentFlowTermsOfServiceUrl = string.Empty; + Instance.UserTrackingUsageDescriptionEn = string.Empty; + Instance.UserTrackingUsageLocalizationEnabled = false; + } + } + } + + public Platform ConsentFlowPlatform + { + get { return Instance.consentFlowEnabled ? Instance.consentFlowPlatform : Platform.All; } + set { Instance.consentFlowPlatform = value; } + } + + /// + /// A URL pointing to the Privacy Policy for the app to be shown when prompting the user for consent. + /// + public string ConsentFlowPrivacyPolicyUrl + { + get { return Instance.consentFlowPrivacyPolicyUrl; } + set { Instance.consentFlowPrivacyPolicyUrl = value; } + } + + /// + /// An optional URL pointing to the Terms of Service for the app to be shown when prompting the user for consent. + /// + public string ConsentFlowTermsOfServiceUrl + { + get { return Instance.consentFlowTermsOfServiceUrl; } + set { Instance.consentFlowTermsOfServiceUrl = 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. + /// + public string UserTrackingUsageDescriptionEn + { + get { return Instance.userTrackingUsageDescriptionEn; } + set { Instance.userTrackingUsageDescriptionEn = value; } + } + + /// + /// Whether or not to localize User Tracking Usage Description. + /// For more information see Apple's documentation. + /// + public bool UserTrackingUsageLocalizationEnabled + { + get { return Instance.userTrackingUsageLocalizationEnabled; } + set + { + var previousValue = Instance.userTrackingUsageLocalizationEnabled; + Instance.userTrackingUsageLocalizationEnabled = value; + + if (value) + { + // If the value didn't change or the english localization text is not the default one, we don't need to update anything. + if (previousValue || !DefaultUserTrackingDescriptionEnV3.Equals(Instance.UserTrackingUsageDescriptionEn)) return; + + Instance.UserTrackingUsageDescriptionDe = DefaultUserTrackingDescriptionDe; + Instance.UserTrackingUsageDescriptionEs = DefaultUserTrackingDescriptionEs; + Instance.UserTrackingUsageDescriptionFr = DefaultUserTrackingDescriptionFr; + Instance.UserTrackingUsageDescriptionJa = DefaultUserTrackingDescriptionJa; + Instance.UserTrackingUsageDescriptionKo = DefaultUserTrackingDescriptionKo; + Instance.UserTrackingUsageDescriptionZhHans = DefaultUserTrackingDescriptionZhHans; + Instance.UserTrackingUsageDescriptionZhHant = DefaultUserTrackingDescriptionZhHant; + } + else + { + Instance.UserTrackingUsageDescriptionDe = string.Empty; + Instance.UserTrackingUsageDescriptionEs = string.Empty; + Instance.UserTrackingUsageDescriptionFr = string.Empty; + Instance.UserTrackingUsageDescriptionJa = string.Empty; + Instance.UserTrackingUsageDescriptionKo = string.Empty; + Instance.UserTrackingUsageDescriptionZhHans = string.Empty; + Instance.UserTrackingUsageDescriptionZhHant = string.Empty; + } + } + } + + /// + /// A User Tracking Usage Description in German to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionDe + { + get { return Instance.userTrackingUsageDescriptionDe; } + set { Instance.userTrackingUsageDescriptionDe = value; } + } + + /// + /// A User Tracking Usage Description in Spanish to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionEs + { + get { return Instance.userTrackingUsageDescriptionEs; } + set { Instance.userTrackingUsageDescriptionEs = value; } + } + + /// + /// A User Tracking Usage Description in French to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionFr + { + get { return Instance.userTrackingUsageDescriptionFr; } + set { Instance.userTrackingUsageDescriptionFr = value; } + } + + /// + /// A User Tracking Usage Description in Japanese to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionJa + { + get { return Instance.userTrackingUsageDescriptionJa; } + set { Instance.userTrackingUsageDescriptionJa = value; } + } + + /// + /// A User Tracking Usage Description in Korean to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionKo + { + get { return Instance.userTrackingUsageDescriptionKo; } + set { Instance.userTrackingUsageDescriptionKo = value; } + } + + /// + /// A User Tracking Usage Description in Chinese (Simplified) to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionZhHans + { + get { return Instance.userTrackingUsageDescriptionZhHans; } + set { Instance.userTrackingUsageDescriptionZhHans = value; } + } + + /// + /// A User Tracking Usage Description in Chinese (Traditional) to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionZhHant + { + get + { + // Since this localization has been added separate from the other localizations, + // we use a placeholder constant to be replaced with the actual value or an empty string based on whether or not the localization was enabled by the publisher. + if (DefaultLocalization.Equals(Instance.userTrackingUsageDescriptionZhHant)) + { + Instance.userTrackingUsageDescriptionZhHant = Instance.UserTrackingUsageLocalizationEnabled ? DefaultUserTrackingDescriptionZhHant : string.Empty; + } + + return Instance.userTrackingUsageDescriptionZhHant; + } + set { Instance.userTrackingUsageDescriptionZhHant = value; } + } + + /// + /// AdMob Android App ID. + /// + public string AdMobAndroidAppId + { + get { return Instance.adMobAndroidAppId; } + set { Instance.adMobAndroidAppId = value; } + } + + /// + /// AdMob iOS App ID. + /// + public string AdMobIosAppId + { + get { return Instance.adMobIosAppId; } + set { Instance.adMobIosAppId = value; } + } + + public bool ShowInternalSettingsInIntegrationManager + { + get { return Instance.showInternalSettingsInIntegrationManager; } + set { Instance.showInternalSettingsInIntegrationManager = value; } + } + + /// + /// Saves the instance of the settings. + /// + public void SaveAsync() + { + EditorUtility.SetDirty(instance); + } +} diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta new file mode 100644 index 0000000..9c8ec08 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 589f0157fc8d1480a908eb38be2be8e6 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef b/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef new file mode 100644 index 0000000..2737229 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef @@ -0,0 +1,18 @@ +{ + "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 diff --git a/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta b/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta new file mode 100644 index 0000000..a99dbb6 --- /dev/null +++ b/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: 0772632c471804ae89859df0956a3692 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef +timeCreated: 1591749873 diff --git a/MaxSdk/Scripts/MaxEventSystemChecker.cs b/MaxSdk/Scripts/MaxEventSystemChecker.cs new file mode 100644 index 0000000..19a082f --- /dev/null +++ b/MaxSdk/Scripts/MaxEventSystemChecker.cs @@ -0,0 +1,37 @@ +// +// EventSystemChecker.cs +// AppLovin MAX Unity Plugin +// +// Created by Jonathan Liu on 10/23/2022. +// Copyright © 2022 AppLovin. All rights reserved. +// + +#if UNITY_EDITOR +using UnityEngine; +using UnityEngine.EventSystems; + +namespace AppLovinMax.Scripts +{ + /// + /// A script to check and enable event system as needed for the AppLovin MAX ad prefabs. + /// + [RequireComponent(typeof(EventSystem))] + public class MaxEventSystemChecker : MonoBehaviour + { + private void Awake() + { + // Enable the EventSystem if there is no other EventSystem in the scene + var eventSystem = GetComponent(); + var currentSystem = UnityEngine.EventSystems.EventSystem.current; + if (currentSystem == null || currentSystem == eventSystem) + { + eventSystem.enabled = true; + } + else + { + eventSystem.enabled = false; + } + } + } +} +#endif diff --git a/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta b/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta new file mode 100644 index 0000000..f75521a --- /dev/null +++ b/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 93afd2b1bb96f411d9e7bfa15fc9a0eb +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxEventSystemChecker.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxEvents.cs b/MaxSdk/Scripts/MaxEvents.cs new file mode 100644 index 0000000..b0a9ad6 --- /dev/null +++ b/MaxSdk/Scripts/MaxEvents.cs @@ -0,0 +1,21 @@ +/** + * Class containing pre-defined constants to use with AppLovin event tracking APIs. + */ +public static class MaxEvents +{ + /** + * Nested class representing pre-defined AppLovin events to be fired with AppLovin event tracking APIs. + */ + public class AppLovin + { + public const string UserLoggedIn = "login"; + public const string UserCreatedAccount = "registration"; + public const string UserCompletedTutorial = "tutorial"; + public const string UserCompletedLevel = "level"; + public const string UserCompletedAchievement = "achievement"; + public const string UserSpentVirtualCurrency = "vcpurchase"; + public const string UserCompletedInAppPurchase = "iap"; + public const string UserSentInvitation = "invite"; + public const string UserSharedLink = "share"; + } +} \ No newline at end of file diff --git a/MaxSdk/Scripts/MaxEvents.cs.meta b/MaxSdk/Scripts/MaxEvents.cs.meta new file mode 100644 index 0000000..3a28e28 --- /dev/null +++ b/MaxSdk/Scripts/MaxEvents.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: c13d7e9087ead447aa741d6d06aef9e1 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxEvents.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxSdk.Scripts.asmdef b/MaxSdk/Scripts/MaxSdk.Scripts.asmdef new file mode 100644 index 0000000..99e1d22 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdk.Scripts.asmdef @@ -0,0 +1,6 @@ + { + "name": "MaxSdk.Scripts", + "references": [], + "includePlatforms": [], + "excludePlatforms": [] +} diff --git a/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta b/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta new file mode 100644 index 0000000..cf4cd69 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: b2529e5083a524b099f54b2bb80f05fc +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdk.Scripts.asmdef +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxSdk.cs b/MaxSdk/Scripts/MaxSdk.cs new file mode 100644 index 0000000..1ffcf2c --- /dev/null +++ b/MaxSdk/Scripts/MaxSdk.cs @@ -0,0 +1,30 @@ +/** + * AppLovin MAX Unity Plugin C# Wrapper + */ + +using UnityEngine; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +public class MaxSdk : +#if UNITY_EDITOR + // Check for Unity Editor first since the editor also responds to the currently selected platform. + MaxSdkUnityEditor +#elif UNITY_ANDROID + MaxSdkAndroid +#elif UNITY_IPHONE || UNITY_IOS + MaxSdkiOS +#else + MaxSdkUnityEditor +#endif +{ + private const string _version = "5.11.4"; + + /// + /// Returns the current plugin version. + /// + public static string Version + { + get { return _version; } + } +} diff --git a/MaxSdk/Scripts/MaxSdk.cs.meta b/MaxSdk/Scripts/MaxSdk.cs.meta new file mode 100644 index 0000000..9f55566 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdk.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: b9c276744a7284b6788f515c12cc403c +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdk.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxSdkAndroid.cs b/MaxSdk/Scripts/MaxSdkAndroid.cs new file mode 100644 index 0000000..47aecb1 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkAndroid.cs @@ -0,0 +1,1236 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using AppLovinMax.ThirdParty.MiniJson; + +/// +/// Android AppLovin MAX Unity Plugin implementation +/// +public class MaxSdkAndroid : MaxSdkBase +{ + private static readonly AndroidJavaClass MaxUnityPluginClass = + new AndroidJavaClass("com.applovin.mediation.unity.MaxUnityPlugin"); + + private static BackgroundCallbackProxy BackgroundCallback = new BackgroundCallbackProxy(); + + public static MaxVariableServiceAndroid VariableService + { + get { return MaxVariableServiceAndroid.Instance; } + } + + public static MaxUserServiceAndroid UserService + { + get { return MaxUserServiceAndroid.Instance; } + } + + static MaxSdkAndroid() + { + InitCallbacks(); + } + + #region Initialization + + /// + /// Set AppLovin SDK Key. + /// + /// This method must be called before any other SDK operation + /// + public static void SetSdkKey(string sdkKey) + { + MaxUnityPluginClass.CallStatic("setSdkKey", sdkKey); + } + + /// + /// Initialize the default instance of AppLovin SDK. + /// + /// Please make sure that application's Android manifest or Info.plist includes the AppLovin SDK key. + /// + /// OPTIONAL: Set the MAX ad unit ids to be used for this instance of the SDK. 3rd-party SDKs will be initialized with the credentials configured for these ad unit ids. + /// This should only be used if you have different sets of ad unit ids / credentials for the same package name. + /// + public static void InitializeSdk(string[] adUnitIds = null) + { + var serializedAdUnitIds = (adUnitIds != null) ? string.Join(",", adUnitIds) : ""; + MaxUnityPluginClass.CallStatic("initializeSdk", serializedAdUnitIds, GenerateMetaData(), BackgroundCallback); + } + + /// + /// Check if the SDK has been initialized + /// + /// True if SDK has been initialized + public static bool IsInitialized() + { + return MaxUnityPluginClass.CallStatic("isInitialized"); + } + + #endregion + + #region User Info + + /// + /// Set an identifier for the current user. This identifier will be tied to SDK events and our optional S2S postbacks. + /// + /// If you're using reward validation, you can optionally set an identifier to be included with currency validation postbacks. + /// For example, a username or email. We'll include this in the postback when we ping your currency endpoint from our server. + /// + /// + /// The user identifier to be set. + public static void SetUserId(string userId) + { + MaxUnityPluginClass.CallStatic("setUserId", userId); + } + + /// + /// User segments allow us to serve ads using custom-defined rules based on which segment the user is in. For now, we only support a custom string 32 alphanumeric characters or less as the user segment. + /// + public static MaxUserSegment UserSegment + { + get { return SharedUserSegment; } + } + + /// + /// This class allows you to provide user or app data that will improve how we target ads. + /// + public static MaxTargetingData TargetingData + { + get { return SharedTargetingData; } + } + + #endregion + + #region MAX + + /// + /// Returns the list of available mediation networks. + /// + /// Please call this method after the SDK has initialized. + /// + public static List GetAvailableMediatedNetworks() + { + var serializedNetworks = MaxUnityPluginClass.CallStatic("getAvailableMediatedNetworks"); + return MaxSdkUtils.PropsStringsToList(serializedNetworks); + } + + /// + /// Present the mediation debugger UI. + /// This debugger tool provides the status of your integration for each third-party ad network. + /// + /// Please call this method after the SDK has initialized. + /// + public static void ShowMediationDebugger() + { + MaxUnityPluginClass.CallStatic("showMediationDebugger"); + } + + /// + /// Present the creative debugger UI. + /// This debugger tool provides information for recently displayed ads. + /// + /// Please call this method after the SDK has initialized. + /// + public static void ShowCreativeDebugger() + { + MaxUnityPluginClass.CallStatic("showCreativeDebugger"); + } + + /// + /// Returns the arbitrary ad value for a given ad unit identifier with key. Returns null if no ad is loaded. + /// + /// + /// Ad value key + /// Arbitrary ad value for a given key, or null if no ad is loaded. + public static string GetAdValue(string adUnitIdentifier, string key) + { + var value = MaxUnityPluginClass.CallStatic("getAdValue", adUnitIdentifier, key); + + if (string.IsNullOrEmpty(value)) return null; + + return value; + } + + #endregion + + #region Privacy + + /// + /// Get the SDK configuration for this user. + /// + /// Note: This method should be called only after SDK has been initialized. + /// + public static SdkConfiguration GetSdkConfiguration() + { + var sdkConfigurationStr = MaxUnityPluginClass.CallStatic("getSdkConfiguration"); + var sdkConfigurationDict = Json.Deserialize(sdkConfigurationStr) as Dictionary; + return SdkConfiguration.Create(sdkConfigurationDict); + } + + /// + /// Set whether or not user has provided consent for information sharing with AppLovin and other providers. + /// + /// true if the user has provided consent for information sharing with AppLovin. false by default. + public static void SetHasUserConsent(bool hasUserConsent) + { + MaxUnityPluginClass.CallStatic("setHasUserConsent", hasUserConsent); + } + + /// + /// Check if user has provided consent for information sharing with AppLovin and other providers. + /// + /// true if user has provided consent for information sharing. false if the user declined to share information or the consent value has not been set . + public static bool HasUserConsent() + { + return MaxUnityPluginClass.CallStatic("hasUserConsent"); + } + + /// + /// Check if user has set consent for information sharing. + /// + /// true if user has set a value of consent for information sharing. + public static bool IsUserConsentSet() + { + return MaxUnityPluginClass.CallStatic("isUserConsentSet"); + } + + /// + /// Mark user as age restricted (i.e. under 16). + /// + /// true if the user is age restricted (i.e. under 16). + public static void SetIsAgeRestrictedUser(bool isAgeRestrictedUser) + { + MaxUnityPluginClass.CallStatic("setIsAgeRestrictedUser", isAgeRestrictedUser); + } + + /// + /// Check if user is age restricted. + /// + /// true if the user is age-restricted. false if the user is not age-restricted or the age-restriction has not been set. + public static bool IsAgeRestrictedUser() + { + return MaxUnityPluginClass.CallStatic("isAgeRestrictedUser"); + } + + /// + /// Check if the user has set its age restricted settings. + /// + /// true if the user has set its age restricted settings. + public static bool IsAgeRestrictedUserSet() + { + return MaxUnityPluginClass.CallStatic("isAgeRestrictedUserSet"); + } + + /// + /// Set whether or not user has opted out of the sale of their personal information. + /// + /// true if the user has opted out of the sale of their personal information. + public static void SetDoNotSell(bool doNotSell) + { + MaxUnityPluginClass.CallStatic("setDoNotSell", doNotSell); + } + + /// + /// Check if the user has opted out of the sale of their personal information. + /// + /// true if the user has opted out of the sale of their personal information. false if the user opted in to the sell of their personal information or the value has not been set . + public static bool IsDoNotSell() + { + return MaxUnityPluginClass.CallStatic("isDoNotSell"); + } + + /// + /// Check if the user has set the option to sell their personal information. + /// + /// true if user has chosen an option to sell their personal information. + public static bool IsDoNotSellSet() + { + return MaxUnityPluginClass.CallStatic("isDoNotSellSet"); + } + + #endregion + + #region Banners + + /// + /// Create a new banner. + /// + /// Ad unit identifier of the banner to create + /// Banner position + public static void CreateBanner(string adUnitIdentifier, BannerPosition bannerPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create banner"); + MaxUnityPluginClass.CallStatic("createBanner", adUnitIdentifier, bannerPosition.ToSnakeCaseString()); + } + + /// + /// Create a new banner with a custom position. + /// + /// Ad unit identifier of the banner to create + /// The X coordinate (horizontal position) of the banner relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the banner relative to the top left corner of the screen. + /// + /// The banner is placed within the safe area of the screen. You can use this to get the absolute position of the banner on screen. + /// + public static void CreateBanner(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create banner"); + MaxUnityPluginClass.CallStatic("createBanner", adUnitIdentifier, x, y); + } + + /// + /// Load a new banner ad. + /// NOTE: The method loads the first banner ad and initiates an automated banner refresh process. + /// You only need to call this method if you pause banner refresh. + /// + /// Ad unit identifier of the banner to load + public static void LoadBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load banner"); + MaxUnityPluginClass.CallStatic("loadBanner", adUnitIdentifier); + } + + /// + /// Set the banner placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the banner to set the placement for + /// Placement to set + public static void SetBannerPlacement(string adUnitIdentifier, string placement) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner placement"); + MaxUnityPluginClass.CallStatic("setBannerPlacement", adUnitIdentifier, placement); + } + + /// + /// Starts or resumes auto-refreshing of the banner for the given ad unit identifier. + /// + /// Ad unit identifier of the banner for which to start auto-refresh + public static void StartBannerAutoRefresh(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "start banner auto-refresh"); + MaxUnityPluginClass.CallStatic("startBannerAutoRefresh", adUnitIdentifier); + } + + /// + /// Pauses auto-refreshing of the banner for the given ad unit identifier. + /// + /// Ad unit identifier of the banner for which to stop auto-refresh + public static void StopBannerAutoRefresh(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "stop banner auto-refresh"); + MaxUnityPluginClass.CallStatic("stopBannerAutoRefresh", adUnitIdentifier); + } + + /// + /// Updates the position of the banner to the new position provided. + /// + /// The ad unit identifier of the banner for which to update the position + /// A new position for the banner + public static void UpdateBannerPosition(string adUnitIdentifier, BannerPosition bannerPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update banner position"); + MaxUnityPluginClass.CallStatic("updateBannerPosition", adUnitIdentifier, bannerPosition.ToSnakeCaseString()); + } + + /// + /// Updates the position of the banner to the new coordinates provided. + /// + /// The ad unit identifier of the banner for which to update the position + /// The X coordinate (horizontal position) of the banner relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the banner relative to the top left corner of the screen. + /// + /// The banner is placed within the safe area of the screen. You can use this to get the absolute position of the banner on screen. + /// + public static void UpdateBannerPosition(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update banner position"); + MaxUnityPluginClass.CallStatic("updateBannerPosition", adUnitIdentifier, x, y); + } + + /// + /// Overrides the width of the banner in dp. + /// + /// The ad unit identifier of the banner for which to override the width for + /// The desired width of the banner in dp + public static void SetBannerWidth(string adUnitIdentifier, float width) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner width"); + MaxUnityPluginClass.CallStatic("setBannerWidth", adUnitIdentifier, width); + } + + /// + /// Show banner at a position determined by the 'CreateBanner' call. + /// + /// Ad unit identifier of the banner to show + public static void ShowBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show banner"); + MaxUnityPluginClass.CallStatic("showBanner", adUnitIdentifier); + } + + /// + /// Remove banner from the ad view and destroy it. + /// + /// Ad unit identifier of the banner to destroy + public static void DestroyBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy banner"); + MaxUnityPluginClass.CallStatic("destroyBanner", adUnitIdentifier); + } + + /// + /// Hide banner. + /// + /// Ad unit identifier of the banner to hide + /// + public static void HideBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide banner"); + MaxUnityPluginClass.CallStatic("hideBanner", adUnitIdentifier); + } + + /// + /// Set non-transparent background color for banners to be fully functional. + /// + /// Ad unit identifier of the banner to set background color for + /// A background color to set for the ad + /// + public static void SetBannerBackgroundColor(string adUnitIdentifier, Color color) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set background color"); + MaxUnityPluginClass.CallStatic("setBannerBackgroundColor", adUnitIdentifier, MaxSdkUtils.ParseColor(color)); + } + + /// + /// Set an extra parameter for the banner ad. + /// + /// Ad unit identifier of the banner to set the extra parameter for. + /// The key for the extra parameter. + /// The value for the extra parameter. + public static void SetBannerExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner extra parameter"); + MaxUnityPluginClass.CallStatic("setBannerExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// 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 extra parameter. Needs to be of type or null + 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); + } + + /// + /// The custom data to tie the showing banner ad to, for ILRD and rewarded postbacks via the {CUSTOM_DATA} macro. Maximum size is 8KB. + /// + /// Banner ad unit identifier of the banner to set the custom data for. + /// The custom data to be set. + public static void SetBannerCustomData(string adUnitIdentifier, string customData) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner custom data"); + MaxUnityPluginClass.CallStatic("setBannerCustomData", adUnitIdentifier, customData); + } + + /// + /// The banner position on the screen. When setting the banner position via or , + /// the banner is placed within the safe area of the screen. This returns the absolute position of the banner on screen. + /// + /// Ad unit identifier of the banner for which to get the position on screen. + /// A representing the banner position on screen. + public static Rect GetBannerLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get banner layout"); + var positionRect = MaxUnityPluginClass.CallStatic("getBannerLayout", adUnitIdentifier); + return GetRectFromString(positionRect); + } + + #endregion + + #region MRECs + + /// + /// Create a new MREC. + /// + /// Ad unit identifier of the MREC to create + /// MREC position + public static void CreateMRec(string adUnitIdentifier, AdViewPosition mrecPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create MREC"); + MaxUnityPluginClass.CallStatic("createMRec", adUnitIdentifier, mrecPosition.ToSnakeCaseString()); + } + + /// + /// Create a new MREC with a custom position. + /// + /// Ad unit identifier of the MREC to create + /// The X coordinate (horizontal position) of the MREC relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the MREC relative to the top left corner of the screen. + /// + /// The MREC is placed within the safe area of the screen. You can use this to get the absolute position Rect of the MREC on screen. + /// + public static void CreateMRec(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create MREC"); + MaxUnityPluginClass.CallStatic("createMRec", adUnitIdentifier, x, y); + } + + /// + /// Load a new MREC ad. + /// NOTE: The method loads the first MREC ad and initiates an automated MREC refresh process. + /// You only need to call this method if you pause MREC refresh. + /// + /// Ad unit identifier of the MREC to load + public static void LoadMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load MREC"); + MaxUnityPluginClass.CallStatic("loadMRec", adUnitIdentifier); + } + + /// + /// Set the MREC placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the MREC to set the placement for + /// Placement to set + public static void SetMRecPlacement(string adUnitIdentifier, string placement) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC placement"); + MaxUnityPluginClass.CallStatic("setMRecPlacement", adUnitIdentifier, placement); + } + + /// + /// Starts or resumes auto-refreshing of the MREC for the given ad unit identifier. + /// + /// Ad unit identifier of the MREC for which to start auto-refresh + public static void StartMRecAutoRefresh(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "start MREC auto-refresh"); + MaxUnityPluginClass.CallStatic("startMRecAutoRefresh", adUnitIdentifier); + } + + /// + /// Pauses auto-refreshing of the MREC for the given ad unit identifier. + /// + /// Ad unit identifier of the MREC for which to stop auto-refresh + public static void StopMRecAutoRefresh(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "stop MREC auto-refresh"); + MaxUnityPluginClass.CallStatic("stopMRecAutoRefresh", adUnitIdentifier); + } + + /// + /// Updates the position of the MREC to the new position provided. + /// + /// The ad unit identifier of the MREC for which to update the position + /// A new position for the MREC + public static void UpdateMRecPosition(string adUnitIdentifier, AdViewPosition mrecPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update MREC position"); + MaxUnityPluginClass.CallStatic("updateMRecPosition", adUnitIdentifier, mrecPosition.ToSnakeCaseString()); + } + + /// + /// Updates the position of the MREC to the new coordinates provided. + /// + /// The ad unit identifier of the MREC for which to update the position + /// The X coordinate (horizontal position) of the MREC relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the MREC relative to the top left corner of the screen. + /// + /// The MREC is placed within the safe area of the screen. You can use this to get the absolute position Rect of the MREC on screen. + /// + public static void UpdateMRecPosition(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update MREC position"); + MaxUnityPluginClass.CallStatic("updateMRecPosition", adUnitIdentifier, x, y); + } + + /// + /// Show MREC at a position determined by the 'CreateMRec' call. + /// + /// Ad unit identifier of the MREC to show + public static void ShowMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show MREC"); + MaxUnityPluginClass.CallStatic("showMRec", adUnitIdentifier); + } + + /// + /// Remove MREC from the ad view and destroy it. + /// + /// Ad unit identifier of the MREC to destroy + public static void DestroyMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy MREC"); + MaxUnityPluginClass.CallStatic("destroyMRec", adUnitIdentifier); + } + + /// + /// Hide MREC. + /// + /// Ad unit identifier of the MREC to hide + public static void HideMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide MREC"); + MaxUnityPluginClass.CallStatic("hideMRec", adUnitIdentifier); + } + + /// + /// Set an extra parameter for the MREC ad. + /// + /// Ad unit identifier of the MREC to set the extra parameter for. + /// The key for the extra parameter. + /// The value for the extra parameter. + public static void SetMRecExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC extra parameter"); + MaxUnityPluginClass.CallStatic("setMRecExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// 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 extra parameter. Needs to be of type or null + 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); + } + + /// + /// The custom data to tie the showing MREC ad to, for ILRD and rewarded postbacks via the {CUSTOM_DATA} macro. Maximum size is 8KB. + /// + /// MREC Ad unit identifier of the banner to set the custom data for. + /// The custom data to be set. + public static void SetMRecCustomData(string adUnitIdentifier, string customData) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC custom data"); + MaxUnityPluginClass.CallStatic("setMRecCustomData", adUnitIdentifier, customData); + } + + /// + /// The MREC position on the screen. When setting the banner position via or , + /// the banner is placed within the safe area of the screen. This returns the absolute position of the MREC on screen. + /// + /// Ad unit identifier of the MREC for which to get the position on screen. + /// A representing the banner position on screen. + public static Rect GetMRecLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get MREC layout"); + var positionRect = MaxUnityPluginClass.CallStatic("getMRecLayout", adUnitIdentifier); + return GetRectFromString(positionRect); + } + + #endregion + + #region Cross Promo Ads + + /// + /// Create a new cross promo ad with a custom position. + /// + /// Ad unit identifier of the cross promo ad to create + /// The X coordinate (horizontal position) of the cross promo ad relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the cross promo ad relative to the top left corner of the screen. + /// The width of the cross promo ad. + /// The height of the cross promo ad. + /// The rotation of the cross promo ad in degrees. + /// + /// The cross promo is placed within the safe area of the screen. You can use this to get the absolute position Rect of the cross promo ad on screen. + /// + public static void CreateCrossPromoAd(string adUnitIdentifier, float x, float y, float width, float height, float rotation) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create cross promo ad"); + MaxUnityPluginClass.CallStatic("createCrossPromoAd", adUnitIdentifier, x, y, width, height, rotation); + } + + /// + /// Set the cross promo ad placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the cross promo ad to set the placement for + /// Placement to set + public static void SetCrossPromoAdPlacement(string adUnitIdentifier, string placement) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set cross promo ad placement"); + MaxUnityPluginClass.CallStatic("setCrossPromoAdPlacement", adUnitIdentifier, placement); + } + + /// + /// Updates the position of the cross promo ad to the new coordinates provided. + /// + /// The ad unit identifier of the cross promo ad for which to update the position + /// The X coordinate (horizontal position) of the cross promo ad relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the cross promo ad relative to the top left corner of the screen. + /// The width of the cross promo ad. + /// The height of the cross promo ad. + /// The rotation of the cross promo ad in degrees. + /// + /// The cross promo ad is placed within the safe area of the screen. You can use this to get the absolute position Rect of the cross promo ad on screen. + /// + public static void UpdateCrossPromoAdPosition(string adUnitIdentifier, float x, float y, float width, float height, float rotation) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update cross promo ad position"); + MaxUnityPluginClass.CallStatic("updateCrossPromoAdPosition", adUnitIdentifier, x, y, width, height, rotation); + } + + /// + /// Show cross promo ad at a position determined by the 'CreateCrossPromoAd' call. + /// + /// Ad unit identifier of the cross promo ad to show + public static void ShowCrossPromoAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show cross promo ad"); + MaxUnityPluginClass.CallStatic("showCrossPromoAd", adUnitIdentifier); + } + + /// + /// Remove cross promo ad from the ad view and destroy it. + /// + /// Ad unit identifier of the cross promo ad to destroy + public static void DestroyCrossPromoAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy cross promo ad"); + MaxUnityPluginClass.CallStatic("destroyCrossPromoAd", adUnitIdentifier); + } + + /// + /// Hide cross promo ad. + /// + /// Ad unit identifier of the cross promo ad to hide + public static void HideCrossPromoAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide cross promo ad"); + MaxUnityPluginClass.CallStatic("hideCrossPromoAd", adUnitIdentifier); + } + + /// + /// The cross promo ad position on the screen. When setting the cross promo ad position via or , + /// the cross promo ad is placed within the safe area of the screen. This returns the absolute position of the cross promo ad on screen. + /// + /// Ad unit identifier of the cross promo ad for which to get the position on screen. + /// A representing the banner position on screen. + public static Rect GetCrossPromoAdLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get cross promo ad layout"); + var positionRect = MaxUnityPluginClass.CallStatic("getCrossPromoAdLayout", adUnitIdentifier); + return GetRectFromString(positionRect); + } + + #endregion + + #region Interstitials + + /// + /// Start loading an interstitial. + /// + /// Ad unit identifier of the interstitial to load + public static void LoadInterstitial(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load interstitial"); + MaxUnityPluginClass.CallStatic("loadInterstitial", adUnitIdentifier); + } + + /// + /// Check if interstitial ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the interstitial to load + /// True if the ad is ready to be displayed + public static bool IsInterstitialReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check interstitial loaded"); + return MaxUnityPluginClass.CallStatic("isInterstitialReady", adUnitIdentifier); + } + + /// + /// Present loaded interstitial for a given placement to tie ad events to. Note: if the interstitial is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the interstitial to load + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowInterstitial(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show interstitial"); + + if (IsInterstitialReady(adUnitIdentifier)) + { + MaxUnityPluginClass.CallStatic("showInterstitial", adUnitIdentifier, placement, customData); + } + else + { + MaxSdkLogger.UserWarning("Not showing MAX Ads interstitial: ad not ready"); + } + } + + /// + /// Set an extra parameter for the ad. + /// + /// Ad unit identifier of the interstitial to set the extra parameter for. + /// The key for the extra parameter. + /// The value for the extra parameter. + public static void SetInterstitialExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set interstitial extra parameter"); + MaxUnityPluginClass.CallStatic("setInterstitialExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// 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 extra parameter. Needs to be of type or null + 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); + } + + #endregion + + #region App Open + + /// + /// Start loading an app open ad. + /// + /// Ad unit identifier of the app open ad to load + public static void LoadAppOpenAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load app open ad"); + MaxUnityPluginClass.CallStatic("loadAppOpenAd", adUnitIdentifier); + } + + /// + /// Check if app open ad ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the app open ad to load + /// True if the ad is ready to be displayed + public static bool IsAppOpenAdReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check app open ad loaded"); + return MaxUnityPluginClass.CallStatic("isAppOpenAdReady", adUnitIdentifier); + } + + /// + /// Present loaded app open ad for a given placement to tie ad events to. Note: if the app open ad is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the app open ad to load + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowAppOpenAd(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show app open ad"); + + if (IsAppOpenAdReady(adUnitIdentifier)) + { + MaxUnityPluginClass.CallStatic("showAppOpenAd", adUnitIdentifier, placement, customData); + } + else + { + MaxSdkLogger.UserWarning("Not showing MAX Ads app open ad: ad not ready"); + } + } + + /// + /// Set an extra parameter for the ad. + /// + /// Ad unit identifier of the app open ad to set the extra parameter for. + /// The key for the extra parameter. + /// The value for the extra parameter. + public static void SetAppOpenAdExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set app open ad extra parameter"); + MaxUnityPluginClass.CallStatic("setAppOpenAdExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// 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 extra parameter. Needs to be of type or null + 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); + } + + #endregion + + #region Rewarded + + /// + /// Start loading an rewarded ad. + /// + /// Ad unit identifier of the rewarded ad to load + public static void LoadRewardedAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load rewarded ad"); + MaxUnityPluginClass.CallStatic("loadRewardedAd", adUnitIdentifier); + } + + /// + /// Check if rewarded ad ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the rewarded ad to load + /// True if the ad is ready to be displayed + public static bool IsRewardedAdReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check rewarded ad loaded"); + return MaxUnityPluginClass.CallStatic("isRewardedAdReady", adUnitIdentifier); + } + + /// ready to be + /// Present loaded rewarded ad for a given placement to tie ad events to. Note: if the rewarded ad is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the interstitial to load + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowRewardedAd(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show rewarded ad"); + + if (IsRewardedAdReady(adUnitIdentifier)) + { + MaxUnityPluginClass.CallStatic("showRewardedAd", adUnitIdentifier, placement, customData); + } + else + { + MaxSdkLogger.UserWarning("Not showing MAX Ads rewarded ad: ad not ready"); + } + } + + /// + /// Set an extra parameter for the ad. + /// + /// Ad unit identifier of the rewarded to set the extra parameter for. + /// The key for the extra parameter. + /// The value for the extra parameter. + public static void SetRewardedAdExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded ad extra parameter"); + MaxUnityPluginClass.CallStatic("setRewardedAdExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// Set a local extra parameter for the ad. + /// + /// 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 + 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); + } + + #endregion + + #region Rewarded Interstitial + + /// + /// Start loading an rewarded interstitial ad. + /// + /// Ad unit identifier of the rewarded interstitial ad to load + public static void LoadRewardedInterstitialAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load rewarded interstitial ad"); + MaxUnityPluginClass.CallStatic("loadRewardedInterstitialAd", adUnitIdentifier); + } + + /// + /// Check if rewarded interstitial ad ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the rewarded interstitial ad to load + /// True if the ad is ready to be displayed + public static bool IsRewardedInterstitialAdReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check rewarded interstitial ad loaded"); + return MaxUnityPluginClass.CallStatic("isRewardedInterstitialAdReady", adUnitIdentifier); + } + + /// + /// Present loaded rewarded interstitial ad for a given placement to tie ad events to. Note: if the rewarded interstitial ad is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the rewarded interstitial to show + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowRewardedInterstitialAd(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show rewarded interstitial ad"); + + if (IsRewardedInterstitialAdReady(adUnitIdentifier)) + { + MaxUnityPluginClass.CallStatic("showRewardedInterstitialAd", adUnitIdentifier, placement, customData); + } + else + { + MaxSdkLogger.UserWarning("Not showing MAX Ads rewarded interstitial ad: ad not ready"); + } + } + + /// + /// Set an extra parameter for the ad. + /// + /// Ad unit identifier of the rewarded interstitial to set the extra parameter for. + /// The key for the extra parameter. + /// The value for the extra parameter. + public static void SetRewardedInterstitialAdExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded interstitial ad extra parameter"); + MaxUnityPluginClass.CallStatic("setRewardedInterstitialAdExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// Set a local extra parameter for the ad. + /// + /// 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 + 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); + } + + #endregion + + #region Event Tracking + + /// + /// Track an event using AppLovin. + /// + /// An event from the list of pre-defined events may be found in MaxEvents.cs as part of the AppLovin SDK framework. + /// A dictionary containing key-value pairs further describing this event. + public static void TrackEvent(string name, IDictionary parameters = null) + { + MaxUnityPluginClass.CallStatic("trackEvent", name, Json.Serialize(parameters)); + } + + #endregion + + #region Settings + + /// + /// Set whether to begin video ads in a muted state or not. + /// + /// Please call this method after the SDK has initialized. + /// + /// true if video ads should being in muted state. + public static void SetMuted(bool muted) + { + MaxUnityPluginClass.CallStatic("setMuted", muted); + } + + /// + /// Whether video ads begin in a muted state or not. Defaults to false. + /// + /// Note: Returns false if the SDK is not initialized. + /// + /// true if video ads begin in muted state. + public static bool IsMuted() + { + return MaxUnityPluginClass.CallStatic("isMuted"); + } + + /// + /// Toggle verbose logging of AppLovin SDK. If enabled AppLovin messages will appear in standard application log accessible via logcat. All log messages will have "AppLovinSdk" tag. + /// + /// true if verbose logging should be enabled. + public static void SetVerboseLogging(bool enabled) + { + MaxUnityPluginClass.CallStatic("setVerboseLogging", enabled); + } + + /// + /// Whether or not verbose logging is enabled. + /// + /// true if verbose logging is enabled. + public static bool IsVerboseLoggingEnabled() + { + return MaxUnityPluginClass.CallStatic("isVerboseLoggingEnabled"); + } + + /// + /// Whether the creative debugger will be displayed on fullscreen ads after flipping the device screen down twice. Defaults to true. + /// + /// true if the creative debugger should be enabled. + public static void SetCreativeDebuggerEnabled(bool enabled) + { + MaxUnityPluginClass.CallStatic("setCreativeDebuggerEnabled", enabled); + } + + /// + /// Enable devices to receive test ads, by passing in the advertising identifier (IDFA/GAID) of each test device. + /// Refer to AppLovin logs for the IDFA/GAID of your current device. + /// + /// String list of advertising identifiers from devices to receive test ads. + public static void SetTestDeviceAdvertisingIdentifiers(string[] advertisingIdentifiers) + { + if (IsInitialized()) + { + MaxSdkLogger.UserError("Test Device Advertising Identifiers must be set before SDK initialization."); + return; + } + + // Wrap the string array in an object array, so the compiler does not split into multiple strings. + object[] arguments = {advertisingIdentifiers}; + MaxUnityPluginClass.CallStatic("setTestDeviceAdvertisingIds", arguments); + } + + /// + /// Whether or not the native AppLovin SDKs listen to exceptions. Defaults to true. + /// + /// true if the native AppLovin SDKs should not listen to exceptions. + public static void SetExceptionHandlerEnabled(bool enabled) + { + MaxUnityPluginClass.CallStatic("setExceptionHandlerEnabled", enabled); + } + + /// + /// Whether or not AppLovin SDK will collect the device location if available. Defaults to true. + /// + /// true if AppLovin SDK should collect the device location if available. + public static void SetLocationCollectionEnabled(bool enabled) + { + MaxUnityPluginClass.CallStatic("setLocationCollectionEnabled", enabled); + } + + /// + /// Set an extra parameter to pass to the AppLovin server. + /// + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. May be null. + public static void SetExtraParameter(string key, string value) + { + MaxUnityPluginClass.CallStatic("setExtraParameter", key, value); + } + + #endregion + + #region Private + + internal static void SetUserSegmentField(string name, string value) + { + MaxUnityPluginClass.CallStatic("setUserSegmentField", name, value); + } + + internal static void SetTargetingDataYearOfBirth(int yearOfBirth) + { + MaxUnityPluginClass.CallStatic("setTargetingDataYearOfBirth", yearOfBirth); + } + + internal static void SetTargetingDataGender(String gender) + { + MaxUnityPluginClass.CallStatic("setTargetingDataGender", gender); + } + + internal static void SetTargetingDataMaximumAdContentRating(int maximumAdContentRating) + { + MaxUnityPluginClass.CallStatic("setTargetingDataMaximumAdContentRating", maximumAdContentRating); + } + + internal static void SetTargetingDataEmail(string email) + { + MaxUnityPluginClass.CallStatic("setTargetingDataEmail", email); + } + + internal static void SetTargetingDataPhoneNumber(string phoneNumber) + { + MaxUnityPluginClass.CallStatic("setTargetingDataPhoneNumber", phoneNumber); + } + + internal static void SetTargetingDataKeywords(string[] keywords) + { + // Wrap the string array in an object array, so the compiler does not split into multiple strings. + object[] arguments = {keywords}; + MaxUnityPluginClass.CallStatic("setTargetingDataKeywords", arguments); + } + + internal static void SetTargetingDataInterests(string[] interests) + { + // Wrap the string array in an object array, so the compiler does not split into multiple strings. + object[] arguments = {interests}; + MaxUnityPluginClass.CallStatic("setTargetingDataInterests", arguments); + } + + internal static void ClearAllTargetingData() + { + MaxUnityPluginClass.CallStatic("clearAllTargetingData"); + } + + #endregion + + #region Obsolete + + [Obsolete("This method has been deprecated. Please use `GetSdkConfiguration().ConsentDialogState`")] + public static ConsentDialogState GetConsentDialogState() + { + if (!IsInitialized()) + { + MaxSdkLogger.UserWarning( + "MAX Ads SDK has not been initialized yet. GetConsentDialogState() may return ConsentDialogState.Unknown"); + } + + return (ConsentDialogState) MaxUnityPluginClass.CallStatic("getConsentDialogState"); + } + + [Obsolete("This method has been deprecated. The AdInfo object is returned with ad callbacks.")] + public static AdInfo GetAdInfo(string adUnitIdentifier) + { + var adInfoString = MaxUnityPluginClass.CallStatic("getAdInfo", adUnitIdentifier); + + if (string.IsNullOrEmpty(adInfoString)) return null; + + var adInfoDictionary = Json.Deserialize(adInfoString) as Dictionary; + return new AdInfo(adInfoDictionary); + } + + #endregion + + internal class BackgroundCallbackProxy : AndroidJavaProxy + { + public BackgroundCallbackProxy() : base("com.applovin.mediation.unity.MaxUnityAdManager$BackgroundCallback") { } + + public void onEvent(string propsStr) + { + HandleBackgroundCallback(propsStr); + } + } +} diff --git a/MaxSdk/Scripts/MaxSdkAndroid.cs.meta b/MaxSdk/Scripts/MaxSdkAndroid.cs.meta new file mode 100644 index 0000000..c5cacde --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkAndroid.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: e64643507f25d48268e8df04710b9dec +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdkAndroid.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxSdkBase.cs b/MaxSdk/Scripts/MaxSdkBase.cs new file mode 100644 index 0000000..539e4cf --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkBase.cs @@ -0,0 +1,772 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using AppLovinMax.ThirdParty.MiniJson; +using UnityEngine; + +#if UNITY_IOS && !UNITY_EDITOR +using System.Runtime.InteropServices; +#endif + +public abstract class MaxSdkBase +{ + // Shared Properties + protected static readonly MaxUserSegment SharedUserSegment = new MaxUserSegment(); + protected static readonly MaxTargetingData SharedTargetingData = new MaxTargetingData(); + + +#if UNITY_EDITOR || UNITY_IPHONE || UNITY_IOS + /// + /// App tracking status values. Primarily used in conjunction with iOS14's AppTrackingTransparency.framework. + /// + public enum AppTrackingStatus + { + /// + /// Device is on < iOS14, AppTrackingTransparency.framework is not available. + /// + Unavailable, + + /// + /// The value returned if a user has not yet received an authorization request to authorize access to app-related data that can be used for tracking the user or the device. + /// + NotDetermined, + + /// + /// The value returned if authorization to access app-related data that can be used for tracking the user or the device is restricted. + /// + Restricted, + + /// + /// The value returned if the user denies authorization to access app-related data that can be used for tracking the user or the device. + /// + Denied, + + /// + /// The value returned if the user authorizes access to app-related data that can be used for tracking the user or the device. + /// + Authorized, + } +#endif + + public enum AdViewPosition + { + TopLeft, + TopCenter, + TopRight, + Centered, + CenterLeft, + CenterRight, + BottomLeft, + BottomCenter, + BottomRight + } + + public enum BannerPosition + { + TopLeft, + TopCenter, + TopRight, + Centered, + CenterLeft, + CenterRight, + BottomLeft, + BottomCenter, + BottomRight + } + + public class SdkConfiguration + { + /// + /// Whether or not the SDK has been initialized successfully. + /// + public bool IsSuccessfullyInitialized { get; private set; } + + /// + /// Get the country code for this user. + /// + public string CountryCode { get; private set; } + +#if UNITY_EDITOR || UNITY_IPHONE || UNITY_IOS + /// + /// App tracking status values. Primarily used in conjunction with iOS14's AppTrackingTransparency.framework. + /// + public AppTrackingStatus AppTrackingStatus { get; private set; } +#endif + + public bool IsTestModeEnabled { get; private set; } + + [Obsolete("This API has been deprecated and will be removed in a future release.")] + public ConsentDialogState ConsentDialogState { get; private set; } + +#if UNITY_EDITOR || !(UNITY_ANDROID || UNITY_IPHONE || UNITY_IOS) + public static SdkConfiguration CreateEmpty() + { + var sdkConfiguration = new SdkConfiguration(); + sdkConfiguration.IsSuccessfullyInitialized = true; +#pragma warning disable 0618 + sdkConfiguration.ConsentDialogState = ConsentDialogState.Unknown; +#pragma warning restore 0618 +#if UNITY_EDITOR + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Authorized; +#endif + var currentRegion = RegionInfo.CurrentRegion; + sdkConfiguration.CountryCode = currentRegion != null ? currentRegion.TwoLetterISORegionName : "US"; + sdkConfiguration.IsTestModeEnabled = false; + + return sdkConfiguration; + } +#endif + + public static SdkConfiguration Create(IDictionary eventProps) + { + var sdkConfiguration = new SdkConfiguration(); + + sdkConfiguration.IsSuccessfullyInitialized = MaxSdkUtils.GetBoolFromDictionary(eventProps, "isSuccessfullyInitialized"); + sdkConfiguration.CountryCode = MaxSdkUtils.GetStringFromDictionary(eventProps, "countryCode", ""); + sdkConfiguration.IsTestModeEnabled = MaxSdkUtils.GetBoolFromDictionary(eventProps, "isTestModeEnabled"); + +#pragma warning disable 0618 + var consentDialogStateStr = MaxSdkUtils.GetStringFromDictionary(eventProps, "consentDialogState", ""); + if ("1".Equals(consentDialogStateStr)) + { + sdkConfiguration.ConsentDialogState = ConsentDialogState.Applies; + } + else if ("2".Equals(consentDialogStateStr)) + { + sdkConfiguration.ConsentDialogState = ConsentDialogState.DoesNotApply; + } + else + { + sdkConfiguration.ConsentDialogState = ConsentDialogState.Unknown; + } +#pragma warning restore 0618 + +#if UNITY_IPHONE || UNITY_IOS + var appTrackingStatusStr = MaxSdkUtils.GetStringFromDictionary(eventProps, "appTrackingStatus", "-1"); + if ("-1".Equals(appTrackingStatusStr)) + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Unavailable; + } + else if ("0".Equals(appTrackingStatusStr)) + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.NotDetermined; + } + else if ("1".Equals(appTrackingStatusStr)) + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Restricted; + } + else if ("2".Equals(appTrackingStatusStr)) + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Denied; + } + else // "3" is authorized + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Authorized; + } +#endif + + return sdkConfiguration; + } + } + + public struct Reward + { + public string Label; + public int Amount; + + public override string ToString() + { + return "Reward: " + Amount + " " + Label; + } + + public bool IsValid() + { + return !string.IsNullOrEmpty(Label) && Amount > 0; + } + } + + /** + * This enum contains various error codes that the SDK can return when a MAX ad fails to load or display. + */ + public enum ErrorCode + { + /// + /// This error code represents an error that could not be categorized into one of the other defined errors. See the message field in the error object for more details. + /// + Unspecified = -1, + + /// + /// This error code indicates that MAX returned no eligible ads from any mediated networks for this app/device. + /// + NoFill = 204, + + /// + /// This error code indicates that MAX returned eligible ads from mediated networks, but all ads failed to load. See the adLoadFailureInfo field in the error object for more details. + /// + AdLoadFailed = -5001, + + /// + /// This error code represents an error that was encountered when showing an ad. + /// + AdDisplayFailed = -4205, + + /// + /// This error code indicates that the ad request failed due to a generic network error. See the message field in the error object for more details. + /// + NetworkError = -1000, + + /// + /// This error code indicates that the ad request timed out due to a slow internet connection. + /// + NetworkTimeout = -1001, + + /// + /// This error code indicates that the ad request failed because the device is not connected to the internet. + /// + NoNetwork = -1009, + + /// + /// This error code indicates that you attempted to show a fullscreen ad while another fullscreen ad is still showing. + /// + FullscreenAdAlreadyShowing = -23, + + /// + /// This error code indicates you are attempting to show a fullscreen ad before the one has been loaded. + /// + FullscreenAdNotReady = -24, + +#if UNITY_ANDROID + /// + /// This error code indicates that the SDK failed to load an ad because it could not find the top Activity. + /// + NoActivity = -5601, + + /// + /// This error code indicates that the SDK failed to display an ad because the user has the "Don't Keep Activities" developer setting enabled. + /// + DontKeepActivitiesEnabled = -5602, +#endif + } + + /** + * This enum contains possible states of an ad in the waterfall the adapter response info could represent. + */ + public enum MaxAdLoadState + { + /// + /// The AppLovin Max SDK did not attempt to load an ad from this network in the waterfall because an ad higher + /// in the waterfall loaded successfully. + /// + AdLoadNotAttempted, + + /// + /// An ad successfully loaded from this network. + /// + AdLoaded, + + /// + /// An ad failed to load from this network. + /// + FailedToLoad + } + + public class AdInfo + { + public string AdUnitIdentifier { get; private set; } + public string AdFormat { get; private set; } + public string NetworkName { get; private set; } + public string NetworkPlacement { get; private set; } + public string Placement { get; private set; } + public string CreativeIdentifier { get; private set; } + public double Revenue { get; private set; } + public string RevenuePrecision { get; private set; } + public WaterfallInfo WaterfallInfo { get; private set; } + public string DspName { get; private set; } + + public AdInfo(IDictionary adInfoDictionary) + { + AdUnitIdentifier = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "adUnitId"); + AdFormat = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "adFormat"); + NetworkName = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "networkName"); + NetworkPlacement = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "networkPlacement"); + CreativeIdentifier = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "creativeId"); + Placement = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "placement"); + Revenue = MaxSdkUtils.GetDoubleFromDictionary(adInfoDictionary, "revenue", -1); + RevenuePrecision = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "revenuePrecision"); + WaterfallInfo = new WaterfallInfo(MaxSdkUtils.GetDictionaryFromDictionary(adInfoDictionary, "waterfallInfo", new Dictionary())); + DspName = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "dspName"); + } + + public override string ToString() + { + return "[AdInfo adUnitIdentifier: " + AdUnitIdentifier + + ", adFormat: " + AdFormat + + ", networkName: " + NetworkName + + ", networkPlacement: " + NetworkPlacement + + ", creativeIdentifier: " + CreativeIdentifier + + ", placement: " + Placement + + ", revenue: " + Revenue + + ", revenuePrecision: " + RevenuePrecision + + ", dspName: " + DspName + "]"; + } + } + + /// + /// Returns information about the ad response in a waterfall. + /// + public class WaterfallInfo + { + public String Name { get; private set; } + public String TestName { get; private set; } + public List NetworkResponses { get; private set; } + public long LatencyMillis { get; private set; } + + public WaterfallInfo(IDictionary waterfallInfoDict) + { + Name = MaxSdkUtils.GetStringFromDictionary(waterfallInfoDict, "name"); + TestName = MaxSdkUtils.GetStringFromDictionary(waterfallInfoDict, "testName"); + + var networkResponsesList = MaxSdkUtils.GetListFromDictionary(waterfallInfoDict, "networkResponses", new List()); + NetworkResponses = new List(); + foreach (var networkResponseObject in networkResponsesList) + { + var networkResponseDict = networkResponseObject as Dictionary; + if (networkResponseDict == null) continue; + + var networkResponse = new NetworkResponseInfo(networkResponseDict); + NetworkResponses.Add(networkResponse); + } + + LatencyMillis = MaxSdkUtils.GetLongFromDictionary(waterfallInfoDict, "latencyMillis"); + } + + public override string ToString() + { + return "[MediatedNetworkInfo: name = " + Name + + ", testName = " + TestName + + ", latency = " + LatencyMillis + + ", networkResponse = " + string.Join(", ", NetworkResponses.Select(networkResponseInfo => networkResponseInfo.ToString()).ToArray()) + "]"; + } + } + + public class NetworkResponseInfo + { + public MaxAdLoadState AdLoadState { get; private set; } + public MediatedNetworkInfo MediatedNetwork { get; private set; } + public Dictionary Credentials { get; private set; } + public bool IsBidding { get; private set; } + public long LatencyMillis { get; private set; } + public ErrorInfo Error { get; private set; } + + public NetworkResponseInfo(IDictionary networkResponseInfoDict) + { + var mediatedNetworkInfoDict = MaxSdkUtils.GetDictionaryFromDictionary(networkResponseInfoDict, "mediatedNetwork"); + MediatedNetwork = mediatedNetworkInfoDict != null ? new MediatedNetworkInfo(mediatedNetworkInfoDict) : null; + + Credentials = MaxSdkUtils.GetDictionaryFromDictionary(networkResponseInfoDict, "credentials", new Dictionary()); + IsBidding = MaxSdkUtils.GetBoolFromDictionary(networkResponseInfoDict, "isBidding"); + LatencyMillis = MaxSdkUtils.GetLongFromDictionary(networkResponseInfoDict, "latencyMillis"); + AdLoadState = (MaxAdLoadState) MaxSdkUtils.GetIntFromDictionary(networkResponseInfoDict, "adLoadState"); + + var errorInfoDict = MaxSdkUtils.GetDictionaryFromDictionary(networkResponseInfoDict, "error"); + Error = errorInfoDict != null ? new ErrorInfo(errorInfoDict) : null; + } + + public override string ToString() + { + var stringBuilder = new StringBuilder("[NetworkResponseInfo: adLoadState = ").Append(AdLoadState); + stringBuilder.Append(", mediatedNetwork = ").Append(MediatedNetwork); + stringBuilder.Append(", credentials = ").Append(string.Join(", ", Credentials.Select(keyValuePair => keyValuePair.ToString()).ToArray())); + + switch (AdLoadState) + { + case MaxAdLoadState.FailedToLoad: + stringBuilder.Append(", error = ").Append(Error); + break; + case MaxAdLoadState.AdLoaded: + stringBuilder.Append(", latency = ").Append(LatencyMillis); + break; + } + + return stringBuilder.Append("]").ToString(); + } + } + + public class MediatedNetworkInfo + { + public string Name { get; private set; } + public string AdapterClassName { get; private set; } + public string AdapterVersion { get; private set; } + public string SdkVersion { get; private set; } + + public MediatedNetworkInfo(IDictionary mediatedNetworkDictionary) + { + // NOTE: Unity Editor creates empty string + Name = MaxSdkUtils.GetStringFromDictionary(mediatedNetworkDictionary, "name", ""); + AdapterClassName = MaxSdkUtils.GetStringFromDictionary(mediatedNetworkDictionary, "adapterClassName", ""); + AdapterVersion = MaxSdkUtils.GetStringFromDictionary(mediatedNetworkDictionary, "adapterVersion", ""); + SdkVersion = MaxSdkUtils.GetStringFromDictionary(mediatedNetworkDictionary, "sdkVersion", ""); + } + + public override string ToString() + { + return "[MediatedNetworkInfo name: " + Name + + ", adapterClassName: " + AdapterClassName + + ", adapterVersion: " + AdapterVersion + + ", sdkVersion: " + SdkVersion + "]"; + } + } + + public class ErrorInfo + { + public ErrorCode Code { get; private set; } + public string Message { get; private set; } + public int MediatedNetworkErrorCode { get; private set; } + public string MediatedNetworkErrorMessage { get; private set; } + public string AdLoadFailureInfo { get; private set; } + public WaterfallInfo WaterfallInfo { get; private set; } + + public ErrorInfo(IDictionary errorInfoDictionary) + { + Code = (ErrorCode) MaxSdkUtils.GetIntFromDictionary(errorInfoDictionary, "errorCode", -1); + Message = MaxSdkUtils.GetStringFromDictionary(errorInfoDictionary, "errorMessage", ""); + MediatedNetworkErrorCode = MaxSdkUtils.GetIntFromDictionary(errorInfoDictionary, "mediatedNetworkErrorCode", (int) ErrorCode.Unspecified); + MediatedNetworkErrorMessage = MaxSdkUtils.GetStringFromDictionary(errorInfoDictionary, "mediatedNetworkErrorMessage", ""); + AdLoadFailureInfo = MaxSdkUtils.GetStringFromDictionary(errorInfoDictionary, "adLoadFailureInfo", ""); + WaterfallInfo = new WaterfallInfo(MaxSdkUtils.GetDictionaryFromDictionary(errorInfoDictionary, "waterfallInfo", new Dictionary())); + } + + public override string ToString() + { + var stringbuilder = new StringBuilder("[ErrorInfo code: ").Append(Code); + stringbuilder.Append(", message: ").Append(Message); + + if (Code == ErrorCode.AdDisplayFailed) + { + stringbuilder.Append(", mediatedNetworkCode: ").Append(MediatedNetworkErrorCode); + stringbuilder.Append(", mediatedNetworkMessage: ").Append(MediatedNetworkErrorMessage); + } + + return stringbuilder.Append(", adLoadFailureInfo: ").Append(AdLoadFailureInfo).Append("]").ToString(); + } + } + + protected static void ValidateAdUnitIdentifier(string adUnitIdentifier, string debugPurpose) + { + if (string.IsNullOrEmpty(adUnitIdentifier)) + { + MaxSdkLogger.UserError("No MAX Ads Ad Unit ID specified for: " + debugPurpose); + } + } + + // Allocate the MaxSdkCallbacks singleton, which receives all callback events from the native SDKs. + protected static void InitCallbacks() + { + var type = typeof(MaxSdkCallbacks); + var mgr = new GameObject("MaxSdkCallbacks", type) + .GetComponent(); // Its Awake() method sets Instance. + if (MaxSdkCallbacks.Instance != mgr) + { + MaxSdkLogger.UserWarning("It looks like you have the " + type.Name + " on a GameObject in your scene. Please remove the script from your scene."); + } + } + + /// + /// Generates serialized Unity meta data to be passed to the SDK. + /// + /// Serialized Unity meta data. + protected static string GenerateMetaData() + { + var metaData = new Dictionary(2); + metaData.Add("UnityVersion", Application.unityVersion); + + var graphicsMemorySize = SystemInfo.graphicsMemorySize; + metaData.Add("GraphicsMemorySizeMegabytes", graphicsMemorySize.ToString()); + + return Json.Serialize(metaData); + } + + /// + /// Parses the prop string provided to a . + /// + /// A prop string representing a Rect + /// A the prop string represents. + protected static Rect GetRectFromString(string rectPropString) + { + var rectDict = Json.Deserialize(rectPropString) as Dictionary; + var originX = MaxSdkUtils.GetFloatFromDictionary(rectDict, "origin_x", 0); + var originY = MaxSdkUtils.GetFloatFromDictionary(rectDict, "origin_y", 0); + var width = MaxSdkUtils.GetFloatFromDictionary(rectDict, "width", 0); + var height = MaxSdkUtils.GetFloatFromDictionary(rectDict, "height", 0); + + return new Rect(originX, originY, width, height); + } + + /// + /// Handles forwarding callbacks from native to C#. + /// + /// A prop string with the event data + protected static void HandleBackgroundCallback(string propsStr) + { + try + { + MaxSdkCallbacks.Instance.ForwardEvent(propsStr); + } + catch (Exception exception) + { + var eventProps = Json.Deserialize(propsStr) as Dictionary; + if (eventProps == null) return; + + var eventName = MaxSdkUtils.GetStringFromDictionary(eventProps, "name", ""); + MaxSdkLogger.UserError("Unable to notify ad delegate due to an error in the publisher callback '" + eventName + "' due to exception: " + exception.Message); + Debug.LogException(exception); + } + } + + [Obsolete("This API has been deprecated and will be removed in a future release.")] + public enum ConsentDialogState + { + Unknown, + Applies, + DoesNotApply + } +} + +/// +/// An extension class for and enums. +/// +internal static class AdPositionExtenstion +{ + public static string ToSnakeCaseString(this MaxSdkBase.BannerPosition position) + { + if (position == MaxSdkBase.BannerPosition.TopLeft) + { + return "top_left"; + } + else if (position == MaxSdkBase.BannerPosition.TopCenter) + { + return "top_center"; + } + else if (position == MaxSdkBase.BannerPosition.TopRight) + { + return "top_right"; + } + else if (position == MaxSdkBase.BannerPosition.Centered) + { + return "centered"; + } + else if (position == MaxSdkBase.BannerPosition.CenterLeft) + { + return "center_left"; + } + else if (position == MaxSdkBase.BannerPosition.CenterRight) + { + return "center_right"; + } + else if (position == MaxSdkBase.BannerPosition.BottomLeft) + { + return "bottom_left"; + } + else if (position == MaxSdkBase.BannerPosition.BottomCenter) + { + return "bottom_center"; + } + else // position == MaxSdkBase.BannerPosition.BottomRight + { + return "bottom_right"; + } + } + + public static string ToSnakeCaseString(this MaxSdkBase.AdViewPosition position) + { + if (position == MaxSdkBase.AdViewPosition.TopLeft) + { + return "top_left"; + } + else if (position == MaxSdkBase.AdViewPosition.TopCenter) + { + return "top_center"; + } + else if (position == MaxSdkBase.AdViewPosition.TopRight) + { + return "top_right"; + } + else if (position == MaxSdkBase.AdViewPosition.Centered) + { + return "centered"; + } + else if (position == MaxSdkBase.AdViewPosition.CenterLeft) + { + return "center_left"; + } + else if (position == MaxSdkBase.AdViewPosition.CenterRight) + { + return "center_right"; + } + else if (position == MaxSdkBase.AdViewPosition.BottomLeft) + { + return "bottom_left"; + } + else if (position == MaxSdkBase.AdViewPosition.BottomCenter) + { + return "bottom_center"; + } + else // position == MaxSdkBase.AdViewPosition.BottomRight + { + return "bottom_right"; + } + } +} + +namespace AppLovinMax.Internal.API +{ + 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) + { + 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); + } + + private CFError(int code, string message) + { + Code = code; + Message = message; + } + + public override string ToString() + { + return "[CFError Code: " + Code + + ", Message: " + Message + "]"; + } + } + + 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. + /// + 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)) + { + return CFType.Standard; + } + 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. + public static void SCF(Action onFlowCompletedAction) + { + OnConsentFlowCompletedAction = onFlowCompletedAction; + +#if UNITY_EDITOR + var errorDict = new Dictionary() + { + {"code", CFError.ErrorCodeUnspecified}, + {"message", "Consent flow is not supported in Unity Editor."} + }; + + 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)); + } + } +} diff --git a/MaxSdk/Scripts/MaxSdkBase.cs.meta b/MaxSdk/Scripts/MaxSdkBase.cs.meta new file mode 100644 index 0000000..5874250 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkBase.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 0822c80ecfc5248e2b853d8d5b449fb3 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdkBase.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxSdkCallbacks.cs b/MaxSdk/Scripts/MaxSdkCallbacks.cs new file mode 100644 index 0000000..d4ade54 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkCallbacks.cs @@ -0,0 +1,1828 @@ +/** + * This is is a global Unity object that is used to forward callbacks from native iOS / Android Max code to the application. + */ + +using System; +using System.Collections.Generic; +using System.Globalization; +using UnityEngine; +using AppLovinMax.Internal.API; +using AppLovinMax.ThirdParty.MiniJson; + +public class MaxSdkCallbacks : MonoBehaviour +{ +#if UNITY_EDITOR + private static MaxSdkCallbacks instance; +#endif + + public static MaxSdkCallbacks Instance + { +#if UNITY_EDITOR + get + { + if (instance != null) return instance; + + instance = new GameObject("MaxSdkCallbacks", typeof(MaxSdkCallbacks)).GetComponent(); + DontDestroyOnLoad(instance); + + return instance; + } +#else + get; private set; +#endif + } + + // Fired when the SDK has finished initializing + private static Action _onSdkInitializedEvent; + public static event Action OnSdkInitializedEvent + { + add + { + LogSubscribedToEvent("OnSdkInitializedEvent"); + _onSdkInitializedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnSdkInitializedEvent"); + _onSdkInitializedEvent -= value; + } + } + + // 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 + { + add + { + LogSubscribedToEvent("OnSdkConsentDialogDismissedEvent"); + _onSdkConsentDialogDismissedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnSdkConsentDialogDismissedEvent"); + _onSdkConsentDialogDismissedEvent -= value; + } + } + + private static Action _onInterstitialAdLoadedEventV2; + private static Action _onInterstitialAdLoadFailedEventV2; + private static Action _onInterstitialAdDisplayedEventV2; + private static Action _onInterstitialAdFailedToDisplayEventV2; + private static Action _onInterstitialAdClickedEventV2; + private static Action _onInterstitialAdRevenuePaidEvent; + private static Action _onInterstitialAdReviewCreativeIdGeneratedEvent; + private static Action _onInterstitialAdHiddenEventV2; + + public class Interstitial + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdLoadedEvent"); + _onInterstitialAdLoadedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdLoadedEvent"); + _onInterstitialAdLoadedEventV2 -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdLoadFailedEvent"); + _onInterstitialAdLoadFailedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdLoadFailedEvent"); + _onInterstitialAdLoadFailedEventV2 -= value; + } + } + + /** + * Fired when an interstitial ad is displayed (may not be received by Unity until the interstitial ad closes). + */ + public static event Action OnAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdDisplayedEvent"); + _onInterstitialAdDisplayedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdDisplayedEvent"); + _onInterstitialAdDisplayedEventV2 -= value; + } + } + + public static event Action OnAdDisplayFailedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdDisplayFailedEvent"); + _onInterstitialAdFailedToDisplayEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdDisplayFailedEvent"); + _onInterstitialAdFailedToDisplayEventV2 -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdClickedEvent"); + _onInterstitialAdClickedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdClickedEvent"); + _onInterstitialAdClickedEventV2 -= value; + } + } + + /// + /// Fired when an interstitial ad impression was validated and revenue will be paid. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdRevenuePaidEvent"); + _onInterstitialAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdRevenuePaidEvent"); + _onInterstitialAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdReviewCreativeIdGeneratedEvent"); + _onInterstitialAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdReviewCreativeIdGeneratedEvent"); + _onInterstitialAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdHiddenEvent"); + _onInterstitialAdHiddenEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdHiddenEvent"); + _onInterstitialAdHiddenEventV2 -= value; + } + } + } + + private static Action _onAppOpenAdLoadedEvent; + private static Action _onAppOpenAdLoadFailedEvent; + private static Action _onAppOpenAdDisplayedEvent; + private static Action _onAppOpenAdFailedToDisplayEvent; + private static Action _onAppOpenAdClickedEvent; + private static Action _onAppOpenAdRevenuePaidEvent; + private static Action _onAppOpenAdHiddenEvent; + + public class AppOpen + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdLoadedEvent"); + _onAppOpenAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdLoadedEvent"); + _onAppOpenAdLoadedEvent -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdLoadFailedEvent"); + _onAppOpenAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdLoadFailedEvent"); + _onAppOpenAdLoadFailedEvent -= value; + } + } + + /** + * Fired when an app open ad is displayed (may not be received by Unity until the app open ad closes). + */ + public static event Action OnAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdDisplayedEvent"); + _onAppOpenAdDisplayedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdDisplayedEvent"); + _onAppOpenAdDisplayedEvent -= value; + } + } + + public static event Action OnAdDisplayFailedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdDisplayFailedEvent"); + _onAppOpenAdFailedToDisplayEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdDisplayFailedEvent"); + _onAppOpenAdFailedToDisplayEvent -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdClickedEvent"); + _onAppOpenAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdClickedEvent"); + _onAppOpenAdClickedEvent -= value; + } + } + + /// + /// Fired when an app open ad impression was validated and revenue will be paid. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdRevenuePaidEvent"); + _onAppOpenAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdRevenuePaidEvent"); + _onAppOpenAdRevenuePaidEvent -= value; + } + } + + public static event Action OnAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdHiddenEvent"); + _onAppOpenAdHiddenEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdHiddenEvent"); + _onAppOpenAdHiddenEvent -= value; + } + } + } + + private static Action _onRewardedAdLoadedEventV2; + private static Action _onRewardedAdLoadFailedEventV2; + private static Action _onRewardedAdDisplayedEventV2; + private static Action _onRewardedAdFailedToDisplayEventV2; + private static Action _onRewardedAdClickedEventV2; + private static Action _onRewardedAdRevenuePaidEvent; + private static Action _onRewardedAdReviewCreativeIdGeneratedEvent; + private static Action _onRewardedAdReceivedRewardEventV2; + private static Action _onRewardedAdHiddenEventV2; + + public class Rewarded + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdLoadedEvent"); + _onRewardedAdLoadedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdLoadedEvent"); + _onRewardedAdLoadedEventV2 -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdLoadFailedEvent"); + _onRewardedAdLoadFailedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdLoadFailedEvent"); + _onRewardedAdLoadFailedEventV2 -= value; + } + } + + /** + * Fired when a rewarded ad is displayed (may not be received by Unity until the rewarded ad closes). + */ + public static event Action OnAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdDisplayedEvent"); + _onRewardedAdDisplayedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdDisplayedEvent"); + _onRewardedAdDisplayedEventV2 -= value; + } + } + + public static event Action OnAdDisplayFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdDisplayFailedEvent"); + _onRewardedAdFailedToDisplayEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdDisplayFailedEvent"); + _onRewardedAdFailedToDisplayEventV2 -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdClickedEvent"); + _onRewardedAdClickedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdClickedEvent"); + _onRewardedAdClickedEventV2 -= value; + } + } + + /// + /// Fired when a rewarded ad impression was validated and revenue will be paid. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdRevenuePaidEvent"); + _onRewardedAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdRevenuePaidEvent"); + _onRewardedAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdReviewCreativeIdGeneratedEvent"); + _onRewardedAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdReviewCreativeIdGeneratedEvent"); + _onRewardedAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdReceivedRewardEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdReceivedRewardEvent"); + _onRewardedAdReceivedRewardEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdReceivedRewardEvent"); + _onRewardedAdReceivedRewardEventV2 -= value; + } + } + + public static event Action OnAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdHiddenEvent"); + _onRewardedAdHiddenEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdHiddenEvent"); + _onRewardedAdHiddenEventV2 -= value; + } + } + } + + private static Action _onRewardedInterstitialAdLoadedEvent; + private static Action _onRewardedInterstitialAdLoadFailedEvent; + private static Action _onRewardedInterstitialAdDisplayedEvent; + private static Action _onRewardedInterstitialAdFailedToDisplayEvent; + private static Action _onRewardedInterstitialAdClickedEvent; + private static Action _onRewardedInterstitialAdRevenuePaidEvent; + private static Action _onRewardedInterstitialAdReviewCreativeIdGeneratedEvent; + private static Action _onRewardedInterstitialAdReceivedRewardEvent; + private static Action _onRewardedInterstitialAdHiddenEvent; + + public class RewardedInterstitial + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdLoadedEvent"); + _onRewardedInterstitialAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdLoadedEvent"); + _onRewardedInterstitialAdLoadedEvent -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdLoadFailedEvent"); + _onRewardedInterstitialAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdLoadFailedEvent"); + _onRewardedInterstitialAdLoadFailedEvent -= value; + } + } + + /** + * Fired when a rewarded interstitial ad is displayed (may not be received by Unity until + * the rewarded interstitial ad closes). + */ + public static event Action OnAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdDisplayedEvent"); + _onRewardedInterstitialAdDisplayedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdDisplayedEvent"); + _onRewardedInterstitialAdDisplayedEvent -= value; + } + } + + public static event Action OnAdDisplayFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdDisplayFailedEvent"); + _onRewardedInterstitialAdFailedToDisplayEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdDisplayFailedEvent"); + _onRewardedInterstitialAdFailedToDisplayEvent -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdClickedEvent"); + _onRewardedInterstitialAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdClickedEvent"); + _onRewardedInterstitialAdClickedEvent -= value; + } + } + + /// + /// Fired when a rewarded interstitial ad impression was validated and revenue will be paid. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdRevenuePaidEvent"); + _onRewardedInterstitialAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdRevenuePaidEvent"); + _onRewardedInterstitialAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdReviewCreativeIdGeneratedEvent"); + _onRewardedInterstitialAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdReviewCreativeIdGeneratedEvent"); + _onRewardedInterstitialAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdReceivedRewardEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdReceivedRewardEvent"); + _onRewardedInterstitialAdReceivedRewardEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdReceivedRewardEvent"); + _onRewardedInterstitialAdReceivedRewardEvent -= value; + } + } + + public static event Action OnAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdHiddenEvent"); + _onRewardedInterstitialAdHiddenEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdHiddenEvent"); + _onRewardedInterstitialAdHiddenEvent -= value; + } + } + } + + private static Action _onBannerAdLoadedEventV2; + private static Action _onBannerAdLoadFailedEventV2; + private static Action _onBannerAdClickedEventV2; + private static Action _onBannerAdRevenuePaidEvent; + private static Action _onBannerAdReviewCreativeIdGeneratedEvent; + private static Action _onBannerAdExpandedEventV2; + private static Action _onBannerAdCollapsedEventV2; + + public class Banner + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdLoadedEvent"); + _onBannerAdLoadedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdLoadedEvent"); + _onBannerAdLoadedEventV2 -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdLoadFailedEvent"); + _onBannerAdLoadFailedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdLoadFailedEvent"); + _onBannerAdLoadFailedEventV2 -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdClickedEvent"); + _onBannerAdClickedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdClickedEvent"); + _onBannerAdClickedEventV2 -= value; + } + } + + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnBannerAdRevenuePaidEvent"); + _onBannerAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdRevenuePaidEvent"); + _onBannerAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdReviewCreativeIdGeneratedEvent"); + _onBannerAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdReviewCreativeIdGeneratedEvent"); + _onBannerAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdExpandedEvent"); + _onBannerAdExpandedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdExpandedEvent"); + _onBannerAdExpandedEventV2 -= value; + } + } + + public static event Action OnAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdCollapsedEvent"); + _onBannerAdCollapsedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdCollapsedEvent"); + _onBannerAdCollapsedEventV2 -= value; + } + } + } + + private static Action _onMRecAdLoadedEventV2; + private static Action _onMRecAdLoadFailedEventV2; + private static Action _onMRecAdClickedEventV2; + private static Action _onMRecAdRevenuePaidEvent; + private static Action _onMRecAdReviewCreativeIdGeneratedEvent; + private static Action _onMRecAdExpandedEventV2; + private static Action _onMRecAdCollapsedEventV2; + + public class MRec + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdLoadedEvent"); + _onMRecAdLoadedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdLoadedEvent"); + _onMRecAdLoadedEventV2 -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdLoadFailedEvent"); + _onMRecAdLoadFailedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdLoadFailedEvent"); + _onMRecAdLoadFailedEventV2 -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdClickedEvent"); + _onMRecAdClickedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdClickedEvent"); + _onMRecAdClickedEventV2 -= value; + } + } + + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnMRecAdRevenuePaidEvent"); + _onMRecAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdRevenuePaidEvent"); + _onMRecAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdReviewCreativeIdGeneratedEvent"); + _onMRecAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdReviewCreativeIdGeneratedEvent"); + _onMRecAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdExpandedEvent"); + _onMRecAdExpandedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdExpandedEvent"); + _onMRecAdExpandedEventV2 -= value; + } + } + + public static event Action OnAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdCollapsedEvent"); + _onMRecAdCollapsedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdCollapsedEvent"); + _onMRecAdCollapsedEventV2 -= value; + } + } + } + + private static Action _onCrossPromoAdLoadedEvent; + private static Action _onCrossPromoAdLoadFailedEvent; + private static Action _onCrossPromoAdClickedEvent; + private static Action _onCrossPromoAdRevenuePaidEvent; + private static Action _onCrossPromoAdExpandedEvent; + private static Action _onCrossPromoAdCollapsedEvent; + + public class CrossPromo + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnCrossPromoAdLoadedEvent"); + _onCrossPromoAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnCrossPromoAdLoadedEvent"); + _onCrossPromoAdLoadedEvent -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnCrossPromoAdLoadFailedEvent"); + _onCrossPromoAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnCrossPromoAdLoadFailedEvent"); + _onCrossPromoAdLoadFailedEvent -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnCrossPromoAdClickedEvent"); + _onCrossPromoAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnCrossPromoAdClickedEvent"); + _onCrossPromoAdClickedEvent -= value; + } + } + + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnCrossPromoAdRevenuePaidEvent"); + _onCrossPromoAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnCrossPromoAdRevenuePaidEvent"); + _onCrossPromoAdRevenuePaidEvent -= value; + } + } + + public static event Action OnAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnCrossPromoAdExpandedEvent"); + _onCrossPromoAdExpandedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnCrossPromoAdExpandedEvent"); + _onCrossPromoAdExpandedEvent -= value; + } + } + + public static event Action OnAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnCrossPromoAdCollapsedEvent"); + _onCrossPromoAdCollapsedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnCrossPromoAdCollapsedEvent"); + _onCrossPromoAdCollapsedEvent -= value; + } + } + } + + private static Action _onBannerAdLoadedEvent; + private static Action _onBannerAdLoadFailedEvent; + private static Action _onBannerAdClickedEvent; + private static Action _onBannerAdExpandedEvent; + private static Action _onBannerAdCollapsedEvent; + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdLoadedEvent` instead.")] + public static event Action OnBannerAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdLoadedEvent"); + _onBannerAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdLoadedEvent"); + _onBannerAdLoadedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdLoadFailedEvent` instead.")] + public static event Action OnBannerAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdLoadFailedEvent"); + _onBannerAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdLoadFailedEvent"); + _onBannerAdLoadFailedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdClickedEvent` instead.")] + public static event Action OnBannerAdClickedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdClickedEvent"); + _onBannerAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdClickedEvent"); + _onBannerAdClickedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdExpandedEvent` instead.")] + public static event Action OnBannerAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdExpandedEvent"); + _onBannerAdExpandedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdExpandedEvent"); + _onBannerAdExpandedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdCollapsedEvent` instead.")] + public static event Action OnBannerAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdCollapsedEvent"); + _onBannerAdCollapsedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdCollapsedEvent"); + _onBannerAdCollapsedEvent -= value; + } + } + + private static Action _onMRecAdLoadedEvent; + private static Action _onMRecAdLoadFailedEvent; + private static Action _onMRecAdClickedEvent; + private static Action _onMRecAdExpandedEvent; + private static Action _onMRecAdCollapsedEvent; + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdLoadedEvent` instead.")] + public static event Action OnMRecAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdLoadedEvent"); + _onMRecAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdLoadedEvent"); + _onMRecAdLoadedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdLoadFailedEvent` instead.")] + public static event Action OnMRecAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdLoadFailedEvent"); + _onMRecAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdLoadFailedEvent"); + _onMRecAdLoadFailedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdClickedEvent` instead.")] + public static event Action OnMRecAdClickedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdClickedEvent"); + _onMRecAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdClickedEvent"); + _onMRecAdClickedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdExpandedEvent` instead.")] + public static event Action OnMRecAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdExpandedEvent"); + _onMRecAdExpandedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdExpandedEvent"); + _onMRecAdExpandedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdCollapsedEvent` instead.")] + public static event Action OnMRecAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdCollapsedEvent"); + _onMRecAdCollapsedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdCollapsedEvent"); + _onMRecAdCollapsedEvent -= value; + } + } + + private static Action _onInterstitialAdLoadedEvent; + private static Action _onInterstitialLoadFailedEvent; + private static Action _onInterstitialAdDisplayedEvent; + private static Action _onInterstitialAdFailedToDisplayEvent; + private static Action _onInterstitialAdClickedEvent; + private static Action _onInterstitialAdHiddenEvent; + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdLoadedEvent` instead.")] + public static event Action OnInterstitialLoadedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialLoadedEvent"); + _onInterstitialAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialLoadedEvent"); + _onInterstitialAdLoadedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent` instead.")] + public static event Action OnInterstitialLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialLoadFailedEvent"); + _onInterstitialLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialLoadFailedEvent"); + _onInterstitialLoadFailedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdHiddenEvent` instead.")] + public static event Action OnInterstitialHiddenEvent + { + add + { + LogSubscribedToEvent("OnInterstitialHiddenEvent"); + _onInterstitialAdHiddenEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialHiddenEvent"); + _onInterstitialAdHiddenEvent -= value; + } + } + + // Fired when an interstitial ad is displayed (may not be received by Unity until the interstitial closes) + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent` instead.")] + public static event Action OnInterstitialDisplayedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialDisplayedEvent"); + _onInterstitialAdDisplayedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialDisplayedEvent"); + _onInterstitialAdDisplayedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdDisplayFailedEvent` instead.")] + public static event Action OnInterstitialAdFailedToDisplayEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdFailedToDisplayEvent"); + _onInterstitialAdFailedToDisplayEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdFailedToDisplayEvent"); + _onInterstitialAdFailedToDisplayEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdClickedEvent` instead.")] + public static event Action OnInterstitialClickedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialClickedEvent"); + _onInterstitialAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialClickedEvent"); + _onInterstitialAdClickedEvent -= value; + } + } + + private static Action _onRewardedAdLoadedEvent; + private static Action _onRewardedAdLoadFailedEvent; + private static Action _onRewardedAdDisplayedEvent; + private static Action _onRewardedAdFailedToDisplayEvent; + private static Action _onRewardedAdClickedEvent; + private static Action _onRewardedAdReceivedRewardEvent; + private static Action _onRewardedAdHiddenEvent; + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdLoadedEvent` instead.")] + public static event Action OnRewardedAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdLoadedEvent"); + _onRewardedAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdLoadedEvent"); + _onRewardedAdLoadedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent` instead.")] + public static event Action OnRewardedAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdLoadFailedEvent"); + _onRewardedAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdLoadFailedEvent"); + _onRewardedAdLoadFailedEvent -= value; + } + } + + // Fired when an rewarded ad is displayed (may not be received by Unity until the rewarded ad closes) + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdDisplayedEvent` instead.")] + public static event Action OnRewardedAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdDisplayedEvent"); + _onRewardedAdDisplayedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdDisplayedEvent"); + _onRewardedAdDisplayedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdHiddenEvent` instead.")] + public static event Action OnRewardedAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdHiddenEvent"); + _onRewardedAdHiddenEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdHiddenEvent"); + _onRewardedAdHiddenEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdClickedEvent` instead.")] + public static event Action OnRewardedAdClickedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdClickedEvent"); + _onRewardedAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdClickedEvent"); + _onRewardedAdClickedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdDisplayFailedEvent` instead.")] + public static event Action OnRewardedAdFailedToDisplayEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdFailedToDisplayEvent"); + _onRewardedAdFailedToDisplayEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdFailedToDisplayEvent"); + _onRewardedAdFailedToDisplayEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent` instead.")] + public static event Action OnRewardedAdReceivedRewardEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdReceivedRewardEvent"); + _onRewardedAdReceivedRewardEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdReceivedRewardEvent"); + _onRewardedAdReceivedRewardEvent -= value; + } + } + +#if !UNITY_EDITOR + void Awake() + { + if (Instance == null) + { + Instance = this; + DontDestroyOnLoad(gameObject); + } + } +#endif + + public void ForwardEvent(string eventPropsStr) + { + var eventProps = Json.Deserialize(eventPropsStr) as Dictionary; + if (eventProps == null) + { + MaxSdkLogger.E("Failed to forward event due to invalid event data"); + return; + } + + var eventName = MaxSdkUtils.GetStringFromDictionary(eventProps, "name", ""); + if (eventName == "OnInitialCallbackEvent") + { + MaxSdkLogger.D("Initial background callback."); + } + else if (eventName == "OnSdkInitializedEvent") + { + 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") + { + CFService.NotifyConsentFlowCompletedIfNeeded(eventProps); + } + // Ad Events + else + { + var adInfo = new MaxSdkBase.AdInfo(eventProps); + var adUnitIdentifier = MaxSdkUtils.GetStringFromDictionary(eventProps, "adUnitId", ""); + if (eventName == "OnBannerAdLoadedEvent") + { + InvokeEvent(_onBannerAdLoadedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onBannerAdLoadedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnBannerAdLoadFailedEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onBannerAdLoadFailedEvent, adUnitIdentifier, errorCode, eventName); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onBannerAdLoadFailedEventV2, adUnitIdentifier, errorInfo, eventName); + } + else if (eventName == "OnBannerAdClickedEvent") + { + InvokeEvent(_onBannerAdClickedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onBannerAdClickedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnBannerAdRevenuePaidEvent") + { + InvokeEvent(_onBannerAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnBannerAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onBannerAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName); + } + else if (eventName == "OnBannerAdExpandedEvent") + { + InvokeEvent(_onBannerAdExpandedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onBannerAdExpandedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnBannerAdCollapsedEvent") + { + InvokeEvent(_onBannerAdCollapsedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onBannerAdCollapsedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnMRecAdLoadedEvent") + { + InvokeEvent(_onMRecAdLoadedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onMRecAdLoadedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnMRecAdLoadFailedEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onMRecAdLoadFailedEvent, adUnitIdentifier, errorCode, eventName); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onMRecAdLoadFailedEventV2, adUnitIdentifier, errorInfo, eventName); + } + else if (eventName == "OnMRecAdClickedEvent") + { + InvokeEvent(_onMRecAdClickedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onMRecAdClickedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnMRecAdRevenuePaidEvent") + { + InvokeEvent(_onMRecAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnMRecAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onMRecAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName); + } + else if (eventName == "OnMRecAdExpandedEvent") + { + InvokeEvent(_onMRecAdExpandedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onMRecAdExpandedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnMRecAdCollapsedEvent") + { + InvokeEvent(_onMRecAdCollapsedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onMRecAdCollapsedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnCrossPromoAdLoadedEvent") + { + InvokeEvent(_onCrossPromoAdLoadedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnCrossPromoAdLoadFailedEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + + InvokeEvent(_onCrossPromoAdLoadFailedEvent, adUnitIdentifier, errorInfo, eventName); + } + else if (eventName == "OnCrossPromoAdClickedEvent") + { + InvokeEvent(_onCrossPromoAdClickedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnCrossPromoAdRevenuePaidEvent") + { + InvokeEvent(_onCrossPromoAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnCrossPromoAdExpandedEvent") + { + InvokeEvent(_onCrossPromoAdExpandedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnCrossPromoAdCollapsedEvent") + { + InvokeEvent(_onCrossPromoAdCollapsedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnInterstitialLoadedEvent") + { + InvokeEvent(_onInterstitialAdLoadedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onInterstitialAdLoadedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnInterstitialLoadFailedEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onInterstitialLoadFailedEvent, adUnitIdentifier, errorCode, eventName); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onInterstitialAdLoadFailedEventV2, adUnitIdentifier, errorInfo, eventName); + } + else if (eventName == "OnInterstitialHiddenEvent") + { + InvokeEvent(_onInterstitialAdHiddenEvent, adUnitIdentifier, eventName); + InvokeEvent(_onInterstitialAdHiddenEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnInterstitialDisplayedEvent") + { + InvokeEvent(_onInterstitialAdDisplayedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onInterstitialAdDisplayedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnInterstitialAdFailedToDisplayEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onInterstitialAdFailedToDisplayEvent, adUnitIdentifier, errorCode, eventName); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onInterstitialAdFailedToDisplayEventV2, adUnitIdentifier, errorInfo, adInfo, eventName); + } + else if (eventName == "OnInterstitialClickedEvent") + { + InvokeEvent(_onInterstitialAdClickedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onInterstitialAdClickedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnInterstitialAdRevenuePaidEvent") + { + InvokeEvent(_onInterstitialAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnInterstitialAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onInterstitialAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName); + } + else if (eventName == "OnAppOpenAdLoadedEvent") + { + InvokeEvent(_onAppOpenAdLoadedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnAppOpenAdLoadFailedEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onAppOpenAdLoadFailedEvent, adUnitIdentifier, errorInfo, eventName); + } + else if (eventName == "OnAppOpenAdHiddenEvent") + { + InvokeEvent(_onAppOpenAdHiddenEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnAppOpenAdDisplayedEvent") + { + InvokeEvent(_onAppOpenAdDisplayedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnAppOpenAdFailedToDisplayEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onAppOpenAdFailedToDisplayEvent, adUnitIdentifier, errorInfo, adInfo, eventName); + } + else if (eventName == "OnAppOpenAdClickedEvent") + { + InvokeEvent(_onAppOpenAdClickedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnAppOpenAdRevenuePaidEvent") + { + InvokeEvent(_onAppOpenAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedAdLoadedEvent") + { + InvokeEvent(_onRewardedAdLoadedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onRewardedAdLoadedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedAdLoadFailedEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onRewardedAdLoadFailedEvent, adUnitIdentifier, errorCode, eventName); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onRewardedAdLoadFailedEventV2, adUnitIdentifier, errorInfo, eventName); + } + else if (eventName == "OnRewardedAdDisplayedEvent") + { + InvokeEvent(_onRewardedAdDisplayedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onRewardedAdDisplayedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedAdHiddenEvent") + { + InvokeEvent(_onRewardedAdHiddenEvent, adUnitIdentifier, eventName); + InvokeEvent(_onRewardedAdHiddenEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedAdClickedEvent") + { + InvokeEvent(_onRewardedAdClickedEvent, adUnitIdentifier, eventName); + InvokeEvent(_onRewardedAdClickedEventV2, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedAdRevenuePaidEvent") + { + InvokeEvent(_onRewardedAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onRewardedAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName); + } + else if (eventName == "OnRewardedAdFailedToDisplayEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onRewardedAdFailedToDisplayEvent, adUnitIdentifier, errorCode, eventName); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onRewardedAdFailedToDisplayEventV2, adUnitIdentifier, errorInfo, adInfo, eventName); + } + else if (eventName == "OnRewardedAdReceivedRewardEvent") + { + var reward = new MaxSdkBase.Reward + { + Label = MaxSdkUtils.GetStringFromDictionary(eventProps, "rewardLabel", ""), + Amount = MaxSdkUtils.GetIntFromDictionary(eventProps, "rewardAmount", 0) + }; + + InvokeEvent(_onRewardedAdReceivedRewardEvent, adUnitIdentifier, reward, eventName); + InvokeEvent(_onRewardedAdReceivedRewardEventV2, adUnitIdentifier, reward, adInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdLoadedEvent") + { + InvokeEvent(_onRewardedInterstitialAdLoadedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdLoadFailedEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + + InvokeEvent(_onRewardedInterstitialAdLoadFailedEvent, adUnitIdentifier, errorInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdDisplayedEvent") + { + InvokeEvent(_onRewardedInterstitialAdDisplayedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdHiddenEvent") + { + InvokeEvent(_onRewardedInterstitialAdHiddenEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdClickedEvent") + { + InvokeEvent(_onRewardedInterstitialAdClickedEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdRevenuePaidEvent") + { + InvokeEvent(_onRewardedInterstitialAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onRewardedInterstitialAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdFailedToDisplayEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + + InvokeEvent(_onRewardedInterstitialAdFailedToDisplayEvent, adUnitIdentifier, errorInfo, adInfo, eventName); + } + else if (eventName == "OnRewardedInterstitialAdReceivedRewardEvent") + { + var reward = new MaxSdkBase.Reward + { + Label = MaxSdkUtils.GetStringFromDictionary(eventProps, "rewardLabel", ""), + Amount = MaxSdkUtils.GetIntFromDictionary(eventProps, "rewardAmount", 0) + }; + + InvokeEvent(_onRewardedInterstitialAdReceivedRewardEvent, adUnitIdentifier, reward, adInfo, eventName); + } + else + { + MaxSdkLogger.UserWarning("Unknown MAX Ads event fired: " + eventName); + } + } + } + +#if UNITY_EDITOR + public static void EmitSdkInitializedEvent() + { + if (_onSdkInitializedEvent == null) return; + + _onSdkInitializedEvent(MaxSdkBase.SdkConfiguration.CreateEmpty()); + } +#endif + + private static void InvokeEvent(Action evt, string eventName) + { + if (!CanInvokeEvent(evt)) return; + + MaxSdkLogger.UserDebug("Invoking event: " + eventName); + evt(); + } + + private static void InvokeEvent(Action evt, T param, string eventName) + { + if (!CanInvokeEvent(evt)) return; + + MaxSdkLogger.UserDebug("Invoking event: " + eventName + ". Param: " + param); + evt(param); + } + + private static void InvokeEvent(Action evt, T1 param1, T2 param2, string eventName) + { + if (!CanInvokeEvent(evt)) return; + + MaxSdkLogger.UserDebug("Invoking event: " + eventName + ". Params: " + param1 + ", " + param2); + evt(param1, param2); + } + + private static void InvokeEvent(Action evt, T1 param1, T2 param2, T3 param3, string eventName) + { + if (!CanInvokeEvent(evt)) return; + + MaxSdkLogger.UserDebug("Invoking event: " + eventName + ". Params: " + param1 + ", " + param2 + ", " + param3); + evt(param1, param2, param3); + } + + private static bool CanInvokeEvent(Delegate evt) + { + if (evt == null) return false; + + // Check that publisher is not over-subscribing + if (evt.GetInvocationList().Length > 5) + { + MaxSdkLogger.UserWarning("Ads Event (" + evt + ") has over 5 subscribers. Please make sure you are properly un-subscribing to actions!!!"); + } + + return true; + } + + private static void LogSubscribedToEvent(string eventName) + { + MaxSdkLogger.D("Listener has been added to callback: " + eventName); + } + + private static void LogUnsubscribedToEvent(string eventName) + { + MaxSdkLogger.D("Listener has been removed from callback: " + eventName); + } + +#if UNITY_EDITOR && UNITY_2019_2_OR_NEWER + /// + /// Resets static event handlers so they still get reset even if Domain Reloading is disabled + /// + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] + private static void ResetOnDomainReload() + { + _onSdkInitializedEvent = null; + _onVariablesUpdatedEvent = null; + _onSdkConsentDialogDismissedEvent = null; + + _onInterstitialAdLoadedEventV2 = null; + _onInterstitialAdLoadFailedEventV2 = null; + _onInterstitialAdDisplayedEventV2 = null; + _onInterstitialAdFailedToDisplayEventV2 = null; + _onInterstitialAdClickedEventV2 = null; + _onInterstitialAdRevenuePaidEvent = null; + _onInterstitialAdReviewCreativeIdGeneratedEvent = null; + _onInterstitialAdHiddenEventV2 = null; + + _onAppOpenAdLoadedEvent = null; + _onAppOpenAdLoadFailedEvent = null; + _onAppOpenAdDisplayedEvent = null; + _onAppOpenAdFailedToDisplayEvent = null; + _onAppOpenAdClickedEvent = null; + _onAppOpenAdRevenuePaidEvent = null; + _onAppOpenAdHiddenEvent = null; + + _onRewardedAdLoadedEventV2 = null; + _onRewardedAdLoadFailedEventV2 = null; + _onRewardedAdDisplayedEventV2 = null; + _onRewardedAdFailedToDisplayEventV2 = null; + _onRewardedAdClickedEventV2 = null; + _onRewardedAdRevenuePaidEvent = null; + _onRewardedAdReviewCreativeIdGeneratedEvent = null; + _onRewardedAdReceivedRewardEventV2 = null; + _onRewardedAdHiddenEventV2 = null; + + _onRewardedInterstitialAdLoadedEvent = null; + _onRewardedInterstitialAdLoadFailedEvent = null; + _onRewardedInterstitialAdDisplayedEvent = null; + _onRewardedInterstitialAdFailedToDisplayEvent = null; + _onRewardedInterstitialAdClickedEvent = null; + _onRewardedInterstitialAdRevenuePaidEvent = null; + _onRewardedInterstitialAdReviewCreativeIdGeneratedEvent = null; + _onRewardedInterstitialAdReceivedRewardEvent = null; + _onRewardedInterstitialAdHiddenEvent = null; + + _onBannerAdLoadedEventV2 = null; + _onBannerAdLoadFailedEventV2 = null; + _onBannerAdClickedEventV2 = null; + _onBannerAdRevenuePaidEvent = null; + _onBannerAdReviewCreativeIdGeneratedEvent = null; + _onBannerAdExpandedEventV2 = null; + _onBannerAdCollapsedEventV2 = null; + + _onMRecAdLoadedEventV2 = null; + _onMRecAdLoadFailedEventV2 = null; + _onMRecAdClickedEventV2 = null; + _onMRecAdRevenuePaidEvent = null; + _onMRecAdReviewCreativeIdGeneratedEvent = null; + _onMRecAdExpandedEventV2 = null; + _onMRecAdCollapsedEventV2 = null; + + _onCrossPromoAdLoadedEvent = null; + _onCrossPromoAdLoadFailedEvent = null; + _onCrossPromoAdClickedEvent = null; + _onCrossPromoAdRevenuePaidEvent = null; + _onCrossPromoAdExpandedEvent = null; + _onCrossPromoAdCollapsedEvent = null; + + _onBannerAdLoadedEvent = null; + _onBannerAdLoadFailedEvent = null; + _onBannerAdClickedEvent = null; + _onBannerAdExpandedEvent = null; + _onBannerAdCollapsedEvent = null; + + _onMRecAdLoadedEvent = null; + _onMRecAdLoadFailedEvent = null; + _onMRecAdClickedEvent = null; + _onMRecAdExpandedEvent = null; + _onMRecAdCollapsedEvent = null; + + _onInterstitialAdLoadedEvent = null; + _onInterstitialLoadFailedEvent = null; + _onInterstitialAdDisplayedEvent = null; + _onInterstitialAdFailedToDisplayEvent = null; + _onInterstitialAdClickedEvent = null; + _onInterstitialAdHiddenEvent = null; + + _onRewardedAdLoadedEvent = null; + _onRewardedAdLoadFailedEvent = null; + _onRewardedAdDisplayedEvent = null; + _onRewardedAdFailedToDisplayEvent = null; + _onRewardedAdClickedEvent = null; + _onRewardedAdReceivedRewardEvent = null; + _onRewardedAdHiddenEvent = null; + } +#endif +} diff --git a/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta b/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta new file mode 100644 index 0000000..c383446 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 1bc9fb13147694ac795ea28866c87af9 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdkCallbacks.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxSdkLogger.cs b/MaxSdk/Scripts/MaxSdkLogger.cs new file mode 100644 index 0000000..ecdc881 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkLogger.cs @@ -0,0 +1,70 @@ +using UnityEngine; + +public class MaxSdkLogger +{ + private const string SdkTag = "AppLovin MAX"; + public const string KeyVerboseLoggingEnabled = "com.applovin.verbose_logging_enabled"; + + /// + /// Log debug messages. + /// + public static void UserDebug(string message) + { + Debug.Log("Debug [" + SdkTag + "] " + message); + } + + /// + /// Log debug messages when verbose logging is enabled. + /// + /// Verbose logging can be enabled by calling or via the Integration Manager for build time logs. + /// + public static void D(string message) + { + if (MaxSdk.IsVerboseLoggingEnabled()) + { + Debug.Log("Debug [" + SdkTag + "] " + message); + } + } + + /// + /// Log warning messages. + /// + public static void UserWarning(string message) + { + Debug.LogWarning("Warning [" + SdkTag + "] " + message); + } + + /// + /// Log warning messages when verbose logging is enabled. + /// + /// Verbose logging can be enabled by calling or via the Integration Manager for build time logs. + /// + public static void W(string message) + { + if (MaxSdk.IsVerboseLoggingEnabled()) + { + Debug.LogWarning("Warning [" + SdkTag + "] " + message); + } + } + + /// + /// Log error messages. + /// + public static void UserError(string message) + { + Debug.LogError("Error [" + SdkTag + "] " + message); + } + + /// + /// Log error messages when verbose logging is enabled. + /// + /// Verbose logging can be enabled by calling or via the Integration Manager for build time logs. + /// + public static void E(string message) + { + if (MaxSdk.IsVerboseLoggingEnabled()) + { + Debug.LogError("Error [" + SdkTag + "] " + message); + } + } +} diff --git a/MaxSdk/Scripts/MaxSdkLogger.cs.meta b/MaxSdk/Scripts/MaxSdkLogger.cs.meta new file mode 100644 index 0000000..1f09051 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkLogger.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 54635e7165bf2486a9cc1da416db8ae6 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdkLogger.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MaxSdk/Scripts/MaxSdkUnityEditor.cs b/MaxSdk/Scripts/MaxSdkUnityEditor.cs new file mode 100644 index 0000000..8aa8a53 --- /dev/null +++ b/MaxSdk/Scripts/MaxSdkUnityEditor.cs @@ -0,0 +1,1536 @@ +// This script is used for Unity Editor and non Android or iOS platforms. + +#if UNITY_EDITOR || !(UNITY_ANDROID || UNITY_IPHONE || UNITY_IOS) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using AppLovinMax.ThirdParty.MiniJson; +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; +using UnityEngine.UI; +using Object = UnityEngine.Object; + +/// +/// Unity Editor AppLovin MAX Unity Plugin implementation +/// +public class MaxSdkUnityEditor : MaxSdkBase +{ + private static bool _isInitialized; + private static bool _hasSdkKey; + private static bool _hasUserConsent = false; + private static bool _isUserConsentSet = false; + private static bool _isAgeRestrictedUser = false; + private static bool _isAgeRestrictedUserSet = false; + private static bool _doNotSell = false; + private static bool _isDoNotSellSet = false; + private static bool _showStubAds = true; + private static readonly HashSet RequestedAdUnits = new HashSet(); + 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; } + } + + [RuntimeInitializeOnLoadMethod] + public static void InitializeMaxSdkUnityEditorOnLoad() + { + // Unity destroys the stub banners each time the editor exits play mode, but the StubBanners stays in memory if Enter Play Mode settings is enabled. + StubBanners.Clear(); + } + + /// + /// Set AppLovin SDK Key. + /// + /// This method must be called before any other SDK operation + /// + public static void SetSdkKey(string sdkKey) + { + _hasSdkKey = true; + } + + #region Initialization + + /// + /// Initialize the default instance of AppLovin SDK. + /// + /// Please make sure that application's Android manifest or Info.plist includes the AppLovin SDK key. + /// + /// + /// OPTIONAL: Set the MAX ad unit ids to be used for this instance of the SDK. 3rd-party SDKs will be initialized with the credentials configured for these ad unit ids. + /// This should only be used if you have different sets of ad unit ids / credentials for the same package name. + /// + public static void InitializeSdk(string[] adUnitIds = null) + { + _ensureHaveSdkKey(); + + _isInitialized = true; + _hasSdkKey = true; + + // Slight delay to emulate the SDK initializing + ExecuteWithDelay(0.1f, () => + { + _isInitialized = true; + +#if UNITY_EDITOR + MaxSdkCallbacks.EmitSdkInitializedEvent(); +#endif + }); + } + + /// + /// Check if the SDK has been initialized. + /// + /// True if SDK has been initialized + public static bool IsInitialized() + { + return _isInitialized; + } + + /// + /// Prevent stub ads from showing in the Unity Editor + /// + public static void DisableStubAds() + { + _showStubAds = false; + } + + #endregion + + #region User Info + + /// + /// Set an identifier for the current user. This identifier will be tied to SDK events and our optional S2S postbacks. + /// + /// If you're using reward validation, you can optionally set an identifier to be included with currency validation postbacks. + /// For example, a username or email. We'll include this in the postback when we ping your currency endpoint from our server. + /// + /// + /// The user identifier to be set. + public static void SetUserId(string userId) { } + + /// + /// User segments allow us to serve ads using custom-defined rules based on which segment the user is in. For now, we only support a custom string 32 alphanumeric characters or less as the user segment. + /// + public static MaxUserSegment UserSegment + { + get { return SharedUserSegment; } + } + + /// + /// This class allows you to provide user or app data that will improve how we target ads. + /// + public static MaxTargetingData TargetingData + { + get { return SharedTargetingData; } + } + + #endregion + + #region MAX + + /// + /// Returns the list of available mediation networks. + /// + /// Please call this method after the SDK has initialized. + /// + public static List GetAvailableMediatedNetworks() + { + return new List(); + } + + /// + /// Present the mediation debugger UI. + /// This debugger tool provides the status of your integration for each third-party ad network. + /// + /// Please call this method after the SDK has initialized. + /// + public static void ShowMediationDebugger() + { + if (!_isInitialized) + { + MaxSdkLogger.UserWarning("The mediation debugger cannot be shown before the MAX SDK has been initialized." + + "\nCall 'MaxSdk.InitializeSdk();' and listen for 'MaxSdkCallbacks.OnSdkInitializedEvent' before showing the mediation debugger."); + } + else + { + MaxSdkLogger.UserWarning("The mediation debugger cannot be shown in the Unity Editor. Please export the project to Android or iOS first."); + } + } + + /// + /// Present the mediation debugger UI. + /// + /// Please call this method after the SDK has initialized. + /// + public static void ShowCreativeDebugger() + { + if (!_isInitialized) + { + MaxSdkLogger.UserWarning("The creative debugger cannot be shown before the MAX SDK has been initialized." + + "\nCall 'MaxSdk.InitializeSdk();' and listen for 'MaxSdkCallbacks.OnSdkInitializedEvent' before showing the mediation debugger."); + } + else + { + MaxSdkLogger.UserWarning("The creative debugger cannot be shown in the Unity Editor. Please export the project to Android or iOS first."); + } + } + + /// + /// Returns the arbitrary ad value for a given ad unit identifier with key. Returns null if no ad is loaded. + /// + /// + /// Ad value key + /// Arbitrary ad value for a given key, or null if no ad is loaded. + public static string GetAdValue(string adUnitIdentifier, string key) + { + return ""; + } + + #endregion + + #region Privacy + + /// + /// Get the SDK configuration for this user. + /// + /// Note: This method should be called only after SDK has been initialized. + /// + public static SdkConfiguration GetSdkConfiguration() + { + return SdkConfiguration.CreateEmpty(); + } + + /// + /// Set whether or not user has provided consent for information sharing with AppLovin and other providers. + /// + /// true if the user has provided consent for information sharing with AppLovin. false by default. + public static void SetHasUserConsent(bool hasUserConsent) + { + _hasUserConsent = hasUserConsent; + _isUserConsentSet = true; + } + + /// + /// Check if user has provided consent for information sharing with AppLovin and other providers. + /// + /// true if user has provided consent for information sharing. false if the user declined to share information or the consent value has not been set . + public static bool HasUserConsent() + { + return _hasUserConsent; + } + + /// + /// Check if user has set consent for information sharing. + /// + /// true if user has set a value of consent for information sharing. + public static bool IsUserConsentSet() + { + return _isUserConsentSet; + } + + /// + /// Mark user as age restricted (i.e. under 16). + /// + /// true if the user is age restricted (i.e. under 16). + public static void SetIsAgeRestrictedUser(bool isAgeRestrictedUser) + { + _isAgeRestrictedUser = isAgeRestrictedUser; + _isAgeRestrictedUserSet = true; + } + + /// + /// Check if user is age restricted. + /// + /// true if the user is age-restricted. false if the user is not age-restricted or the age-restriction has not been set. + public static bool IsAgeRestrictedUser() + { + return _isAgeRestrictedUser; + } + + /// + /// Check if user set its age restricted settings. + /// + /// true if user has set its age restricted settings. + public static bool IsAgeRestrictedUserSet() + { + return _isAgeRestrictedUserSet; + } + + /// + /// Set whether or not user has opted out of the sale of their personal information. + /// + /// true if the user has opted out of the sale of their personal information. + public static void SetDoNotSell(bool doNotSell) + { + _doNotSell = doNotSell; + _isDoNotSellSet = true; + } + + /// + /// Check if the user has opted out of the sale of their personal information. + /// + /// true if the user has opted out of the sale of their personal information. false if the user opted in to the sell of their personal information or the value has not been set . + public static bool IsDoNotSell() + { + return _doNotSell; + } + + /// + /// Check if the user has set the option to sell their personal information. + /// + /// true if user has chosen an option to sell their personal information. + public static bool IsDoNotSellSet() + { + return _isDoNotSellSet; + } + + #endregion + + #region Banners + + /// + /// Create a new banner. + /// + /// Ad unit identifier of the banner to create + /// Banner position + public static void CreateBanner(string adUnitIdentifier, BannerPosition bannerPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create banner"); + RequestAdUnit(adUnitIdentifier); + + if (_showStubAds && !StubBanners.ContainsKey(adUnitIdentifier)) + { + CreateStubBanner(adUnitIdentifier, bannerPosition); + } + + ExecuteWithDelay(1f, () => + { + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnBannerAdLoadedEvent", adUnitIdentifier)); + MaxSdkCallbacks.Instance.ForwardEvent(eventProps); + }); + } + + /// + /// Create a new banner with a custom position. + /// + /// Ad unit identifier of the banner to create + /// The X coordinate (horizontal position) of the banner relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the banner relative to the top left corner of the screen. + /// + /// The banner is placed within the safe area of the screen. You can use this to get the absolute position of the banner on screen. + /// + public static void CreateBanner(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create banner"); + RequestAdUnit(adUnitIdentifier); + + // TODO: Add stub ads support + } + + private static void CreateStubBanner(string adUnitIdentifier, BannerPosition bannerPosition) + { +#if UNITY_EDITOR + // Only support BottomCenter and TopCenter for now + var bannerPrefabName = bannerPosition == BannerPosition.BottomCenter ? "BannerBottom" : "BannerTop"; + var prefabPath = MaxSdkUtils.GetAssetPathForExportPath("MaxSdk/Prefabs/" + bannerPrefabName + ".prefab"); + var bannerPrefab = AssetDatabase.LoadAssetAtPath(prefabPath); + var stubBanner = Object.Instantiate(bannerPrefab, Vector3.zero, Quaternion.identity); + stubBanner.SetActive(false); // Hidden by default + Object.DontDestroyOnLoad(stubBanner); + + var bannerText = stubBanner.GetComponentInChildren(); + bannerText.text += ":\n" + adUnitIdentifier; + + StubBanners.Add(adUnitIdentifier, stubBanner); +#endif + } + + /// + /// Load a new banner ad. + /// NOTE: The method loads the first banner ad and initiates an automated banner refresh process. + /// You only need to call this method if you pause banner refresh. + /// + /// Ad unit identifier of the banner to load + public static void LoadBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load banner"); + + ExecuteWithDelay(1f, () => + { + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnBannerAdLoadedEvent", adUnitIdentifier)); + MaxSdkCallbacks.Instance.ForwardEvent(eventProps); + }); + } + + /// + /// Set the banner placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the banner to set the placement for + /// Placement to set + public static void SetBannerPlacement(string adUnitIdentifier, string placement) + { + MaxSdkLogger.UserDebug("Setting banner placement to '" + placement + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Starts or resumes auto-refreshing of the banner for the given ad unit identifier. + /// + /// Ad unit identifier of the banner for which to start auto-refresh + public static void StartBannerAutoRefresh(string adUnitIdentifier) + { + MaxSdkLogger.UserDebug("Starting banner auto refresh."); + } + + /// + /// Pauses auto-refreshing of the banner for the given ad unit identifier. + /// + /// Ad unit identifier of the banner for which to stop auto-refresh + public static void StopBannerAutoRefresh(string adUnitIdentifier) + { + MaxSdkLogger.UserDebug("Stopping banner auto refresh."); + } + + /// + /// Updates the position of the banner to the new position provided. + /// + /// The ad unit identifier of the banner for which to update the position + /// A new position for the banner + public static void UpdateBannerPosition(string adUnitIdentifier, BannerPosition bannerPosition) + { + Debug.Log("[AppLovin MAX] Updating banner position to '" + bannerPosition + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Updates the position of the banner to the new coordinates provided. + /// + /// The ad unit identifier of the banner for which to update the position + /// The X coordinate (horizontal position) of the banner relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the banner relative to the top left corner of the screen. + /// + /// The banner is placed within the safe area of the screen. You can use this to get the absolute position of the banner on screen. + /// + public static void UpdateBannerPosition(string adUnitIdentifier, float x, float y) + { + MaxSdkLogger.UserDebug("Updating banner position to '(" + x + "," + y + ")"); + } + + /// + /// Overrides the width of the banner in points/dp. + /// + /// The ad unit identifier of the banner for which to override the width for + /// The desired width of the banner in points/dp + public static void SetBannerWidth(string adUnitIdentifier, float width) + { + // NOTE: Will implement in a future release + Debug.Log("[AppLovin MAX] Set banner width to '" + width + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Show banner at a position determined by the 'CreateBanner' call. + /// + /// Ad unit identifier of the banner to show + public static void ShowBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show banner"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("Banner '" + adUnitIdentifier + "' was not created, can not show it"); + } + else + { + GameObject stubBanner; + if (StubBanners.TryGetValue(adUnitIdentifier, out stubBanner)) + { + stubBanner.SetActive(true); + } + } + } + + /// + /// Remove banner from the ad view and destroy it. + /// + /// Ad unit identifier of the banner to destroy + public static void DestroyBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy banner"); + + GameObject stubBanner; + if (StubBanners.TryGetValue(adUnitIdentifier, out stubBanner)) + { + Object.Destroy(stubBanner); + StubBanners.Remove(adUnitIdentifier); + } + } + + /// + /// Hide banner. + /// + /// Ad unit identifier of the banner to hide + /// + public static void HideBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide banner"); + + GameObject stubBanner; + if (StubBanners.TryGetValue(adUnitIdentifier, out stubBanner)) + { + stubBanner.SetActive(false); + } + } + + /// + /// Set non-transparent background color for banners to be fully functional. + /// + /// Ad unit identifier of the banner to set background color for + /// A background color to set for the ad + /// + public static void SetBannerBackgroundColor(string adUnitIdentifier, Color color) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set background color"); + + GameObject stubBanner; + if (StubBanners.TryGetValue(adUnitIdentifier, out stubBanner)) + { + stubBanner.GetComponentInChildren().color = color; + } + } + + /// + /// Set an extra parameter for the banner ad. + /// + /// Ad unit identifier of the banner to set the extra parameter for. + /// The key for the extra parameter. + /// The value for the extra parameter. + public static void SetBannerExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner extra parameter"); + } + + /// + /// 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. + public static void SetBannerLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner local extra parameter"); + } + + /// + /// The custom data to tie the showing banner ad to, for ILRD and rewarded postbacks via the {CUSTOM_DATA} macro. Maximum size is 8KB. + /// + /// Banner ad unit identifier of the banner to set the custom data for. + /// The custom data to be set. + public static void SetBannerCustomData(string adUnitIdentifier, string customData) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner custom data"); + } + + /// + /// The banner position on the screen. When setting the banner position via or , + /// the banner is placed within the safe area of the screen. This returns the absolute position of the banner on screen. + /// + /// Ad unit identifier of the banner for which to get the position on screen. + /// A representing the banner position on screen. + public static Rect GetBannerLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get banner layout"); + return Rect.zero; + } + + #endregion + + #region MRECs + + /// + /// Create a new MREC. + /// + /// Ad unit identifier of the MREC to create + /// MREC position + public static void CreateMRec(string adUnitIdentifier, AdViewPosition mrecPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create MREC"); + RequestAdUnit(adUnitIdentifier); + + ExecuteWithDelay(1f, () => + { + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnMRecAdLoadedEvent", adUnitIdentifier)); + MaxSdkCallbacks.Instance.ForwardEvent(eventProps); + }); + } + + /// + /// Create a new MREC with a custom position. + /// + /// Ad unit identifier of the MREC to create + /// The X coordinate (horizontal position) of the MREC relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the MREC relative to the top left corner of the screen. + /// + /// The MREC is placed within the safe area of the screen. You can use this to get the absolute position Rect of the MREC on screen. + /// + public static void CreateMRec(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create MREC"); + RequestAdUnit(adUnitIdentifier); + } + + /// + /// Load a new MREC ad. + /// NOTE: The method loads the first MREC ad and initiates an automated MREC refresh process. + /// You only need to call this method if you pause MREC refresh. + /// + /// Ad unit identifier of the MREC to load + public static void LoadMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load MREC"); + + ExecuteWithDelay(1f, () => + { + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnMRecAdLoadedEvent", adUnitIdentifier)); + MaxSdkCallbacks.Instance.ForwardEvent(eventProps); + }); + } + + /// + /// Set the MREC placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the MREC to set the placement for + /// Placement to set + public static void SetMRecPlacement(string adUnitIdentifier, string placement) + { + MaxSdkLogger.UserDebug("Setting MREC placement to '" + placement + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Starts or resumes auto-refreshing of the MREC for the given ad unit identifier. + /// + /// Ad unit identifier of the MREC for which to start auto-refresh + public static void StartMRecAutoRefresh(string adUnitIdentifier) + { + MaxSdkLogger.UserDebug("Starting banner auto refresh."); + } + + /// + /// Pauses auto-refreshing of the MREC for the given ad unit identifier. + /// + /// Ad unit identifier of the MREC for which to stop auto-refresh + public static void StopMRecAutoRefresh(string adUnitIdentifier) + { + MaxSdkLogger.UserDebug("Stopping banner auto refresh."); + } + + /// + /// Updates the position of the MREC to the new position provided. + /// + /// The ad unit identifier of the MREC for which to update the position + /// A new position for the MREC + public static void UpdateMRecPosition(string adUnitIdentifier, AdViewPosition mrecPosition) + { + MaxSdkLogger.UserDebug("Updating MREC position to '" + mrecPosition + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Updates the position of the MREC to the new coordinates provided. + /// + /// The ad unit identifier of the MREC for which to update the position + /// The X coordinate (horizontal position) of the MREC relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the MREC relative to the top left corner of the screen. + /// + /// The MREC is placed within the safe area of the screen. You can use this to get the absolute position Rect of the MREC on screen. + /// + public static void UpdateMRecPosition(string adUnitIdentifier, float x, float y) + { + MaxSdkLogger.UserDebug("Updating MREC position to '(" + x + "," + y + ")"); + } + + /// + /// Show MREC at a position determined by the 'CreateMRec' call. + /// + /// Ad unit identifier of the MREC to show + public static void ShowMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show MREC"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("MREC '" + adUnitIdentifier + "' was not created, can not show it"); + } + } + + /// + /// Remove MREC from the ad view and destroy it. + /// + /// Ad unit identifier of the MREC to destroy + public static void DestroyMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy MREC"); + } + + /// + /// Hide MREC. + /// + /// Ad unit identifier of the MREC to hide + public static void HideMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide MREC"); + } + + /// + /// Set an extra parameter for the MREC ad. + /// + /// Ad unit identifier of the MREC to set the extra parameter for. + /// The key for the extra parameter. + /// The value for the extra parameter. + public static void SetMRecExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC extra parameter"); + } + + /// + /// 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. + public static void SetMRecLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC local extra parameter"); + } + + /// + /// The custom data to tie the showing MREC ad to, for ILRD and rewarded postbacks via the {CUSTOM_DATA} macro. Maximum size is 8KB. + /// + /// MREC Ad unit identifier of the banner to set the custom data for. + /// The custom data to be set. + public static void SetMRecCustomData(string adUnitIdentifier, string customData) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC custom data"); + } + + /// + /// The MREC position on the screen. When setting the MREC position via or , + /// the MREC is placed within the safe area of the screen. This returns the absolute position of the MREC on screen. + /// + /// Ad unit identifier of the MREC for which to get the position on screen. + /// A representing the banner position on screen. + public static Rect GetMRecLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get MREC layout"); + return Rect.zero; + } + + #endregion + + #region Cross Promo Ads + + /// + /// Create a new cross promo ad with a custom position. + /// + /// Ad unit identifier of the cross promo ad to create + /// The X coordinate (horizontal position) of the cross promo ad relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the cross promo ad relative to the top left corner of the screen. + /// The width of the cross promo ad. + /// The height of the cross promo ad. + /// The rotation of the cross promo ad in degrees. + /// + /// The cross promo is placed within the safe area of the screen. You can use this to get the absolute position Rect of the cross promo ad on screen. + /// + public static void CreateCrossPromoAd(string adUnitIdentifier, float x, float y, float width, float height, float rotation) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create cross promo ad"); + RequestAdUnit(adUnitIdentifier); + } + + /// + /// Set the cross promo ad placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the cross promo ad to set the placement for + /// Placement to set + public static void SetCrossPromoAdPlacement(string adUnitIdentifier, string placement) + { + MaxSdkLogger.UserDebug("Setting cross promo ad placement to '" + placement + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Updates the position of the cross promo ad to the new coordinates provided. + /// + /// The ad unit identifier of the cross promo ad for which to update the position + /// The X coordinate (horizontal position) of the cross promo ad relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the cross promo ad relative to the top left corner of the screen. + /// The width of the cross promo ad. + /// The height of the cross promo ad. + /// The rotation of the cross promo ad in degrees. + /// + /// The cross promo ad is placed within the safe area of the screen. You can use this to get the absolute position Rect of the cross promo ad on screen. + /// + public static void UpdateCrossPromoAdPosition(string adUnitIdentifier, float x, float y, float width, float height, float rotation) + { + MaxSdkLogger.UserDebug("Updating cross promo ad position to (" + x + "," + y + ") with size " + width + " x " + height + " and rotation of " + rotation + " degrees"); + } + + /// + /// Show cross promo ad at a position determined by the 'CreateCrossPromoAd' call. + /// + /// Ad unit identifier of the cross promo ad to show + public static void ShowCrossPromoAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show cross promo ad"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("Cross promo ad '" + adUnitIdentifier + "' was not created, can not show it"); + } + } + + /// + /// Remove cross promo ad from the ad view and destroy it. + /// + /// Ad unit identifier of the cross promo ad to destroy + public static void DestroyCrossPromoAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy cross promo ad"); + } + + /// + /// Hide cross promo ad. + /// + /// Ad unit identifier of the cross promo ad to hide + public static void HideCrossPromoAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide cross promo ad"); + } + + /// + /// The cross promo ad position on the screen. When setting the cross promo ad position via or , + /// the cross promo ad is placed within the safe area of the screen. This returns the absolute position of the cross promo ad on screen. + /// + /// Ad unit identifier of the cross promo ad for which to get the position on screen. + /// A representing the banner position on screen. + public static Rect GetCrossPromoAdLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get cross promo ad layout"); + return Rect.zero; + } + + #endregion + + #region Interstitials + + /// + /// Start loading an interstitial. + /// + /// Ad unit identifier of the interstitial to load + public static void LoadInterstitial(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load interstitial"); + RequestAdUnit(adUnitIdentifier); + + ExecuteWithDelay(1f, () => + { + AddReadyAdUnit(adUnitIdentifier); + + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnInterstitialLoadedEvent", adUnitIdentifier)); + MaxSdkCallbacks.Instance.ForwardEvent(eventProps); + }); + } + + /// + /// Check if interstitial ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the interstitial to load + /// True if the ad is ready to be displayed + public static bool IsInterstitialReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check interstitial loaded"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("Interstitial '" + adUnitIdentifier + + "' was not requested, can not check if it is loaded"); + return false; + } + + return IsAdUnitReady(adUnitIdentifier); + } + + /// + /// Present loaded interstitial for a given placement to tie ad events to. Note: if the interstitial is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the interstitial to load + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowInterstitial(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show interstitial"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning( + "Interstitial '" + adUnitIdentifier + "' was not requested, can not show it"); + return; + } + + if (!IsInterstitialReady(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("Interstitial '" + adUnitIdentifier + "' is not ready, please check IsInterstitialReady() before showing."); + return; + } + + RemoveReadyAdUnit(adUnitIdentifier); + + if (_showStubAds) + { + ShowStubInterstitial(adUnitIdentifier); + } + } + + private static void ShowStubInterstitial(string adUnitIdentifier) + { +#if UNITY_EDITOR + var prefabPath = MaxSdkUtils.GetAssetPathForExportPath("MaxSdk/Prefabs/Interstitial.prefab"); + var interstitialPrefab = AssetDatabase.LoadAssetAtPath(prefabPath); + var stubInterstitial = Object.Instantiate(interstitialPrefab, Vector3.zero, Quaternion.identity); + var interstitialText = GameObject.Find("MaxInterstitialTitle").GetComponent(); + var closeButton = GameObject.Find("MaxInterstitialCloseButton").GetComponent