From 66117704f5f2a4bc81d5b5a88bfdc6abe27adad1 Mon Sep 17 00:00:00 2001 From: Eschenko_D Date: Mon, 28 Dec 2020 16:33:41 +0200 Subject: [PATCH] Release 1.9.1 --- CHANGELOG.md | 17 ++ Editor/CASEditorUtils.cs | 2 +- Editor/CASInitSettignsInspector.cs | 39 +-- Editor/CASInternal.cs | 142 ++++++--- Editor/CASPostprocessBuild.cs | 64 +++- Editor/DependencyManager.cs | 15 +- Plugins/Android/libs/cas-unity.jar | Bin 28998 -> 30361 bytes Plugins/iOS/CASUInterface.m | 67 ++++- Plugins/iOS/CASUManager.h | 1 + Plugins/iOS/CASUManager.m | 18 +- Plugins/iOS/CASUTypes.h | 4 +- README.md | 312 ++++++++++++-------- Runtime/Android/CASJavaProxy.cs | 4 +- Runtime/Android/CASMediationManager.cs | 40 ++- Runtime/Android/CASSettings.cs | 10 + Runtime/CASFactory.cs | 146 ++++----- Runtime/CASInitSettings.cs | 121 ++++++++ Runtime/Common/AdNetwork.cs | 25 ++ Runtime/Common/AdNetwork.cs.meta | 13 + Runtime/Common/MediationExtras.cs | 52 ++++ Runtime/Common/MediationExtras.cs.meta | 13 + Runtime/Common/MobileAds.cs | 58 +++- Runtime/Unity/CASMediationManager.cs | 6 +- Runtime/iOS/AppTrackingTransparency.cs | 76 +++++ Runtime/iOS/AppTrackingTransparency.cs.meta | 13 + Runtime/iOS/CASExterns.cs | 23 ++ Runtime/iOS/CASMediationManager.cs | 75 ++--- Templates/CASAndroidMediation.list | 2 +- Templates/CASSKAdNetworks.txt | 3 + Templates/CASiOSMediation.list | 2 +- package.json | 2 +- 31 files changed, 1005 insertions(+), 360 deletions(-) create mode 100644 Runtime/Common/AdNetwork.cs create mode 100644 Runtime/Common/AdNetwork.cs.meta create mode 100644 Runtime/Common/MediationExtras.cs create mode 100644 Runtime/Common/MediationExtras.cs.meta create mode 100644 Runtime/iOS/AppTrackingTransparency.cs create mode 100644 Runtime/iOS/AppTrackingTransparency.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index baa2a2f..7f8f2e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Clever Ads Solutions Unity Plugin Change Log +## [1.9.1] - 2020-12-28 +### Dependencies +- [Android] Wraps [1.9.1 SDK](https://github.com/cleveradssolutions/CAS-Android/releases) +- [iOS] Wraps [1.9.1 SDK](https://github.com/cleveradssolutions/CAS-iOS/releases) +### Features +- Added `CAS.MobileAds.BuildManager().Initialize()` [builder](https://github.com/cleveradssolutions/CAS-Unity#step-4-initialize-cas-sdk) to initialize the `IMediationManager` for alternative to `CAS.MobileAds.Initialize(...)` method. +- Added [Mediation extras](https://github.com/cleveradssolutions/CAS-Unity#mediation-extras) options. +- [iOS] Added `CAS.iOS.AppTrackingTransparency` class that provides a [tracking authorization request](https://github.com/cleveradssolutions/CAS-Unity#include-ios). +### Changes +- Migrated Cross-promotion dependency from `Advanced Integration` to `Solutions` section. +- `CAS.MobileAds.InitializeFromResources()` is obsolete in favor of `BuildManager()`. +- [iOS] `SKAdNetworkItems` are added to end of the Plist array instead of replacing all items in the array. +### Bug Fixes +- [iOS] `Library not loaded` while laoding application with Unity 2019.3+. The `Unity-iPhone` pod target is added automatically after build. +- [Android] `java.lang.NoSuchMethodError` when call `CAS.MobileAds.ValidateIntegration()` +- [Editor] Select the correct CAS Settings asset from resources by the build target platform. + ## [1.8.3] - 2020-12-18 ### Dependencies - [Android] Wraps [1.8.3 SDK](https://github.com/cleveradssolutions/CAS-Android/releases) diff --git a/Editor/CASEditorUtils.cs b/Editor/CASEditorUtils.cs index f928780..9c96a93 100644 --- a/Editor/CASEditorUtils.cs +++ b/Editor/CASEditorUtils.cs @@ -39,7 +39,7 @@ public static class CASEditorUtils internal const string gitUnityRepo = "CAS-Unity"; internal const string gitUnityRepoURL = gitRootURL + gitUnityRepo; internal const string supportURL = gitUnityRepoURL + "#support"; - internal const string configuringPrivacyURL = gitUnityRepoURL + "#step-2-configuring-cas-sdk"; + internal const string configuringPrivacyURL = gitUnityRepoURL + "#include-ios"; internal const string websiteURL = "https://cleveradssolutions.com"; internal const string generalDeprecateDependency = "General"; diff --git a/Editor/CASInitSettignsInspector.cs b/Editor/CASInitSettignsInspector.cs index 059fbd3..2c600dd 100644 --- a/Editor/CASInitSettignsInspector.cs +++ b/Editor/CASInitSettignsInspector.cs @@ -30,11 +30,9 @@ internal class CASInitSettignsInspector : Editor private bool allowedPackageUpdate; private string newCASVersion; private bool deprecateDependenciesExist; - private bool usingMultidexOnBuild; + //private bool usingMultidexOnBuild; private int editorRuntimeActiveAdFlags; - private GUIStyle boxScopeStyle = null; - private GUIStyle wordWrapTextAred = null; private void OnEnable() { @@ -73,7 +71,7 @@ private void OnEnable() allowedPackageUpdate = Utils.IsPackageExist( Utils.packageName ); newCASVersion = Utils.GetNewVersionOrNull( Utils.gitUnityRepo, MobileAds.wrapperVersion, false ); - usingMultidexOnBuild = PlayerPrefs.GetInt( Utils.editorIgnoreMultidexPrefs, 0 ) == 0; + //usingMultidexOnBuild = PlayerPrefs.GetInt( Utils.editorIgnoreMultidexPrefs, 0 ) == 0; dependencyManager = DependencyManager.Create( platform, ( Audience )audienceTaggedProp.enumValueIndex, true ); } @@ -96,15 +94,9 @@ public override void OnInspectorGUI() var obj = serializedObject; obj.UpdateIfRequiredOrScript(); - if (wordWrapTextAred == null) - { - wordWrapTextAred = new GUIStyle( EditorStyles.textArea ); - wordWrapTextAred.wordWrap = true; - } - LinksToolbarGUI(); - BeginBoxScope(); + HelpStyles.BeginBoxScope(); EditorGUILayout.PropertyField( testAdModeProp ); EditorGUI.BeginDisabledGroup( testAdModeProp.boolValue ); managerIdsList.DoLayoutList(); @@ -115,7 +107,7 @@ public override void OnInspectorGUI() GUILayout.Label( "These settings are required for initialization with: CAS.MobileAds.InitializeFromResources(0)", EditorStyles.wordWrappedMiniLabel, GUILayout.ExpandHeight( false ) ); - EndBoxScope(); + HelpStyles.EndBoxScope(); DrawSeparator(); OnAudienceGUI(); @@ -154,9 +146,7 @@ public override void OnInspectorGUI() } else { - BeginBoxScope(); dependencyManager.OnGUI( platform ); - EndBoxScope(); } obj.ApplyModifiedProperties(); @@ -226,8 +216,8 @@ private void OnIOSLocationUsageDescriptionGUI() EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel++; trackingUsageDescriptionProp.stringValue = - EditorGUILayout.TextArea( trackingUsageDescriptionProp.stringValue, wordWrapTextAred ); - EditorGUILayout.HelpBox( "NSUserTrackingUsageDescription key with a custom message describing your usage. Can be empty.", MessageType.None ); + EditorGUILayout.TextArea( trackingUsageDescriptionProp.stringValue, HelpStyles.wordWrapTextAred ); + EditorGUILayout.HelpBox( "NSUserTrackingUsageDescription key with a custom message describing your usage location tracking to AppTrackingTransparency.Request(). Can be empty if not using location tracking", MessageType.None ); EditorGUI.indentLevel--; EditorGUILayout.PropertyField( trackLocationEnabledProp ); @@ -367,23 +357,6 @@ private void DeprecatedDependenciesGUI() EditorGUILayout.EndHorizontal(); } } - - private void BeginBoxScope() - { - if (boxScopeStyle == null) - { - boxScopeStyle = new GUIStyle( EditorStyles.helpBox ); - var p = boxScopeStyle.padding; - p.right += 3; - p.left += 3; - } - EditorGUILayout.BeginVertical( boxScopeStyle ); - } - - private void EndBoxScope() - { - EditorGUILayout.EndVertical(); - } } } #pragma warning restore 649 \ No newline at end of file diff --git a/Editor/CASInternal.cs b/Editor/CASInternal.cs index d492b77..db58b92 100644 --- a/Editor/CASInternal.cs +++ b/Editor/CASInternal.cs @@ -8,6 +8,83 @@ namespace CAS.UEditor { + + internal static class HelpStyles + { + private static GUIStyle boxScopeStyle; + public static GUIStyle wordWrapTextAred; + + public static GUIContent helpIconContent; + public static GUIContent errorIconContent; + private static GUIContent tempContent; + + + static HelpStyles() + { + boxScopeStyle = new GUIStyle( EditorStyles.helpBox ); + boxScopeStyle.padding = new RectOffset( 6, 6, 6, 6 ); + wordWrapTextAred = new GUIStyle( EditorStyles.textArea ); + wordWrapTextAred.wordWrap = true; + + errorIconContent = EditorGUIUtility.IconContent( "d_console.erroricon.sml" ); + helpIconContent = EditorGUIUtility.IconContent( "_Help" ); + tempContent = new GUIContent(); + } + + public static void OnLabelGUI( Dependency.Label label ) + { + if (label == Dependency.Label.None) + return; + if (( label & Dependency.Label.Banner ) == Dependency.Label.Banner) + { + tempContent.text = "B"; + tempContent.tooltip = "Support Banner Ad"; + GUILayout.Label( tempContent, "AssetLabel", GUILayout.ExpandWidth( false ) ); + } + else + { + GUILayout.Label( " B ", GUILayout.ExpandWidth( false ) ); + } + if (( label & Dependency.Label.Inter ) == Dependency.Label.Inter) + { + tempContent.text = "I"; + tempContent.tooltip = "Support Interstitial Ad"; + GUILayout.Label( tempContent, "AssetLabel", GUILayout.ExpandWidth( false ) ); + } + else + { + GUILayout.Label( " I ", GUILayout.ExpandWidth( false ) ); + } + if (( label & Dependency.Label.Reward ) == Dependency.Label.Reward) + { + tempContent.text = "R"; + tempContent.tooltip = "Support Rewarded Video Ad"; + GUILayout.Label( tempContent, "AssetLabel", GUILayout.ExpandWidth( false ) ); + } + else + { + GUILayout.Label( " R ", GUILayout.ExpandWidth( false ) ); + } + if (( label & Dependency.Label.Beta ) == Dependency.Label.Beta) + { + tempContent.text = "beta"; + tempContent.tooltip = "Dependencies in closed beta and available upon invite only. " + + "If you would like to be considered for the beta, please contact Support."; + GUILayout.Label( tempContent, "AssetLabel", GUILayout.ExpandWidth( false ) ); + } + } + + public static void BeginBoxScope() + { + EditorGUILayout.BeginVertical( boxScopeStyle ); + } + + public static void EndBoxScope() + { + EditorGUILayout.EndVertical(); + } + } + public partial class DependencyManager { #region Internal implementation @@ -18,9 +95,6 @@ public partial class DependencyManager private List other = new List(); internal GUILayoutOption columnWidth; - internal GUILayoutOption nameColumnWidth; - internal GUIContent helpIconContent = null; - internal GUIContent betaContent = null; internal bool installedAny; @@ -32,8 +106,6 @@ public partial class DependencyManager internal void Init( BuildTarget platform, bool deepInit = true ) { - helpIconContent = null; - betaContent = null; installedAny = false; for (int i = 0; i < simple.Length; i++) simple[i].Reset(); @@ -81,42 +153,43 @@ internal void Init( BuildTarget platform, bool deepInit = true ) firebaseDeepLinksExist = Utils.IsFirebaseServiceExist( "dynamic" ); } + private void OnHeaderGUI() + { + EditorGUILayout.BeginHorizontal(); + GUILayout.Space( 25 ); + GUILayout.Label( "Dependency", EditorStyles.largeLabel ); + GUILayout.Label( "Current", EditorStyles.largeLabel, columnWidth ); + GUILayout.Label( "Latest", EditorStyles.largeLabel, columnWidth ); + GUILayout.Label( "Action", EditorStyles.largeLabel, columnWidth ); + EditorGUILayout.EndHorizontal(); + } + internal void OnGUI( BuildTarget platform ) { - if (helpIconContent == null) - helpIconContent = EditorGUIUtility.IconContent( "_Help" ); - if (betaContent == null) - betaContent = new GUIContent( "beta", "Dependencies in closed beta and available upon invite only. " + - "If you would like to be considered for the beta, please contact Support." ); if (!installedAny) EditorGUILayout.HelpBox( "Dependencies of native SDK were not found. " + "Please use the following options to integrate solutions or any SDK separately.", MessageType.Warning ); columnWidth = GUILayout.MaxWidth( EditorGUIUtility.currentViewWidth * 0.15f ); - nameColumnWidth = GUILayout.MaxWidth( EditorGUIUtility.currentViewWidth * 0.32f ); - EditorGUILayout.BeginHorizontal(); - GUILayout.Space( 25 ); - GUILayout.Label( "Dependency", EditorStyles.largeLabel, nameColumnWidth ); - GUILayout.Label( "Current", EditorStyles.largeLabel, columnWidth ); - GUILayout.Label( "Latest", EditorStyles.largeLabel, columnWidth ); - GUILayout.Label( "Action", EditorStyles.largeLabel, columnWidth ); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); if (simple.Length > 0) { - solutionsFoldout = GUILayout.Toggle( solutionsFoldout, "Solutions", EditorStyles.toolbarButton ); + HelpStyles.BeginBoxScope(); + solutionsFoldout = GUILayout.Toggle( solutionsFoldout, "Solutions", EditorStyles.foldout ); if (solutionsFoldout) { + OnHeaderGUI(); for (int i = 0; i < simple.Length; i++) simple[i].OnGUI( this, platform ); } + HelpStyles.EndBoxScope(); } if (advanced.Length > 0) { - advancedFoldout = GUILayout.Toggle( advancedFoldout, "Advanced Integration", EditorStyles.toolbarButton ); + HelpStyles.BeginBoxScope(); + advancedFoldout = GUILayout.Toggle( advancedFoldout, "Advanced Integration", EditorStyles.foldout ); if (!advancedFoldout) { for (int i = 0; i < advanced.Length; i++) @@ -134,18 +207,22 @@ internal void OnGUI( BuildTarget platform ) } if (advancedFoldout) { + OnHeaderGUI(); for (int i = 0; i < advanced.Length; i++) advanced[i].OnGUI( this, platform ); } + HelpStyles.EndBoxScope(); } if (other.Count > 0) { - otherFoldout = GUILayout.Toggle( otherFoldout, "Other Active Dependencies: " + other.Count, EditorStyles.toolbarButton ); + HelpStyles.BeginBoxScope(); + otherFoldout = GUILayout.Toggle( otherFoldout, "Other Active Dependencies: " + other.Count, EditorStyles.foldout ); if (otherFoldout) { for (int i = 0; i < other.Count; i++) other[i].OnGUI( this ); } + HelpStyles.EndBoxScope(); } EditorGUILayout.HelpBox( "Please provide us with a list of integrated dependencies " + @@ -164,11 +241,6 @@ internal void OnGUI( BuildTarget platform ) } EditorGUILayout.EndHorizontal(); } - else if (platform == BuildTarget.iOS && !firebaseDeepLinksExist) - { - EditorGUILayout.HelpBox( "CAS Cross-promotion uses deep links to track conversions. " + - "Please add Firebase Deep Link dependency to the project.", MessageType.Warning ); - } } internal void SetAudience( Audience audience ) @@ -278,22 +350,14 @@ internal void OnGUI( DependencyManager mediation, BuildTarget platform ) EditorGUILayout.BeginHorizontal(); bool installed = !string.IsNullOrEmpty( installedVersion ); if (( inBan && installed ) || ( installed && locked ) || ( isRequired && !locked && !installed )) - GUILayout.Label( EditorGUIUtility.IconContent( "d_console.erroricon.sml" ), GUILayout.Width( 20 ) ); + GUILayout.Label( HelpStyles.errorIconContent, GUILayout.Width( 20 ) ); else if (string.IsNullOrEmpty( url )) GUILayout.Space( 25 ); - else if (GUILayout.Button( mediation.helpIconContent, EditorStyles.label, GUILayout.Width( 20 ) )) + else if (GUILayout.Button( HelpStyles.helpIconContent, EditorStyles.label, GUILayout.Width( 20 ) )) Application.OpenURL( url ); - if (beta) - { - GUILayout.Label( name, GUILayout.ExpandWidth( false ) ); - GUILayout.Label( mediation.betaContent, "AssetLabel", GUILayout.ExpandWidth( false ) ); - GUILayout.FlexibleSpace(); - } - else - { - GUILayout.Label( name ); - } + HelpStyles.OnLabelGUI( labels ); + GUILayout.Label( name ); if (installed) { diff --git a/Editor/CASPostprocessBuild.cs b/Editor/CASPostprocessBuild.cs index fdafa6a..a07aa61 100644 --- a/Editor/CASPostprocessBuild.cs +++ b/Editor/CASPostprocessBuild.cs @@ -1,7 +1,6 @@ #if UNITY_IOS || CASDeveloper using System; using System.Collections.Generic; -using System.Dynamic; using System.IO; using UnityEditor; using UnityEditor.Callbacks; @@ -36,6 +35,31 @@ public static void OnPostProcessBuild( BuildTarget buildTarget, string path ) } } +#if UNITY_2019_3_OR_NEWER + [PostProcessBuild( 45 )]//must be between 40 and 50 to ensure that it's not overriden by Podfile generation (40) and that it's added before "pod install" (50) + private static void FixPodFileBug( BuildTarget target, string buildPath ) + { + if (target != BuildTarget.iOS) + return; + var podPath = buildPath + "/Podfile"; + if (!File.Exists( podPath )) + { + Debug.LogError( CASEditorUtils.logTag + "Podfile not found.\n" + + "Please add `target 'Unity-iPhone' do end` to the Podfile in root folder of XCode project and call `pod install --no-repo-update`" ); + return; + } + var content = File.ReadAllText( podPath ); + if (content.Contains( "'Unity-iPhone'" )) + return; + using (StreamWriter sw = File.AppendText( podPath )) + { + sw.WriteLine(); + sw.WriteLine( "target 'Unity-iPhone' do" ); + sw.WriteLine( "end" ); + } + } +#endif + private static void ConfigureInfoPlist( string plistPath ) { EditorUtility.DisplayProgressBar( casTitle, "Read iOS Info.plist", 0.3f ); @@ -88,26 +112,39 @@ private static void ConfigureInfoPlist( string plistPath ) EditorUtility.DisplayProgressBar( casTitle, "Write SKAdNetworks to Info.plist", 0.5f ); var templateFile = CASEditorUtils.GetTemplatePath( CASEditorUtils.iosSKAdNetworksTemplateFile ); if (string.IsNullOrEmpty( templateFile )) - CASEditorUtils.StopBuildWithMessage( "Not found SKAdNetworkItems. Try reimport CAS package.", BuildTarget.iOS ); - var networksLines = File.ReadAllLines( templateFile ); - var adNetworkItems = plist.root.CreateArray( "SKAdNetworkItems" ); + { + Debug.LogError( CASEditorUtils.logTag + "Not found SKAdNetworkItems. Try reimport CAS package." ); + } + else + { + var networksLines = File.ReadAllLines( templateFile ); + + PlistElementArray adNetworkItems; + var adNetworkItemsField = plist.root["SKAdNetworkItems"]; + if (adNetworkItemsField == null) + adNetworkItems = plist.root.CreateArray( "SKAdNetworkItems" ); + else + adNetworkItems = adNetworkItemsField.AsArray(); - for (int i = 0; i < networksLines.Length; i++) - if (!string.IsNullOrEmpty( networksLines[i] )) + for (int i = 0; i < networksLines.Length; i++) { - var dict = adNetworkItems.AddDict(); - dict.SetString( "SKAdNetworkIdentifier", networksLines[i] ); + if (!string.IsNullOrEmpty( networksLines[i] )) + { + var dict = adNetworkItems.AddDict(); + dict.SetString( "SKAdNetworkIdentifier", networksLines[i] ); + } } + } #endregion #region Write LSApplicationQueriesSchemes EditorUtility.DisplayProgressBar( casTitle, "Write LSApplicationQueriesSchemes to Info.plist", 0.6f ); PlistElementArray applicationQueriesSchemes; var applicationQueriesSchemesField = plist.root["LSApplicationQueriesSchemes"]; - if (applicationQueriesSchemesField != null) - applicationQueriesSchemes = applicationQueriesSchemesField.AsArray(); - else + if (applicationQueriesSchemesField == null) applicationQueriesSchemes = plist.root.CreateArray( "LSApplicationQueriesSchemes" ); + else + applicationQueriesSchemes = applicationQueriesSchemesField.AsArray(); foreach (var scheme in new[] { "fb", "instagram", "tumblr", "twitter" }) if (applicationQueriesSchemes.values.Find( x => x.AsString() == scheme ) == null) applicationQueriesSchemes.AddString( scheme ); @@ -128,8 +165,9 @@ private static void ConfigureXCodeProject( string rootPath, string projectPath ) var target = project.TargetGuidByName( PBXProject.GetUnityTargetName() ); #endif project.SetBuildProperty( target, "ENABLE_BITCODE", "No" ); - project.AddBuildProperty( target, "OTHER_LDFLAGS", "-lxml2 -ObjC -fobjc-arc" ); - project.AddBuildProperty( target, "CLANG_ENABLE_MODULES", "YES" ); // InMobi required + project.AddBuildProperty( target, "OTHER_LDFLAGS", "-ObjC" ); + //project.AddBuildProperty( target, "OTHER_LDFLAGS", "-lxml2 -ObjC -fobjc-arc" ); + //project.AddBuildProperty( target, "CLANG_ENABLE_MODULES", "YES" ); // InMobi required project.SetBuildProperty( target, "SWIFT_VERSION", "5.0" ); EditorUtility.DisplayProgressBar( casTitle, "Copy CAS Settings json to project", 0.8f ); diff --git a/Editor/DependencyManager.cs b/Editor/DependencyManager.cs index 7c62423..9518e8b 100644 --- a/Editor/DependencyManager.cs +++ b/Editor/DependencyManager.cs @@ -63,9 +63,22 @@ public Dependency FindCrossPromotion() } } + + [Serializable] public partial class Dependency { + [Flags] + public enum Label + { + None = 0, + Banner = 1, + Inter = 2, + Reward = 4, + Native = 8, + Beta = 16, + } + public string name; public string version; public string require; @@ -74,7 +87,7 @@ public partial class Dependency public string[] dependencies; public string[] contains; public string[] source; - public bool beta; + public Label labels = Label.Banner | Label.Inter | Label.Reward; public string installedVersion { get; set; } public bool isNewer { get; set; } diff --git a/Plugins/Android/libs/cas-unity.jar b/Plugins/Android/libs/cas-unity.jar index a8d19474d4746412ccc6f09dd637a8ec5f169cf9..e53c652d093d45890faceac78af833a4a7bc665f 100644 GIT binary patch delta 10048 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 delta 9218 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 diff --git a/Plugins/iOS/CASUInterface.m b/Plugins/iOS/CASUInterface.m index de630f5..da46355 100644 --- a/Plugins/iOS/CASUInterface.m +++ b/Plugins/iOS/CASUInterface.m @@ -13,6 +13,7 @@ #if __has_include("UnityAppController.h") #import "UnityAppController.h" #endif +#import static NSString * CASUStringFromUTF8String(const char *bytes) { @@ -141,11 +142,42 @@ void CASUOpenDebugger() NSLog(@"[CAS] Framework bridge cant find CASDebugger.h"); } +const char * CASUGetActiveMediationPattern() +{ + return cStringCopy([CASNetwork getActiveNetworkPattern].UTF8String); +} + +BOOL CASUIsActiveMediationNetwork(NSInteger net) +{ + NSArray *values = [CASNetwork values]; + if (net > 0 && net < [values count]) { + return [CASNetwork isActiveNetwork:[values objectAtIndex:net]]; + } + return NO; +} + const char * CASUGetSDKVersion() { return cStringCopy([CAS getSDKVersion].UTF8String); } +#pragma mark - CAS ATTrackingManager + +void CASURequestTracking(CASUTrackingStatusCallback callback) +{ + if (@available(iOS 14, *)) { + [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) { + if (callback) { + callback(status); + } + }]; + } else { + if (callback) { + callback(3); + } + } +} + #pragma mark - CAS Manager CASUTypeManagerRef CASUCreateManager(CASUTypeManagerClientRef *client, @@ -156,10 +188,37 @@ CASUTypeManagerRef CASUCreateManager(CASUTypeManagerClientRef *client, { CASUManager *manager = [[CASUManager alloc] initWithAppID:CASUStringFromUTF8String(managerID) - enable:enableAd - demoAd:demoAd - forClient:client - onInit:onInit]; + enable:enableAd + demoAd:demoAd + forClient:client + mediationExtras:nil + onInit:onInit]; + + CASUPluginUtil *cache = [CASUPluginUtil sharedInstance]; + [cache saveObject:manager withKey:manager.mediationManager.managerID]; + return (__bridge CASUTypeManagerRef)manager; +} + +CASUTypeManagerRef CASUCreateManagerWithExtras(CASUTypeManagerClientRef *client, + CASUInitializationCompleteCallback onInit, + const char *managerID, + NSInteger enableAd, + BOOL demoAd, + const char **extraKeys, + const char **extraValues, + NSInteger extrasCount) +{ + NSDictionary *mediationExtras = [[NSDictionary alloc] init]; + for (int i = 0; i < extrasCount; i++) { + [mediationExtras setValue:CASUStringFromUTF8String(extraKeys[i]) forKey:CASUStringFromUTF8String(extraValues[i])]; + } + CASUManager *manager = [[CASUManager alloc] + initWithAppID:CASUStringFromUTF8String(managerID) + enable:enableAd + demoAd:demoAd + forClient:client + mediationExtras:mediationExtras + onInit:onInit]; CASUPluginUtil *cache = [CASUPluginUtil sharedInstance]; [cache saveObject:manager withKey:manager.mediationManager.managerID]; diff --git a/Plugins/iOS/CASUManager.h b/Plugins/iOS/CASUManager.h index 82bf8bf..acea5cd 100644 --- a/Plugins/iOS/CASUManager.h +++ b/Plugins/iOS/CASUManager.h @@ -17,6 +17,7 @@ enable:(NSUInteger)types demoAd:(BOOL)demoAd forClient:(CASUTypeManagerClientRef _Nullable *_Nullable)client + mediationExtras:(NSDictionary *_Nullable)extras onInit:(nullable CASUInitializationCompleteCallback)onInit; @property (nonatomic, strong, nonnull) CASMediationManager *mediationManager; diff --git a/Plugins/iOS/CASUManager.m b/Plugins/iOS/CASUManager.m index de01c0d..dcfb323 100644 --- a/Plugins/iOS/CASUManager.m +++ b/Plugins/iOS/CASUManager.m @@ -20,6 +20,7 @@ - (id)initWithAppID:(NSString *)appID enable:(NSUInteger)types demoAd:(BOOL)demoAd forClient:(CASUTypeManagerClientRef *)client + mediationExtras:(NSDictionary *_Nullable)extras onInit:(CASUInitializationCompleteCallback)onInit { self = [super init]; if (self) { @@ -28,15 +29,16 @@ - (id)initWithAppID:(NSString *)appID [CAS createWithManagerID:appID enableTypes:types demoAdMode:demoAd + mediationExtras:extras onInit:^(BOOL succses, NSString *_Nullable error) { - if (onInit) { - if (error) { - onInit(client, succses, [error cStringUsingEncoding:NSUTF8StringEncoding]); - } else { - onInit(client, succses, NULL); - } - } - }]; + if (onInit) { + if (error) { + onInit(client, succses, [error cStringUsingEncoding:NSUTF8StringEncoding]); + } else { + onInit(client, succses, NULL); + } + } + }]; bannerPositionId = 3; self.bannerCallback = [[CASUCallback alloc] initForFullScreen:NO]; diff --git a/Plugins/iOS/CASUTypes.h b/Plugins/iOS/CASUTypes.h index ffe2c90..902fd92 100644 --- a/Plugins/iOS/CASUTypes.h +++ b/Plugins/iOS/CASUTypes.h @@ -22,10 +22,12 @@ typedef void (*CASUDidAdFailedToLoadCallback)(CASUTypeManagerClientRef *client, typedef void (*CASUWillShownWithAdCallback)(CASUTypeManagerClientRef *client); typedef void (*CASUDidShowAdFailedWithErrorCallback)(CASUTypeManagerClientRef *client, - const char *error); + const char *error); typedef void (*CASUDidClickedAdCallback)(CASUTypeManagerClientRef *client); typedef void (*CASUDidCompletedAdCallback)(CASUTypeManagerClientRef *client); typedef void (*CASUDidClosedAdCallback)(CASUTypeManagerClientRef *client); + +typedef void (*CASUTrackingStatusCallback)(NSInteger status); diff --git a/README.md b/README.md index 30e50a3..412a3f3 100644 --- a/README.md +++ b/README.md @@ -32,11 +32,12 @@ The Integration Demo application demonstrate how to integrate the CAS in your ap 5. [Implement CAS Events](#step-5-implement-cas-events) 6. [Implement our Ad Units](#step-6-implement-our-ad-units) 7. [Include native platforms](#step-7-include-native-platforms) - 7.1 [Include Android](#include-android) - 7.2 [Include iOS](#include-ios) - 8. [GitHub issue tracker](#github-issue-tracker) - 9. [Support](#support) - 10. [License](#license) + 7.1. [Include Android](#include-android) + 7.2. [Include iOS](#include-ios) + 8. [Mediation extras](#mediation-extras) + 9. [GitHub issue tracker](#github-issue-tracker) + 10. [Support](#support) + 11. [License](#license) ## Step 1 Add the CAS package to Your Project if you are using Unity 2018.4 or newer then you can add CAS SDK to your Unity project using the [Unity Package Manager](https://docs.unity3d.com/Manual/upm-ui.html), or you can import the package manually. @@ -60,7 +61,7 @@ Modify `Packages/manifest.json` to the following form: ], "dependencies": { "com.cleversolutions.ads.unity" - : "https://github.com/cleveradssolutions/CAS-Unity.git#1.8.3" + : "https://github.com/cleveradssolutions/CAS-Unity.git#1.9.1" } } ``` @@ -111,7 +112,7 @@ Banner, Interstitial, Rewarded Video - [Home](https://www.superawesome.com) - [P - Facebook Audience Network Banner, Interstitial, Rewarded Video - [Home](https://www.facebook.com/business/marketing/audience-network) - [Privacy Policy](https://developers.facebook.com/docs/audience-network/policy/) - Yandex Ads -Banner, Interstitial, Rewarded Video - [Home](https://yandex.com/dev/mobile-ads/) - [Privacy Policy](https://yandex.com/legal/mobileads_sdk_agreement/) +Banner, Interstitial, ~~Rewarded Video~~ - [Home](https://yandex.com/dev/mobile-ads/) - [Privacy Policy](https://yandex.com/legal/mobileads_sdk_agreement/) #### Dependencies of Closed Beta third party partners: > :warning: Next dependencies in closed beta and available upon invite only. If you would like to be considered for the beta, please contact Support. - Verizon Media @@ -120,7 +121,7 @@ Banner, Interstitial, Rewarded Video - [Home](https://www.verizonmedia.com/adver Banner, Interstitial, Rewarded Video - [Home](https://target.my.com/) - [Privacy Policy](https://legal.my.com/us/mytarget/privacy/) *Works to CIS countries only* - MobFox -Banner, Interstitial, Rewarded Video - [Home](https://www.mobfox.com) - [Privacy Policy](https://www.mobfox.com/privacy-policy/) +Banner, Interstitial, ~~Rewarded Video~~ - [Home](https://www.mobfox.com) - [Privacy Policy](https://www.mobfox.com/privacy-policy/) - Amazon Ads Banner, ~~Interstitial, Rewarded Video~~ - [Home](https://advertising.amazon.com) - [Privacy Policy](https://advertising.amazon.com/legal/privacy-notice) *** @@ -341,43 +342,6 @@ CAS.MobileAds.manager.lastPageAdContent = new LastPageAdContent(...); ``` By default, this page will not be displayed while the ad content is NULL. *** -
iOS Tracking Usage Description - -**Property for iOS only.** -iOS 14 and above requires publishers to obtain permission to track the user's device across applications. -To display the App Tracking Transparency authorization request for accessing the IDFA, update your Info.plist to add the NSUserTrackingUsageDescription key with a custom message describing your usage. - -> You can leave the field blank so that CAS does not define NSUserTrackingUsageDescription. - -Below is an example description text: -- This identifier will be used to deliver personalized ads to you. -- Your data will be used to provide you a better and personalized ad experience. -- We try to show ads for apps and products that will be most interesting to you based on the apps you use. -- We try to show ads for apps and products that will be most interesting to you based on the apps you use, the device you are on, and the country you are in. - -For more information, see [Apple's developer documentation](https://developer.apple.com/documentation/bundleresources/information_property_list/nsusertrackingusagedescription) or [Google Ads documentation](https://developers.google.com/admob/ios/ios14#request). - -> **Important!** CAS does not provide legal advice. Therefore, the information on this page is not a substitute for seeking your own legal counsel to determine the legal requirements of your business and processes, and how to address them. -*** -
iOS Track Location Enabled - -**Property for iOS only.** -The SDK automatically collects location data if the user allowed the app to track the location. -Change the flag at any time using the following method: -```c# -CAS.MobileAds.settings.trackLocationEnabled = enabled; -``` -Disabled by default. -*** -
iOS App Pause On Background - -**Property for iOS only.** -Indicates if the Unity app should be automatically paused when a full screen ad (Interstitial or Rewarded video ad) is displayed. -```c# -CAS.MobileAds.settings.iOSAppPauseOnBackground = pause; -``` -Enabled by default. -***
## Step 3 Privacy Laws @@ -450,45 +414,40 @@ CAS.MobileAds.settings.taggedAudience = Audience.Mixed; ## Step 4 Initialize CAS SDK -Before loading ads, have your app initialize the CAS SDK by calling `CAS.MobileAds.Initialize()` which initializes the SDK and calls back a completion listener once initialization is complete. -Initialize can be called for different identifiers to create different managers (Placement). -This needs to be done only once for each manager, ideally at app launch. +
Initialize code -
Simple initialize +To display ads, you must initialize the mediation manager with a unique identifier. +If you haven't created an CAS account and registered an app yet, now's a great time to do so at [cleveradssolutions.com](https://cleveradssolutions.com). +In a real app, it is important that you use your actual CAS manager ID. +This needs to be done only once for each manager, ideally at app launch. -Also to initialize SDK using settings from resources, created by menu `Assets > CleverAdsSolutions > Settings`, there is the following method: -```c# -CAS.MobileAds.InitializeFromResources( - managerIndex: 0, - initCompleteAction: (success, error) => { - // CAS manager initialization done - }); -``` -*** -
Advanced initialzie + +The settings for initializing the mediation manager are contained in the `CASInitSettings` asset. +This asset is unique to each supported runtime platform and can be customized using the editor `Assets > CleverAdsSolutions > Settings` menu. +Also you can change any properties of the asset using `MobileAds.BuildManager()` to get actual `CASInitSettings` asset. + +> If you're just looking to experiment with the SDK, though, you can use the **Test Ad Mode** above with any manager ID string. Here's an example of how to call `Initialize()` within the `Start()` method of a script attached to a GameObject: ```c# using CAS; -... -public class CleverAdsSolutionsDemoScript : MonoBehaviour + +class CleverAdsSolutionsDemoScript : MonoBehaviour { IMediationManager manager; - public void Start() + void Start() { + // Configure AdsSettings before initialize // Initialize the Clever Ads Solutions SDK manager. - manager = MobileAds.Initialize( - // CAS manager (Placement) identifier. - managerID, - // Optional set active Ad Types: 'AdFlags.Banner | AdFlags.Interstitial' for example. - // Ad types can be enabled manually after initialize by IMediationManager.SetEnableAd - enableAd: AdFlags.Everything, - // Optional Enable demo mode that will always request test ads. Set FALSE for release! - testAdMode: !releaseBuild, - // Optional subscribe to initialization done - initCompleteAction: (success, error) => { - // CAS manager initialization done - }); + CASInitSettings builder = MobileAds.BuildManager(); + // Any changes CASInitSettings properties + builder.WithTestAdMode(isTestBuild); + // Add initialize listener + builder.WithInitListener((success, error) => { + // CAS manager initialization done + }); + // Call Initialize method in any case to get IMediationManager instance + manager = builder.Initialize(); } } ``` @@ -692,49 +651,68 @@ If you do not find the manifest file [Plugins/Android/AndroidManifest.xml](https Or Unity 2019.3+ makes it possible to activate in `Player Settings > Publishing Settings > Build > Custom Main Manifest` checkmark. ***
-
Google Ads App Android ID (Automated) - -**Automated integration during application build.** -About Google Ads App ID [here](https://developers.google.com/admob/android/quick-start#update_your_androidmanifestxml). -*** -
### Include iOS Make sure that Cocoapods is installed. In the Unity editor, select: `Assets > External Dependency Manager > iOS Resolver > Install Cocoapods` -
Supports Unity 2019.3 and newer +
Tracking Usage Description + + iOS 14 and above requires publishers to obtain permission to track the user's device across applications. + To display the App Tracking Transparency authorization request for accessing the IDFA, update your Info.plist to add the NSUserTrackingUsageDescription key with a custom message describing your usage. - If you get the following error while loading your application: - ``` - Error loading [path]/Your.app/Frameworks/UnityFramework.framework/UnityFramework: - dlopen([path]/Your.app/Frameworks/UnityFramework.framework/UnityFramework, 265): - Library not loaded: @rpath/CleverAdsSolutions.framework - Referenced from: [path]/Your.app/Frameworks/UnityFramework.framework/UnityFramework - Reason: image not found - ``` - Then please add `target 'Unity-iPhone'` to the Podfile in root folder of XCode project as follows: - ```cpp - source 'https://github.com/CocoaPods/Specs.git' - source 'https://github.com/cleveradssolutions/CAS-Specs.git' - platform :ios, '11.0' - - target 'UnityFramework' do - pod 'CleverAdsSolutions-SDK', 'version' - end - - target 'Unity-iPhone' do - end - ``` - Save Podfile and call terminal command +You can set description in `Assets > CleverAdsSolution > iOS Settings` menu or leave the field blank so that CAS does not define NSUserTrackingUsageDescription. + + Below is an example description text: + - This identifier will be used to deliver personalized ads to you. + - Your data will be used to provide you a better and personalized ad experience. + - We try to show ads for apps and products that will be most interesting to you based on the apps you use. + - We try to show ads for apps and products that will be most interesting to you based on the apps you use, the device you are on, and the country you are in. + +To present the authorization request, call `CAS.iOS.AppTrackingTransparency.Request()`. We recommend waiting for the completion callback prior to initialize SDK, so that if the user grants the App Tracking Transparency permission, the third party networks can use the IDFA in ad requests. + +```csharp +class CleverAdsSolutionsDemoScript : MonoBehaviour +{ + CAS.IMediationManager manager; + void Start() + { + CAS.iOS.AppTrackingTransparency.OnAuthorizationRequestComplete + += OnAuthorizationRequestComplete; + CAS.iOS.AppTrackingTransparency.Request(); + } + + void OnAuthorizationRequestComplete( + CAS.iOS.AppTrackingTransparency.Status status){ + manager = CAS.MobileAds.BuildManager().Initialize(); + } +} +``` + + For more information, see [Apple's developer documentation](https://developer.apple.com/documentation/bundleresources/information_property_list/nsusertrackingusagedescription) + + > **Important!** CAS does not provide legal advice. Therefore, the information on this page is not a substitute for seeking your own legal counsel to determine the legal requirements of your business and processes, and how to address them. + *** +
Track Location Enabled + + The SDK automatically collects location data if the user allowed the app to track the location. + Change the flag at any time using the following method: + ```c# + CAS.MobileAds.settings.trackLocationEnabled = enabled; ``` - cd [path to XCode project] - pod install --no-repo-update + Disabled by default. + *** +
App Pause On Background + + **Property for iOS only.** + Indicates if the Unity app should be automatically paused when a full screen ad (Interstitial or Rewarded video ad) is displayed. + ```c# + CAS.MobileAds.settings.iOSAppPauseOnBackground = pause; ``` - - > We are working with EDM4U to fix this problem in [issue #405](https://github.com/googlesamples/unity-jar-resolver/issues/405) + Enabled by default. *** -
Configuring permissions (Optional) +
+
Configuring permissions (Optional) In iOS 10, Apple has extended the scope of its privacy controls by restricting access to features like the camera, photo library, etc. In order to unlock rich, immersive experiences in the SDK that take advantage of these services, please add the following entry to your apps plist: ```xml @@ -748,25 +726,121 @@ In iOS 10, Apple has extended the scope of its privacy controls by restricting a > You can also use the settings provided by the Unity `Player Settings > Other Settings > Usage Description`. ***
-
Google Ads App iOS ID (Automated) -**Automated integration during application build.** -About Google Ads App ID [here](https://developers.google.com/admob/ios/quick-start). + +## Mediation extras +The CAS mediation adapters provides the `CAS.MediationExtras` constant keys to customize parameters to be sent to networks SDK. + +The following sample code demonstrates how to pass these parameters to the networks adapter: +```csharp +manager = CAS.MobileAds.BuildManager() + .WithMediationExtras(MediationExtras.vunglePublishIDFV, "1") + .WithMediationExtras(MediationExtras.vungleAndroidIdOptedOut, "0") + .Initialize(); +``` + +Although the GDPR and CCPA settings are used by all media adapters, you have the option to override these values for a specific network. +
Google Ads + +```csharp +manager = CAS.MobileAds.BuildManager() + // User GDPR consent "1" is accepted and "0" is rejected + .WithMediationExtras(MediationExtras.AdMobGDPRConsent, "0") + // User CCPA do not sell data "1" and "0" is use data in ad + .WithMediationExtras(MediationExtras.AdMobCCPAOptedOut, "1") + .Initialize(); +``` +See Admob [GDPR](https://developers.google.com/admob/android/eu-consent) and [CCPA](https://developers.google.com/admob/android/ccpa#rdp_signal) implementation details for more information about what values may be provided in these methods. *** -
-
Configuring SK Ad Networks (Automated) +
AppLovin -**Automated integration during application build.** -About SKAdNetwork [here](https://developer.apple.com/documentation/storekit/skadnetwork). +```csharp +manager = CAS.MobileAds.BuildManager() + // User GDPR consent "1" is accepted and "0" is rejected + .WithMediationExtras(MediationExtras.AppLovinGDPRConsent, "0") + // User CCPA do not sell data "1" and "0" is use data in ad + .WithMediationExtras(MediationExtras.AppLovinCCPAOptedOut, "1") + // Initialize MAX + .WithMediationExtras(MediationExtras.AppLovinUseMAX, "1") + .Initialize(); +``` *** -
-
Configuring URL Schemes (Automated) +
AdColony + +```csharp +manager = CAS.MobileAds.BuildManager() + // User GDPR consent "1" is accepted and "0" is rejected + .WithMediationExtras(MediationExtras.AdColonyGDPRConsent, "0") + // User CCPA do not sell data "1" and "0" is use data in ad + .WithMediationExtras(MediationExtras.AdColonyCCPAOptedOut, "1") + .Initialize(); +``` +See [AdColony’s Privacy Laws implementation details](https://github.com/AdColony/AdColony-Android-SDK/wiki/Privacy-Laws) for more information about what values may be provided in these methods. +*** +
Vungle + +```csharp +manager = CAS.MobileAds.BuildManager() + // User GDPR consent "1" is accepted and "0" is rejected + .WithMediationExtras(MediationExtras.VungleGDPRConsent, "0") + // User CCPA do not sell data "1" and "0" is use data in ad + .WithMediationExtras(MediationExtras.VungleCCPAOptedOut, "1") + // Restrict Use of Android Device ID + .WithMediationExtras(MediationExtras.vungleAndroidIdOptedOut, "1") + // Restrict Use of IDFV + .WithMediationExtras(MediationExtras.vunglePublishIDFV, "0") + .Initialize(); +``` +See [Vungle's Advanced Settings implementation](https://support.vungle.com/hc/en-us/articles/360047780372) for more information. +*** +
IronSource + +```csharp +manager = CAS.MobileAds.BuildManager() + // User GDPR consent "1" is accepted and "0" is rejected + .WithMediationExtras(MediationExtras.ironSourceGDPRConsent, "0") + // User CCPA do not sell data "1" and "0" is use data in ad + .WithMediationExtras(MediationExtras.ironSourceCCPAOptedOut, "1") + .Initialize(); +``` +See [ironSource's managing consent](https://developers.ironsrc.com/ironsource-mobile/android/advanced-settings/) documentation for more details. +*** +
Unity Ads -**Automated integration during application build.** -About URL Schemes [here](https://github.com/cleveradssolutions/CAS-iOS#step-6-configuring-url-schemes). +```csharp +manager = CAS.MobileAds.BuildManager() + // User GDPR consent "1" is accepted and "0" is rejected + .WithMediationExtras(MediationExtras.unityAdsGDPRConsent, "0") + // User CCPA do not sell data "1" and "0" is use data in ad + .WithMediationExtras(MediationExtras.unityAdsCCPAOptedOut, "1") + .Initialize(); +``` +See [Unity Ads data privacy and consent implementation details](https://unityads.unity3d.com/help/legal/data-privacy-and-consent) for more information about what values may be provided in these methods. +*** +
InMobi + +```csharp +manager = CAS.MobileAds.BuildManager() + // User GDPR consent "1" is accepted and "0" is rejected + .WithMediationExtras(MediationExtras.InMobiGDPRConsent, "0") + .WithMediationExtras(MediationExtras.InMobiGDPRIAB, iab_string) + .Initialize(); +``` +See [InMobi's GDPR implementation details](https://support.inmobi.com/monetize/android-guidelines) for more information about the possible keys and values that InMobi accepts in this consent object. +*** +
StartApp + +```csharp +manager = CAS.MobileAds.BuildManager() + // User GDPR consent "1" is accepted and "0" is rejected + .WithMediationExtras(MediationExtras.startAppGDPRConsent, "0") + .Initialize(); +``` ***
+>Unique properties for each network will be added in the future. + ## GitHub issue tracker To file bugs, make feature requests, or suggest improvements for the Unity Plugin SDK, please use [GitHub's issue tracker](https://github.com/cleveradssolutions/CAS-Unity/issues). diff --git a/Runtime/Android/CASJavaProxy.cs b/Runtime/Android/CASJavaProxy.cs index bfc5078..a6ddca1 100644 --- a/Runtime/Android/CASJavaProxy.cs +++ b/Runtime/Android/CASJavaProxy.cs @@ -20,9 +20,9 @@ internal static class CASJavaProxy internal static AndroidJavaObject GetJavaListObject( List csTypeList ) { AndroidJavaObject javaTypeArrayList = new AndroidJavaObject( "java.util.ArrayList" ); - foreach (string itemList in csTypeList) + for (int i = 0; i < csTypeList.Count; i++) { - javaTypeArrayList.Call( "add", itemList ); + javaTypeArrayList.Call( "add", csTypeList[i] ); } return javaTypeArrayList; } diff --git a/Runtime/Android/CASMediationManager.cs b/Runtime/Android/CASMediationManager.cs index 38319d9..f9b2a09 100644 --- a/Runtime/Android/CASMediationManager.cs +++ b/Runtime/Android/CASMediationManager.cs @@ -101,10 +101,10 @@ public event Action OnRewardedAdClosed } #endregion - public CASMediationManager( string managerID, bool isDemoAdMode ) + public CASMediationManager( CASInitSettings initData ) { - this.managerID = managerID; - this.isTestAdMode = isDemoAdMode; + managerID = initData.targetId; + isTestAdMode = initData.testAdMode; } ~CASMediationManager() @@ -119,24 +119,40 @@ public CASMediationManager( string managerID, bool isDemoAdMode ) } } - public void CreateManager( AdFlags enableAd, InitCompleteAction initCompleteAction ) + public void CreateManager( CASInitSettings initData ) { _bannerProxy = new AdCallbackProxy(); _interstitialProxy = new AdCallbackProxy(); _rewardedProxy = new AdCallbackProxy(); _adLoadProxy = new AdLoadCallbackProxy(); - if (initCompleteAction != null) - initializationListener = new InitializationListenerProxy( this, initCompleteAction ); + if (initData.initListener != null) + initializationListener = new InitializationListenerProxy( this, initData.initListener ); AndroidJavaObject activity = CASJavaProxy.GetUnityActivity(); - _managerBridge = new AndroidJavaObject( CASJavaProxy.NativeBridgeClassName, - activity, - managerID, - ( int )enableAd, - isTestAdMode, - initializationListener ); + if (initData.extrasKeys != null && initData.extrasValues != null + && initData.extrasKeys.Count != 0 && initData.extrasValues.Count != 0) + { + _managerBridge = new AndroidJavaObject( CASJavaProxy.NativeBridgeClassName, + activity, + managerID, + ( int )initData.allowedAdFlags, + isTestAdMode, + initializationListener, + CASJavaProxy.GetJavaListObject( initData.extrasKeys ), + CASJavaProxy.GetJavaListObject( initData.extrasValues ) + ); + } + else + { + _managerBridge = new AndroidJavaObject( CASJavaProxy.NativeBridgeClassName, + activity, + managerID, + ( int )initData.allowedAdFlags, + isTestAdMode, + initializationListener ); + } _managerBridge.Call( "setListeners", _bannerProxy, diff --git a/Runtime/Android/CASSettings.cs b/Runtime/Android/CASSettings.cs index 9c08222..08863fc 100644 --- a/Runtime/Android/CASSettings.cs +++ b/Runtime/Android/CASSettings.cs @@ -50,6 +50,16 @@ public void ValidateIntegration() // settingsBridge.CallStatic( "validateIntegration" ); } + public string GetActiveMediationPattern() + { + return settingsBridge.CallStatic( "getActiveMediationPattern" ); + } + + public bool IsActiveMediationNetwork( AdNetwork net ) + { + return settingsBridge.CallStatic( "isActiveMediationNetwork", (int)net ); + } + public bool analyticsCollectionEnabled { get { return _analyticsCollectionEnabled; } diff --git a/Runtime/CASFactory.cs b/Runtime/CASFactory.cs index aca0550..b6460c6 100644 --- a/Runtime/CASFactory.cs +++ b/Runtime/CASFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using UnityEngine; @@ -8,8 +9,20 @@ internal static class CASFactory { internal static volatile bool isExecuteEventsOnUnityThread = false; + internal static IMediationManager manager; internal static IAdsSettings _settings; + internal static CASInitSettings LoadInitSettingsFromResources() + { +#if UNITY_ANDROID + return Resources.Load( "CASSettingsAndroid" ); +#elif UNITY_IOS + return Resources.Load( "CASSettingsiOS" ); +#else + return null; +#endif + } + internal static IAdsSettings CreateSettigns( CASInitSettings initSettings ) { IAdsSettings settings = null; @@ -63,77 +76,33 @@ internal static string GetSDKVersion() return MobileAds.wrapperVersion; } - - internal static IMediationManager Initialize( - string managerID, - AdFlags enableAd = AdFlags.Everything, - bool testAdMode = false, - InitCompleteAction initCompleteAction = null ) + internal static IMediationManager CreateManager( CASInitSettings initSettings ) { - if (string.IsNullOrEmpty( managerID )) - throw new ArgumentNullException( "managerID", "Manager ID is empty" ); - if (MobileAds.manager != null && MobileAds.manager.managerID == managerID) + if (manager != null && manager.managerID == initSettings.targetId) { - if (initCompleteAction != null) - initCompleteAction( true, null ); - return MobileAds.manager; + if (initSettings.initListener != null) + initSettings.initListener( true, null ); + manager.bannerSize = initSettings.bannerSize; + return manager; } if (_settings == null) - _settings = CreateSettigns( LoadInitSettingsFromResources() ); - EventExecutor.Initialize(); - return CreateManager( managerID, enableAd, testAdMode, initCompleteAction ); - } - - internal static IMediationManager InitializeFromResources( - int managerIndex, AdFlags enableAd, InitCompleteAction initCompleteAction = null ) - { - var initSettings = LoadInitSettingsFromResources(); + _settings = CreateSettigns( initSettings ); - if (!initSettings) - throw new FileNotFoundException( "No settings found in resources. " + - "Please use Assets/CleverAdsSolutions/Settings menu for create settings asset." ); - string managerID; - if (Application.isEditor || initSettings.testAdMode) - { - managerID = "demo"; - } - else - { - if (initSettings.managerIds.Length - 1 < managerIndex || string.IsNullOrEmpty( initSettings.managerIds[managerIndex] )) - throw new ArgumentNullException( "managerIds", "Manager ID is empty. " + - "Please use Assets/CleverAdsSolutions/Settings menu and set manager ID." ); - managerID = initSettings.managerIds[managerIndex]; - } - if (MobileAds.manager != null && MobileAds.manager.managerID == managerID) - { - if (initCompleteAction != null) - initCompleteAction( true, null ); - return MobileAds.manager; - } EventExecutor.Initialize(); - var manager = CreateManager( managerID, initSettings.allowedAdFlags & enableAd, initSettings.testAdMode, initCompleteAction ); - manager.bannerSize = initSettings.bannerSize; - return manager; - } - - internal static IMediationManager CreateManager( - string managerID, AdFlags enableAd, bool demoAdMode, InitCompleteAction initCompleteAction ) - { - IMediationManager manager = null; #if UNITY_EDITOR || TARGET_OS_SIMULATOR - manager = CAS.Unity.CASMediationManager.CreateManager( enableAd, initCompleteAction ); + manager = CAS.Unity.CASMediationManager.CreateManager( initSettings ); #elif UNITY_ANDROID if (Application.platform == RuntimePlatform.Android) { - var android = new CAS.Android.CASMediationManager( managerID, demoAdMode ); - android.CreateManager( enableAd, initCompleteAction ); + var android = new CAS.Android.CASMediationManager( initSettings ); + android.CreateManager( initSettings ); manager = android; } #elif UNITY_IOS if (Application.platform == RuntimePlatform.IPhonePlayer) { - var ios = new CAS.iOS.CASMediationManager( managerID, demoAdMode ); - ios.CreateManager( enableAd, initCompleteAction ); + var ios = new CAS.iOS.CASMediationManager( initSettings ); + ios.CreateManager( initSettings ); manager = ios; } #endif @@ -144,10 +113,12 @@ internal static IMediationManager CreateManager( internal static void ValidateIntegration() { -#if UNITY_ANDROID +#if UNITY_EDITOR + // TODO: Implementation editor +#elif UNITY_ANDROID if (Application.platform == RuntimePlatform.Android) { - var androidSettings = MobileAds.settings as CAS.Android.CASSettings; + var androidSettings = GetAdsSettings() as CAS.Android.CASSettings; androidSettings.ValidateIntegration(); } #elif UNITY_IOS @@ -158,25 +129,55 @@ internal static void ValidateIntegration() #endif } - internal static CASInitSettings LoadInitSettingsFromResources() + #region Mediation network states + internal static string GetActiveMediationPattern() + { +#if UNITY_EDITOR + // TODO: Implementation editor +#elif UNITY_ANDROID + if (Application.platform == RuntimePlatform.Android) + { + var androidSettings = GetAdsSettings() as CAS.Android.CASSettings; + return androidSettings.GetActiveMediationPattern(); + } +#elif UNITY_IOS + if (Application.platform == RuntimePlatform.IPhonePlayer) + return CAS.iOS.CASExterns.CASUGetActiveMediationPattern(); +#endif + return ""; + } + + internal static AdNetwork[] GetActiveNetworks() + { + var pattern = GetActiveMediationPattern(); + var result = new List(); + for (int i = 0; i < pattern.Length; i++) + { + if (pattern[i] == '1') + result.Add( ( AdNetwork )i ); + } + return result.ToArray(); + } + + internal static bool IsActiveNetwork( AdNetwork network ) { - string assetName; - switch (Application.platform) +#if UNITY_EDITOR + // TODO: Implementation editor +#elif UNITY_ANDROID + if (Application.platform == RuntimePlatform.Android) { - case RuntimePlatform.WindowsEditor: - case RuntimePlatform.Android: - assetName = "CASSettingsAndroid"; - break; - case RuntimePlatform.OSXEditor: - case RuntimePlatform.IPhonePlayer: - assetName = "CASSettingsiOS"; - break; - default: - return null; + var androidSettings = GetAdsSettings() as CAS.Android.CASSettings; + return androidSettings.IsActiveMediationNetwork( network ); } - return Resources.Load( assetName ); +#elif UNITY_IOS + if (Application.platform == RuntimePlatform.IPhonePlayer) + return CAS.iOS.CASExterns.CASUIsActiveMediationNetwork( ( int )network ); +#endif + return false; } + #endregion + #region Execute events wrapper internal static void ExecuteEvent( Action action ) { if (action == null) @@ -271,5 +272,6 @@ internal static void ExecuteEvent( InitCompleteAction action, bool success, stri Debug.LogException( e ); } } + #endregion } } \ No newline at end of file diff --git a/Runtime/CASInitSettings.cs b/Runtime/CASInitSettings.cs index bc0e4fb..9596adf 100644 --- a/Runtime/CASInitSettings.cs +++ b/Runtime/CASInitSettings.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using UnityEngine; namespace CAS @@ -17,5 +18,125 @@ public class CASInitSettings : ScriptableObject public bool debugMode; public string trackingUsageDescription; public bool trackLocationEnabled; + + internal List extrasKeys; + internal List extrasValues; + internal string targetId; + internal InitCompleteAction initListener; + + /// + /// An manager ID is a unique ID number assigned to each of your ad placements when they're created in CAS. + /// The manager ID is added to your app's code and used to identify ad requests. + /// If you haven't created an CAS account and registered an app yet, now's a great time to do so at . + /// In a real app, it is important that you use your actual CAS manager ID. + /// + /// Manager ID is empty + public CASInitSettings WithManagerId( string managerId ) + { + if (string.IsNullOrEmpty( managerId )) + throw new ArgumentNullException( "managerID", "Manager ID is empty" ); + targetId = managerId; + return this; + } + + /// + /// An manager ID is a unique ID number assigned to each of your ad placements when they're created in CAS. + /// The manager ID is added to your app's code and used to identify ad requests. + /// If you haven't created an CAS account and registered an app yet, now's a great time to do so at . + /// In a real app, it is important that you use your actual CAS manager ID. + /// + /// Use Manager Id at Index from list `Assets/CleverAdsSolutions/Settings` menu + /// + /// Manager ID is empty + public CASInitSettings WithManagerIdAtIndex( int index ) + { + if (index < 0 || managerIds == null || managerIds.Length - 1 < index + || string.IsNullOrEmpty( managerIds[index] )) + throw new ArgumentNullException( "index", "Manager ID is empty. " + + "Please use Assets/CleverAdsSolutions/Settings menu and set manager ID." ); + targetId = managerIds[index]; + return this; + } + + /// + /// Initialization complete result callback + /// + public CASInitSettings WithInitListener( InitCompleteAction listener ) + { + initListener = listener; + return this; + } + + /// + /// An demoAdMode is optional to enable Test ad mode that will always request test ads. + /// If you're just looking to experiment with the SDK in a Hello World app, though, you can use the with any manager ID string. + /// Please remember to set False demo ad mode after tests done. + /// + public CASInitSettings WithTestAdMode( bool test ) + { + testAdMode = test; + return this; + } + + /// + /// An Enabled Ad types is option to increase application performance by initializing only those ad types that will be used. + /// Changes in current session only. + /// Ad types can be enabled manually after initialize by + /// + /// For example: .withEnabledAdTypes(AdFlags.Banner | AdFlags.Interstitial) + /// + public CASInitSettings WithEnabledAdTypes( AdFlags adTypes ) + { + allowedAdFlags = adTypes; + return this; + } + + /// + /// Additional mediation settings. + /// Use constant key from + /// + public CASInitSettings WithMediationExtras( string key, string value ) + { + if (extrasKeys == null || extrasValues == null) + { + extrasKeys = new List(); + extrasValues = new List(); + } + extrasKeys.Add( key ); + extrasValues.Add( value ); + return this; + } + + /// + /// Clear additional mediation settings. + /// + public CASInitSettings ClearMediationExtras() + { + if (extrasKeys != null) + extrasKeys.Clear(); + if (extrasValues != null) + extrasValues.Clear(); + return this; + } + + /// + /// Initialize new and save to field. + /// Can be called for different identifiers to create different managers. + /// + /// Not supported platform. Allowed Android, iOS and Editor only + /// Manager ID is empty + public IMediationManager Initialize() + { + if (string.IsNullOrEmpty( targetId )) + { + if (Application.isEditor || testAdMode) + targetId = "demo"; + else + WithManagerIdAtIndex( 0 ); + } + var manager = CASFactory.CreateManager( this ); + manager.bannerSize = bannerSize; + return manager; + } } } \ No newline at end of file diff --git a/Runtime/Common/AdNetwork.cs b/Runtime/Common/AdNetwork.cs new file mode 100644 index 0000000..f9629d6 --- /dev/null +++ b/Runtime/Common/AdNetwork.cs @@ -0,0 +1,25 @@ +namespace CAS +{ + public enum AdNetwork + { + AdMob, + Vungle, + Kidoz, + Chartboost, + UnityAds, + AppLovin, + SuperAwesome, + StartApp, + AdColony, + FacebookAN, + InMobi, + MobFox, + MyTarget, + CrossPromo, + IronSource, + YandexAds, + OwnVAST, + AmazonAds, + Verizon + } +} \ No newline at end of file diff --git a/Runtime/Common/AdNetwork.cs.meta b/Runtime/Common/AdNetwork.cs.meta new file mode 100644 index 0000000..65d730c --- /dev/null +++ b/Runtime/Common/AdNetwork.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 71d101e5c43754ed08287095f55a55fa +labels: +- CleverAdsSolutions +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Common/MediationExtras.cs b/Runtime/Common/MediationExtras.cs new file mode 100644 index 0000000..f64cdcf --- /dev/null +++ b/Runtime/Common/MediationExtras.cs @@ -0,0 +1,52 @@ +namespace CAS +{ + public class MediationExtras + { + public const string AdMobGDPRConsent = "AM_gdpr"; + public const string AdMobCCPAOptedOut = "AM_ccpa"; + + public const string AppLovinGDPRConsent = "AL_gdpr"; + public const string AppLovinCCPAOptedOut = "AL_ccpa"; + /// + /// Value "1" to enable MAX + /// + public const string AppLovinUseMAX = "AL_max"; + + public const string InMobiGDPRConsent = "IM_gdpr"; + /// + /// Provide user consent in IAB string format + /// + public const string InMobiGDPRIAB = "IM_iab"; + + public const string AdColonyGDPRConsent = "AC_gdpr"; + public const string AdColonyCCPAOptedOut = "AC_ccpa"; + + public const string VungleGDPRConsent = "V_gdpr"; + public const string VungleCCPAOptedOut = "V_ccpa"; + /// + /// Enables/disables automatic fallback collection of Android ID in case ifa is not available. + /// Android only. + /// + /// Default value is "0". + /// if "1" disables the collection. + // endregion + public const string vungleAndroidIdOptedOut = "V_aIDOpt"; + /// + /// Sets the publish IDFV flag. + /// iOS only. + /// + /// This value is persistent and so may be set once. + /// Default value is "1". + /// if "0" no publish the IDFV value. + /// + public const string vunglePublishIDFV = "V_aIDOpt"; + + public const string ironSourceGDPRConsent = "IS_gdpr"; + public const string ironSourceCCPAOptedOut = "IS_ccpa"; + + public const string unityAdsGDPRConsent = "U_gdpr"; + public const string unityAdsCCPAOptedOut = "U_ccpa"; + + public const string startAppGDPRConsent = "StA_gdpr"; + } +} diff --git a/Runtime/Common/MediationExtras.cs.meta b/Runtime/Common/MediationExtras.cs.meta new file mode 100644 index 0000000..4145361 --- /dev/null +++ b/Runtime/Common/MediationExtras.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e81c603cf282640eaab8c7c4fee1d62e +labels: +- CleverAdsSolutions +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Common/MobileAds.cs b/Runtime/Common/MobileAds.cs index e4493e9..58a07d3 100644 --- a/Runtime/Common/MobileAds.cs +++ b/Runtime/Common/MobileAds.cs @@ -11,7 +11,7 @@ public static class MobileAds /// /// CAS Unity wrapper version /// - public const string wrapperVersion = "1.8.3"; + public const string wrapperVersion = "1.9.1"; /// /// Get singleton instance for configure all mediation managers. @@ -25,7 +25,10 @@ public static IAdsSettings settings /// Get last initialized /// May be NULL before the first initialization in the session. /// - public static IMediationManager manager { get; private set; } + public static IMediationManager manager + { + get { return CASFactory.manager; } + } /// /// You can now easily tailor the way you serve your ads to fit a specific audience! @@ -46,6 +49,18 @@ public static string GetSDKVersion() return CASFactory.GetSDKVersion(); } + /// + /// Create builder. + /// Don't forget to call the method to create manager instance. + /// + public static CASInitSettings BuildManager() + { + var builder = CASFactory.LoadInitSettingsFromResources(); + if (builder == null) + return ScriptableObject.CreateInstance(); + return UnityEngine.Object.Instantiate( builder ); + } + /// /// Initialize new and save to field. /// Can be called for different identifiers to create different managers. @@ -64,7 +79,12 @@ public static IMediationManager Initialize( bool testAdMode = false, InitCompleteAction initCompleteAction = null ) { - return manager = CASFactory.Initialize( managerID, enableAd, testAdMode, initCompleteAction ); + return BuildManager() + .WithManagerId( managerID ) + .WithEnabledAdTypes( enableAd ) + .WithTestAdMode( testAdMode ) + .WithInitListener( initCompleteAction ) + .Initialize(); } /// @@ -82,12 +102,18 @@ public static IMediationManager Initialize( /// Manager ID is empty /// Not supported runtime platform /// No settings found in resources + [Obsolete( "Use the new extended parameters of BuildManager() instead" )] public static IMediationManager InitializeFromResources( int managerIndex = 0, AdFlags enableAd = AdFlags.Everything, InitCompleteAction initCompleteAction = null ) { - return manager = CASFactory.InitializeFromResources( managerIndex, enableAd, initCompleteAction ); + var builder = BuildManager() + .WithInitListener( initCompleteAction ); + builder.WithEnabledAdTypes( enableAd & builder.allowedAdFlags ); + if (managerIndex > 0) + builder.WithManagerIdAtIndex( managerIndex ); + return builder.Initialize(); } /// @@ -96,7 +122,7 @@ public static IMediationManager InitializeFromResources( /// After you have finished your integration, call the following static method /// and confirm that all networks you have implemented are marked as VERIFIED. /// - /// Find log information by tag: CASIntegrationHelper + /// Find log information by tag: CASIntegrationHelper /// /// Once you’ve successfully verified your integration, /// please remember to remove the integration helper from your code. @@ -105,5 +131,27 @@ public static void ValidateIntegration() { CASFactory.ValidateIntegration(); } + + /// + /// Mediation pattern string with format '1' - active and '0' - not active. + /// Char index of string pattern equals enum index of + /// + public static string GetActiveMediationPattern() + { + return CASFactory.GetActiveMediationPattern(); + } + + /// + /// Get array of active mediation networks in build. + /// + public static AdNetwork[] GetActiveNetworks() + { + return CASFactory.GetActiveNetworks(); + } + + public static bool IsActiveNetwork( AdNetwork network ) + { + return CASFactory.IsActiveNetwork( network ); + } } } diff --git a/Runtime/Unity/CASMediationManager.cs b/Runtime/Unity/CASMediationManager.cs index d7125b6..e5e3ffe 100644 --- a/Runtime/Unity/CASMediationManager.cs +++ b/Runtime/Unity/CASMediationManager.cs @@ -81,13 +81,13 @@ public AdPosition bannerPosition public event Action OnRewardedAdClosed; #endregion - public static IMediationManager CreateManager( AdFlags enableAd, InitCompleteAction initCompleteAction ) + public static IMediationManager CreateManager( CASInitSettings initSettings ) { var obj = new GameObject( "CASMediationManager" ); DontDestroyOnLoad( obj ); var manager = obj.AddComponent(); - manager.enabledTypes = enableAd; - manager._initCompleteAction = initCompleteAction; + manager.enabledTypes = initSettings.allowedAdFlags; + manager._initCompleteAction = initSettings.initListener; manager.bannerSize = AdSize.Banner; manager._settings = CAS.MobileAds.settings as CASSettings; return manager; diff --git a/Runtime/iOS/AppTrackingTransparency.cs b/Runtime/iOS/AppTrackingTransparency.cs new file mode 100644 index 0000000..ae66c85 --- /dev/null +++ b/Runtime/iOS/AppTrackingTransparency.cs @@ -0,0 +1,76 @@ +using System; + +namespace CAS.iOS +{ + /// + /// Wraps for the native iOS 14.0 ATTrackingManager. + /// A class that provides a tracking authorization request and the tracking authorization status of the app. + /// + /// + public static class AppTrackingTransparency + { + public enum Status + { + NotDetermined, + Restricted, + Denied, + Authorized + } + + /// + /// Returns information about your application’s tracking authorization status. + /// Users are able to grant or deny developers tracking privileges on a per-app basis. + /// Application developers must call for the ability to track users. + /// + /// The current authorization status. If the user has not yet been prompted to approve access, the return value will either be + /// , or if this value is managed. + /// Once the user has been prompted, the return value will be either or . + /// + public static event Action OnAuthorizationRequestComplete; + + /// + /// Request user tracking authorization with a completion handler returning the user's authorization status. + /// Users are able to grant or deny developers tracking privileges on a per-app basis. + /// This method allows developers to determine if access has been granted. On first use, this method will prompt the user to grant or deny access. + /// + /// Please set NSUserTrackingUsageDescription in 'Assets > CleverAdsSolutions > iOS Settings' menu to correct tracking authorization request. + /// + /// The completion handler will be called with the result of the user's decision for granting or denying permission to use application tracking. + /// The completion handler will be called immediately if access to request authorization is restricted. + /// The completion handler will be called immediately if runtime platform is not iOS 14 or newer. + /// + /// Please subscribe callback OnAuthorizationRequestComplete before call Request() + /// Please set NSUserTrackingUsageDescription in 'Assets > CleverAdsSolutions > iOS Settings' menu to correct tracking authorization request. + public static void Request() + { + if (OnAuthorizationRequestComplete == null) + throw new ArgumentNullException( "Please subscribe callback OnAuthorizationRequestComplete before call Request()." ); +#if UNITY_IOS +#if UNITY_EDITOR + var settings = CASFactory.LoadInitSettingsFromResources(); + if (settings == null || string.IsNullOrEmpty( settings.trackingUsageDescription )) + throw new ArgumentNullException( "Please set NSUserTrackingUsageDescription in 'Assets > CleverAdsSolutions > iOS Settings' menu to correct tracking authorization request." ); +#endif + CASExterns.CASURequestTracking( AuthorizationRequestComplete ); +#else + OnAuthorizationRequestComplete( Status.Authorized ); +#endif + } + +#if UNITY_IOS || CASDeveloper + [AOT.MonoPInvokeCallback( typeof( CASExterns.CASUTrackingStatusCallback ) )] + private static void AuthorizationRequestComplete( int status ) + { + try + { + if (OnAuthorizationRequestComplete != null) + OnAuthorizationRequestComplete( ( Status )status ); + } + catch (Exception e) + { + UnityEngine.Debug.LogException( e ); + } + } +#endif + } +} diff --git a/Runtime/iOS/AppTrackingTransparency.cs.meta b/Runtime/iOS/AppTrackingTransparency.cs.meta new file mode 100644 index 0000000..0037d7c --- /dev/null +++ b/Runtime/iOS/AppTrackingTransparency.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 427d13f73789c428f9411e0c7c72fc6b +labels: +- CleverAdsSolutions +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/iOS/CASExterns.cs b/Runtime/iOS/CASExterns.cs index cdbcb5e..19aaac7 100644 --- a/Runtime/iOS/CASExterns.cs +++ b/Runtime/iOS/CASExterns.cs @@ -64,6 +64,15 @@ internal class CASExterns [DllImport( "__Internal" )] internal static extern string CASUValidateIntegration(); + + [DllImport( "__Internal" )] + internal static extern string CASUGetActiveMediationPattern(); + + [DllImport( "__Internal" )] + internal static extern bool CASUIsActiveMediationNetwork( int net ); + + [DllImport( "__Internal" )] + internal static extern void CASURequestTracking( CASUTrackingStatusCallback callback ); #endregion #region CAS Callback types @@ -77,6 +86,8 @@ internal class CASExterns internal delegate void CASUInitializationCompleteCallback( IntPtr client, bool success, string error ); internal delegate void CASUDidAdLoadedCallback( IntPtr client, int adType ); internal delegate void CASUDidAdFailedToLoadCallback( IntPtr client, int adType, string error ); + + internal delegate void CASUTrackingStatusCallback( int status ); #endregion #region CAS Manager @@ -89,6 +100,18 @@ internal static extern IntPtr CASUCreateManager( bool demoAd ); + [DllImport( "__Internal" )] + internal static extern IntPtr CASUCreateManagerWithExtras( + IntPtr client, // C# manager client ptr + CASUInitializationCompleteCallback onInit, + string managerID, + int enableAd, + bool demoAd, + string[] extraKeys, + string[] extraValues, + int extrasCount + ); + [DllImport( "__Internal" )] internal static extern void CASUFreeManager( IntPtr manager ); diff --git a/Runtime/iOS/CASMediationManager.cs b/Runtime/iOS/CASMediationManager.cs index a62735d..b3b56af 100644 --- a/Runtime/iOS/CASMediationManager.cs +++ b/Runtime/iOS/CASMediationManager.cs @@ -1,6 +1,4 @@ #if UNITY_IOS || CASDeveloper -// Vungle Network crashes if ad orientation is not allowed -//#define CAS_EXPIREMENTAL_ORIENTATION using System; using System.Runtime.InteropServices; using UnityEngine; @@ -15,9 +13,6 @@ internal class CASMediationManager : IMediationManager private AdSize _bannerSize = AdSize.Banner; private AdPosition _bannerPosition = AdPosition.BottomCenter; private LastPageAdContent _lastPageAdContent = null; -#if CAS_EXPIREMENTAL_ORIENTATION - private bool[] autorotateOrientation = new bool[4]; -#endif public string managerID { get; } public bool isTestAdMode { get; } @@ -40,10 +35,10 @@ internal class CASMediationManager : IMediationManager public event Action OnRewardedAdClosed; #endregion - public CASMediationManager( string managerID, bool isDemoAdMode ) + public CASMediationManager( CASInitSettings initData ) { - this.managerID = managerID; - this.isTestAdMode = isDemoAdMode; + managerID = initData.targetId; + isTestAdMode = initData.testAdMode; } ~CASMediationManager() @@ -58,20 +53,39 @@ public CASMediationManager( string managerID, bool isDemoAdMode ) } } - public void CreateManager( AdFlags enableAd, InitCompleteAction initCompleteAction ) + public void CreateManager( CASInitSettings initData ) { - _initCompleteAction = initCompleteAction; + _initCompleteAction = initData.initListener; CASExterns.CASUSetPluginPlatformWithName( "Unity", Application.unityVersion ); _managerClientPtr = ( IntPtr )GCHandle.Alloc( this ); - _managerPtr = CASExterns.CASUCreateManager( - _managerClientPtr, - InitializationCompleteCallback, - managerID, - ( int )enableAd, - isTestAdMode - ); + + if (initData.extrasKeys != null && initData.extrasValues != null + && initData.extrasKeys.Count != 0 && initData.extrasValues.Count != 0) + { + var extrasCount = Math.Min( initData.extrasKeys.Count, initData.extrasValues.Count ); + _managerPtr = CASExterns.CASUCreateManagerWithExtras( + _managerClientPtr, + InitializationCompleteCallback, + managerID, + ( int )initData.allowedAdFlags, + isTestAdMode, + initData.extrasKeys.ToArray(), + initData.extrasValues.ToArray(), + extrasCount + ); + } + else + { + _managerPtr = CASExterns.CASUCreateManager( + _managerClientPtr, + InitializationCompleteCallback, + managerID, + ( int )initData.allowedAdFlags, + isTestAdMode + ); + } CASExterns.CASUSetLoadAdDelegate( _managerPtr, DidAdLoadedCallback, @@ -169,10 +183,6 @@ public void SetEnableAd( AdType adType, bool enabled ) public void ShowAd( AdType adType ) { -#if CAS_EXPIREMENTAL_ORIENTATION - if (adType == AdType.Interstitial || adType == AdType.Rewarded) - PrepareScreenOrientation(); -#endif CASExterns.CASUShowAdWithType( _managerPtr, ( int )adType ); } @@ -186,29 +196,6 @@ public float GetBannerWidthInPixels() return CASExterns.CASUGetBannerWidthInPixels( _managerPtr ); } -#if CAS_EXPIREMENTAL_ORIENTATION - private void PrepareScreenOrientation() - { - autorotateOrientation[0] = Screen.autorotateToPortrait; - autorotateOrientation[1] = Screen.autorotateToPortraitUpsideDown; - autorotateOrientation[2] = Screen.autorotateToLandscapeLeft; - autorotateOrientation[3] = Screen.autorotateToLandscapeRight; - - Screen.autorotateToPortrait = true; - Screen.autorotateToPortraitUpsideDown = true; - Screen.autorotateToLandscapeLeft = true; - Screen.autorotateToLandscapeRight = true; - } - - private void RestoreScreenOrientation() - { - Screen.autorotateToPortrait = autorotateOrientation[0]; - Screen.autorotateToPortraitUpsideDown = autorotateOrientation[1]; - Screen.autorotateToLandscapeLeft = autorotateOrientation[2]; - Screen.autorotateToLandscapeRight = autorotateOrientation[3]; - } -#endif - #region Callback methods private static CASMediationManager IntPtrToManagerClient( IntPtr managerClient ) { diff --git a/Templates/CASAndroidMediation.list b/Templates/CASAndroidMediation.list index a1aec7b..de176d0 100644 --- a/Templates/CASAndroidMediation.list +++ b/Templates/CASAndroidMediation.list @@ -1 +1 @@ -{"simple":[{"name":"MixedAudience","version":"1.8.3","require":"","url":"","filter":-1,"dependencies":["com.cleversolutions.ads:cas-sdk-teen:1.8.3","tv.superawesome.sdk.publisher:superawesome:7.2.16+"],"contains":["Base","Additional","GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","Chartboost","StartApp","Kidoz","FacebookAN","YandexAds","SuperAwesome"],"source":[],"beta":false},{"name":"FamiliesAds","version":"1.8.3","require":"","url":"","filter":2,"dependencies":["com.cleversolutions.ads:cas-sdk-general:1.8.3"],"contains":["Base","GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","Chartboost","StartApp","Kidoz","SuperAwesome"],"source":[],"beta":false},{"name":"NotChildrenAds","version":"1.8.3","require":"","url":"","filter":0,"dependencies":["com.cleversolutions.ads:cas-sdk-teen:1.8.3"],"contains":["Base","Additional","GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","Chartboost","StartApp","Kidoz","FacebookAN","YandexAds"],"source":[],"beta":false}],"advanced":[{"name":"Base","version":"1.8.3","require":"","url":"https://cleveradssolutions.com/","filter":1,"dependencies":["com.cleversolutions.ads:cas-sdk:1.8.3"],"contains":[],"source":["https://dl.bintray.com/cleveradssolutions/CAS-Android"],"beta":false},{"name":"Additional","version":"1.8.3","require":"Base","url":"https://cleveradssolutions.com/","filter":0,"dependencies":["com.cleversolutions.ads:mediation-teen:1.8.3"],"contains":[],"source":[],"beta":false},{"name":"CrossPromotion","version":"1.8.3","require":"Base","url":"https://github.com/cleveradssolutions/CAS-Unity#step-1-add-the-cas-package-to-your-project","filter":1,"dependencies":["com.cleversolutions.ads:cas-promo:1.8.3"],"contains":[],"source":[],"beta":false},{"name":"GoogleAds","version":"19.6.0","require":"Base","url":"https://admob.google.com/home/","filter":1,"dependencies":["com.google.android.gms:play-services-ads:19.6.0"],"contains":[],"source":[],"beta":false},{"name":"UnityAds","version":"3.6.0","require":"Base","url":"https://unity.com/solutions/unity-ads","filter":1,"dependencies":["com.unity3d.ads:unity-ads:3.6.0"],"contains":[],"source":[],"beta":false},{"name":"IronSource","version":"7.0.4.1","require":"Base","url":"https://www.ironsrc.com","filter":1,"dependencies":["com.ironsource.sdk:mediationsdk:7.0.4.1+"],"contains":[],"source":["https://dl.bintray.com/ironsource-mobile/android-sdk"],"beta":false},{"name":"AdColony","version":"4.3.1","require":"Base","url":"https://www.adcolony.com/","filter":1,"dependencies":["com.adcolony:sdk:4.3.1"],"contains":[],"source":["https://adcolony.bintray.com/AdColony"],"beta":false},{"name":"Vungle","version":"6.8.1","require":"Base","url":"https://vungle.com/","filter":1,"dependencies":["com.vungle:publisher-sdk-android:6.8.1+"],"contains":[],"source":[],"beta":false},{"name":"AppLovin","version":"9.14.10","require":"Base","url":"https://www.applovin.com/","filter":1,"dependencies":["com.applovin:applovin-sdk:9.14.10+"],"contains":[],"source":[],"beta":false},{"name":"InMobi","version":"9.1.1","require":"Base","url":"https://www.inmobi.com/","filter":1,"dependencies":["com.inmobi.monetization:inmobi-ads:9.1.1+"],"contains":[],"source":[],"beta":false},{"name":"Chartboost","version":"8.2.0","require":"Base","url":"https://www.chartboost.com/","filter":1,"dependencies":["com.chartboost:chartboost-sdk:8.2.0"],"contains":[],"source":["https://chartboostmobile.bintray.com/Chartboost"],"beta":false},{"name":"StartApp","version":"4.7.5","require":"Base","url":"https://www.startapp.com/","filter":1,"dependencies":["com.chartboost:chartboost-sdk:8.2.0"],"contains":[],"source":[],"beta":false},{"name":"Kidoz","version":"0.8.8.8","require":"Base","url":"https://kidoz.net/","filter":1,"dependencies":["com.kidoz.sdk:KidozSDK:0.8.8.8+"],"contains":[],"source":[],"beta":false},{"name":"SuperAwesome","version":"7.2.16","require":"Base","url":"https://www.superawesome.com/","filter":2,"dependencies":["tv.superawesome.sdk.publisher:superawesome:7.2.16+"],"contains":[],"source":["http://dl.bintray.com/gabrielcoman/maven","http://dl.bintray.com/superawesome/SuperAwesomeSDK"],"beta":false},{"name":"FacebookAN","version":"6.2.0","require":"Additional","url":"https://www.facebook.com/business/marketing/audience-network","filter":0,"dependencies":["com.facebook.android:audience-network-sdk:6.2.0"],"contains":[],"source":[],"beta":false},{"name":"YandexAds","version":"3.1.1","require":"Additional","url":"https://yandex.ru/dev/mobile-ads","filter":0,"dependencies":["com.yandex.android:mobileads:3.1.1+","com.yandex.android:mobmetricalib:3.14.3"],"contains":[],"source":[],"beta":false},{"name":"MyTarget","version":"5.11.9","require":"Additional","url":"https://target.my.com/","filter":0,"dependencies":["com.my.target:mytarget-sdk:5.11.9+"],"contains":[],"source":[],"beta":true},{"name":"Verizon","version":"1.8.2","require":"Additional","url":"https://www.verizonmedia.com/advertising/solutions#/mobile","filter":0,"dependencies":["com.verizon.ads:android-vas-standard-edition:1.8.2+"],"contains":[],"source":[],"beta":true},{"name":"MobFox","version":"4.3.2","require":"Additional","url":"https://www.mobfox.com/","filter":0,"dependencies":["com.github.mobfox:mfx-android-sdk:4.3.2+","com.android.volley:volley:1.1.1"],"contains":[],"source":["https://jitpack.io"],"beta":true},{"name":"AmazonAds","version":"6.0.0","require":"Additional","url":"https://advertising.amazon.com/","filter":0,"dependencies":["com.amazon.android:mobile-ads:6.0.0"],"contains":[],"source":[],"beta":true}]} \ No newline at end of file +{"simple":[{"name":"MixedAudience","version":"1.9.1","require":"","url":"","filter":-1,"dependencies":["com.cleversolutions.ads:cas-sdk-teen:1.9.1","tv.superawesome.sdk.publisher:superawesome:7.2.16+"],"contains":["Base","Additional","GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","Chartboost","StartApp","Kidoz","FacebookAN","YandexAds","SuperAwesome"],"source":[],"labels":0},{"name":"FamiliesAds","version":"1.9.1","require":"","url":"","filter":2,"dependencies":["com.cleversolutions.ads:cas-sdk-general:1.9.1"],"contains":["Base","GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","Chartboost","StartApp","Kidoz","SuperAwesome"],"source":[],"labels":0},{"name":"NotChildrenAds","version":"1.9.1","require":"","url":"","filter":0,"dependencies":["com.cleversolutions.ads:cas-sdk-teen:1.9.1"],"contains":["Base","Additional","GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","Chartboost","StartApp","Kidoz","FacebookAN","YandexAds"],"source":[],"labels":0},{"name":"CrossPromotion","version":"1.9.1","require":"Base","url":"https://github.com/cleveradssolutions/CAS-Unity#step-1-add-the-cas-package-to-your-project","filter":1,"dependencies":["com.cleversolutions.ads:cas-promo:1.9.1"],"contains":[],"source":[],"labels":0}],"advanced":[{"name":"Base","version":"1.9.1","require":"","url":"https://cleveradssolutions.com/","filter":1,"dependencies":["com.cleversolutions.ads:cas-sdk:1.9.1"],"contains":[],"source":["https://dl.bintray.com/cleveradssolutions/CAS-Android"],"labels":0},{"name":"Additional","version":"1.9.1","require":"Base","url":"https://cleveradssolutions.com/","filter":0,"dependencies":["com.cleversolutions.ads:mediation-teen:1.9.1"],"contains":[],"source":[],"labels":0},{"name":"GoogleAds","version":"19.6.0","require":"Base","url":"https://admob.google.com/home/","filter":1,"dependencies":["com.google.android.gms:play-services-ads:19.6.0"],"contains":[],"source":[],"labels":7},{"name":"UnityAds","version":"3.6.0","require":"Base","url":"https://unity.com/solutions/unity-ads","filter":1,"dependencies":["com.unity3d.ads:unity-ads:3.6.0"],"contains":[],"source":[],"labels":7},{"name":"IronSource","version":"7.0.4.1","require":"Base","url":"https://www.ironsrc.com","filter":1,"dependencies":["com.ironsource.sdk:mediationsdk:7.0.4.1+"],"contains":[],"source":["https://dl.bintray.com/ironsource-mobile/android-sdk"],"labels":6},{"name":"AdColony","version":"4.3.1","require":"Base","url":"https://www.adcolony.com/","filter":1,"dependencies":["com.adcolony:sdk:4.3.1"],"contains":[],"source":["https://adcolony.bintray.com/AdColony"],"labels":7},{"name":"Vungle","version":"6.8.1","require":"Base","url":"https://vungle.com/","filter":1,"dependencies":["com.vungle:publisher-sdk-android:6.8.1+"],"contains":[],"source":[],"labels":7},{"name":"AppLovin","version":"9.14.12","require":"Base","url":"https://www.applovin.com/","filter":1,"dependencies":["com.applovin:applovin-sdk:9.14.12+"],"contains":[],"source":[],"labels":7},{"name":"InMobi","version":"9.1.1","require":"Base","url":"https://www.inmobi.com/","filter":1,"dependencies":["com.inmobi.monetization:inmobi-ads:9.1.1+"],"contains":[],"source":[],"labels":7},{"name":"Chartboost","version":"8.2.0","require":"Base","url":"https://www.chartboost.com/","filter":1,"dependencies":["com.chartboost:chartboost-sdk:8.2.0"],"contains":[],"source":["https://chartboostmobile.bintray.com/Chartboost"],"labels":7},{"name":"StartApp","version":"4.7.5","require":"Base","url":"https://www.startapp.com/","filter":1,"dependencies":["com.chartboost:chartboost-sdk:8.2.0"],"contains":[],"source":[],"labels":7},{"name":"Kidoz","version":"8.9.0","require":"Base","url":"https://kidoz.net/","filter":1,"dependencies":["com.kidoz.sdk:KidozSDK:8.9.0+"],"contains":[],"source":[],"labels":7},{"name":"SuperAwesome","version":"7.2.16","require":"Base","url":"https://www.superawesome.com/","filter":2,"dependencies":["tv.superawesome.sdk.publisher:superawesome:7.2.16+"],"contains":[],"source":["http://dl.bintray.com/gabrielcoman/maven","http://dl.bintray.com/superawesome/SuperAwesomeSDK"],"labels":7},{"name":"FacebookAN","version":"6.2.0","require":"Additional","url":"https://www.facebook.com/business/marketing/audience-network","filter":0,"dependencies":["com.facebook.android:audience-network-sdk:6.2.0"],"contains":[],"source":[],"labels":7},{"name":"YandexAds","version":"3.1.1","require":"Additional","url":"https://yandex.ru/dev/mobile-ads","filter":0,"dependencies":["com.yandex.android:mobileads:3.1.1+","com.yandex.android:mobmetricalib:3.14.3"],"contains":[],"source":[],"labels":3},{"name":"MyTarget","version":"5.11.9","require":"Additional","url":"https://target.my.com/","filter":0,"dependencies":["com.my.target:mytarget-sdk:5.11.9+"],"contains":[],"source":[],"labels":23},{"name":"Verizon","version":"1.8.2","require":"Additional","url":"https://www.verizonmedia.com/advertising/solutions#/mobile","filter":0,"dependencies":["com.verizon.ads:android-vas-standard-edition:1.8.2+"],"contains":[],"source":[],"labels":23},{"name":"MobFox","version":"4.3.2","require":"Additional","url":"https://www.mobfox.com/","filter":0,"dependencies":["com.github.mobfox:mfx-android-sdk:4.3.2+","com.android.volley:volley:1.1.1"],"contains":[],"source":["https://jitpack.io"],"labels":19},{"name":"AmazonAds","version":"6.0.0","require":"Additional","url":"https://advertising.amazon.com/","filter":0,"dependencies":["com.amazon.android:mobile-ads:6.0.0"],"contains":[],"source":[],"labels":17}]} \ No newline at end of file diff --git a/Templates/CASSKAdNetworks.txt b/Templates/CASSKAdNetworks.txt index 8568a79..3efb8b9 100644 --- a/Templates/CASSKAdNetworks.txt +++ b/Templates/CASSKAdNetworks.txt @@ -59,3 +59,6 @@ MTKV5XTK9E.skadnetwork p78axxw29g.skadnetwork v9wttpbfk9.skadnetwork n38lu8286q.skadnetwork +578prtvx9j.skadnetwork +24t9a8vw3c.skadnetwork +s39g8k73mm.skadnetwork diff --git a/Templates/CASiOSMediation.list b/Templates/CASiOSMediation.list index 2b04d94..648a8aa 100644 --- a/Templates/CASiOSMediation.list +++ b/Templates/CASiOSMediation.list @@ -1 +1 @@ -{"simple":[{"name":"Recomended","version":"1.8.3","require":"","url":"","filter":1,"dependencies":["CleverAdsSolutions-SDK"],"contains":["GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","FacebookAN","YandexAds","Kidoz","Chartboost","StartApp","SuperAwesome","Main","Base"],"source":[],"beta":false},{"name":"Main","version":"1.8.3","require":"","url":"","filter":1,"dependencies":["CleverAdsSolutions-SDK/General"],"contains":["GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","Base"],"source":[],"beta":false}],"advanced":[{"name":"Base","version":"1.0","require":"","url":"","filter":0,"dependencies":[],"contains":[],"source":["https://github.com/CocoaPods/Specs.git","https://github.com/cleveradssolutions/CAS-Specs.git"],"beta":false},{"name":"CrossPromotion","version":"1.8.3","require":"","url":"https://github.com/cleveradssolutions/CAS-Unity#step-1-add-the-cas-package-to-your-project","filter":1,"dependencies":["CleverAdsSolutions-Promo"],"contains":["Base"],"source":[],"beta":false},{"name":"GoogleAds","version":"1.8.3","require":"","url":"https://admob.google.com/home/","filter":1,"dependencies":["CleverAdsSolutions-SDK/GoogleAds"],"contains":["Base"],"source":[],"beta":false},{"name":"UnityAds","version":"1.8.3","require":"","url":"https://unity.com/solutions/unity-ads","filter":1,"dependencies":["CleverAdsSolutions-SDK/UnityAds"],"contains":["Base"],"source":[],"beta":false},{"name":"IronSource","version":"1.8.3","require":"","url":"https://www.ironsrc.com","filter":1,"dependencies":["CleverAdsSolutions-SDK/IronSource"],"contains":["Base"],"source":[],"beta":false},{"name":"AdColony","version":"1.8.3","require":"","url":"https://www.adcolony.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/AdColony"],"contains":["Base"],"source":[],"beta":false},{"name":"Vungle","version":"1.8.3","require":"","url":"https://vungle.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/Vungle"],"contains":["Base"],"source":[],"beta":false},{"name":"AppLovin","version":"1.8.3","require":"","url":"https://www.applovin.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/AppLovin"],"contains":["Base"],"source":[],"beta":false},{"name":"InMobi","version":"1.8.3","require":"","url":"https://www.inmobi.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/InMobi"],"contains":["Base"],"source":[],"beta":false},{"name":"Kidoz","version":"1.8.3","require":"","url":"https://kidoz.net/","filter":1,"dependencies":["CleverAdsSolutions-SDK/Kidoz"],"contains":["Base"],"source":[],"beta":false},{"name":"SuperAwesome","version":"1.8.3","require":"","url":"https://www.superawesome.com/","filter":2,"dependencies":["CleverAdsSolutions-SDK/SuperAwesome"],"contains":["Base"],"source":[],"beta":false},{"name":"StartApp","version":"1.8.3","require":"","url":"https://www.startapp.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/StartApp"],"contains":["Base"],"source":[],"beta":false},{"name":"FacebookAN","version":"1.8.3","require":"","url":"https://www.facebook.com/business/marketing/audience-network","filter":1,"dependencies":["CleverAdsSolutions-SDK/FBAudienceNetwork"],"contains":["Base"],"source":[],"beta":false},{"name":"YandexAds","version":"1.8.3","require":"","url":"https://yandex.ru/dev/mobile-ads","filter":1,"dependencies":["CleverAdsSolutions-SDK/YandexAds"],"contains":["Base"],"source":[],"beta":false},{"name":"Chartboost","version":"1.8.3","require":"","url":"https://www.chartboost.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/Chartboost"],"contains":["Base"],"source":[],"beta":false},{"name":"MyTarget","version":"1.8.3","require":"","url":"https://target.my.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/MyTarget"],"contains":["Base"],"source":[],"beta":true},{"name":"Verizon","version":"1.8.3","require":"","url":"https://www.verizonmedia.com/advertising/solutions#/mobile","filter":1,"dependencies":["CleverAdsSolutions-SDK/Verizon"],"contains":["Base"],"source":[],"beta":true},{"name":"MobFox","version":"1.8.3","require":"","url":"https://www.mobfox.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/MobFox"],"contains":["Base"],"source":[],"beta":true},{"name":"AmazonAds","version":"1.8.3","require":"","url":"https://advertising.amazon.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/AmazonAd"],"contains":["Base"],"source":[],"beta":true}]} \ No newline at end of file +{"simple":[{"name":"Recomended","version":"1.9.1","require":"","url":"","filter":1,"dependencies":["CleverAdsSolutions-SDK"],"contains":["GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","FacebookAN","YandexAds","Kidoz","Chartboost","StartApp","SuperAwesome","Main","Base"],"source":[],"labels":0},{"name":"Main","version":"1.9.1","require":"","url":"","filter":1,"dependencies":["CleverAdsSolutions-SDK/General"],"contains":["GoogleAds","UnityAds","IronSource","AdColony","Vungle","AppLovin","InMobi","Base"],"source":[],"labels":0},{"name":"CrossPromotion","version":"1.9.1","require":"","url":"https://github.com/cleveradssolutions/CAS-Unity#step-1-add-the-cas-package-to-your-project","filter":1,"dependencies":["CleverAdsSolutions-Promo"],"contains":["Base","Cross-promotion uses Firebase Deep Link to track conversions."],"source":[],"labels":0}],"advanced":[{"name":"Base","version":"1.0","require":"","url":"","filter":0,"dependencies":[],"contains":[],"source":["https://github.com/CocoaPods/Specs.git","https://github.com/cleveradssolutions/CAS-Specs.git"],"labels":0},{"name":"GoogleAds","version":"1.9.1","require":"","url":"https://admob.google.com/home/","filter":1,"dependencies":["CleverAdsSolutions-SDK/GoogleAds"],"contains":["Base"],"source":[],"labels":7},{"name":"UnityAds","version":"1.9.1","require":"","url":"https://unity.com/solutions/unity-ads","filter":1,"dependencies":["CleverAdsSolutions-SDK/UnityAds"],"contains":["Base"],"source":[],"labels":7},{"name":"IronSource","version":"1.9.1","require":"","url":"https://www.ironsrc.com","filter":1,"dependencies":["CleverAdsSolutions-SDK/IronSource"],"contains":["Base"],"source":[],"labels":6},{"name":"AdColony","version":"1.9.1","require":"","url":"https://www.adcolony.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/AdColony"],"contains":["Base"],"source":[],"labels":7},{"name":"Vungle","version":"1.9.1","require":"","url":"https://vungle.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/Vungle"],"contains":["Base"],"source":[],"labels":7},{"name":"AppLovin","version":"1.9.1","require":"","url":"https://www.applovin.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/AppLovin"],"contains":["Base"],"source":[],"labels":7},{"name":"InMobi","version":"1.9.1","require":"","url":"https://www.inmobi.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/InMobi"],"contains":["Base"],"source":[],"labels":7},{"name":"Kidoz","version":"1.9.1","require":"","url":"https://kidoz.net/","filter":1,"dependencies":["CleverAdsSolutions-SDK/Kidoz"],"contains":["Base"],"source":[],"labels":7},{"name":"SuperAwesome","version":"1.9.1","require":"","url":"https://www.superawesome.com/","filter":2,"dependencies":["CleverAdsSolutions-SDK/SuperAwesome"],"contains":["Base"],"source":[],"labels":7},{"name":"StartApp","version":"1.9.1","require":"","url":"https://www.startapp.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/StartApp"],"contains":["Base"],"source":[],"labels":7},{"name":"FacebookAN","version":"1.9.1","require":"","url":"https://www.facebook.com/business/marketing/audience-network","filter":1,"dependencies":["CleverAdsSolutions-SDK/FBAudienceNetwork"],"contains":["Base"],"source":[],"labels":7},{"name":"YandexAds","version":"1.9.1","require":"","url":"https://yandex.ru/dev/mobile-ads","filter":1,"dependencies":["CleverAdsSolutions-SDK/YandexAds"],"contains":["Base"],"source":[],"labels":3},{"name":"Chartboost","version":"1.9.1","require":"","url":"https://www.chartboost.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/Chartboost"],"contains":["Base"],"source":[],"labels":7},{"name":"MyTarget","version":"1.9.1","require":"","url":"https://target.my.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/MyTarget"],"contains":["Base"],"source":[],"labels":23},{"name":"Verizon","version":"1.9.1","require":"","url":"https://www.verizonmedia.com/advertising/solutions#/mobile","filter":1,"dependencies":["CleverAdsSolutions-SDK/Verizon"],"contains":["Base"],"source":[],"labels":23},{"name":"MobFox","version":"1.9.1","require":"","url":"https://www.mobfox.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/MobFox"],"contains":["Base"],"source":[],"labels":19},{"name":"AmazonAds","version":"1.9.1","require":"","url":"https://advertising.amazon.com/","filter":1,"dependencies":["CleverAdsSolutions-SDK/AmazonAd"],"contains":["Base"],"source":[],"labels":17}]} \ No newline at end of file diff --git a/package.json b/package.json index 79866ef..0c8dd04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.cleversolutions.ads.unity", - "version": "1.8.3", + "version": "1.9.1", "displayName": "CleverAdsSolutions", "description": "Clever Ads Solutions Unity wrapper for mobile ads on platforms Android and iOS.", "unity": "2017.4",