// // MaxCmpService.cs // AppLovin User Engagement Unity Plugin // // Created by Santosh Bagadi on 10/1/23. // Copyright © 2023 AppLovin. All rights reserved. // using System; using System.Collections.Generic; #if UNITY_EDITOR #elif UNITY_ANDROID using UnityEngine; #elif UNITY_IOS using System.Runtime.InteropServices; #endif /// /// This class provides direct APIs for interfacing with the Google-certified CMP installed, if any. /// public class MaxCmpService { private static readonly MaxCmpService _instance = new MaxCmpService(); private MaxCmpService() { } private static Action OnCompletedAction; #if UNITY_EDITOR #elif UNITY_ANDROID private static readonly AndroidJavaClass MaxUnityPluginClass = new AndroidJavaClass("com.applovin.mediation.unity.MaxUnityPlugin"); #elif UNITY_IOS [DllImport("__Internal")] private static extern void _MaxShowCmpForExistingUser(); [DllImport("__Internal")] private static extern bool _MaxHasSupportedCmp(); #endif internal static MaxCmpService Instance { get { return _instance; } } /// /// Shows the CMP flow to an existing user. /// Note that the user's current consent will be reset before the CMP alert is shown. /// /// Called when the CMP flow finishes showing. public void ShowCmpForExistingUser(Action onCompletedAction) { OnCompletedAction = onCompletedAction; #if UNITY_EDITOR var errorProps = new Dictionary { {"code", (int) MaxCmpError.ErrorCode.FormUnavailable}, {"message", "CMP is not supported in Unity editor"} }; NotifyCompletedIfNeeded(errorProps); #elif UNITY_ANDROID MaxUnityPluginClass.CallStatic("showCmpForExistingUser"); #elif UNITY_IOS _MaxShowCmpForExistingUser(); #endif } /// /// Returns true if a supported CMP SDK is detected. /// public bool HasSupportedCmp { get { #if UNITY_EDITOR return false; #elif UNITY_ANDROID return MaxUnityPluginClass.CallStatic("hasSupportedCmp"); #elif UNITY_IOS return _MaxHasSupportedCmp(); #else return false; #endif } } internal static void NotifyCompletedIfNeeded(Dictionary errorProps) { if (OnCompletedAction == null) return; var error = (errorProps == null) ? null : MaxCmpError.Create(errorProps); OnCompletedAction(error); } } public class MaxCmpError { public enum ErrorCode { /// /// Indicates that an unspecified error has occurred. /// Unspecified = -1, /// /// Indicates that the CMP has not been integrated correctly. /// IntegrationError = 1, /// /// Indicates that the CMP form is unavailable. /// FormUnavailable = 2, /// /// Indicates that the CMP form is not required. /// FormNotRequired = 3 } public static MaxCmpError Create(IDictionary error) { return new MaxCmpError() { Code = GetCode(MaxSdkUtils.GetIntFromDictionary(error, "code")), Message = MaxSdkUtils.GetStringFromDictionary(error, "message"), CmpCode = MaxSdkUtils.GetIntFromDictionary(error, "cmpCode", -1), CmpMessage = MaxSdkUtils.GetStringFromDictionary(error, "cmpMessage") }; } private static ErrorCode GetCode(int code) { switch (code) { case 1: return ErrorCode.IntegrationError; case 2: return ErrorCode.FormUnavailable; case 3: return ErrorCode.FormNotRequired; default: return ErrorCode.Unspecified; } } private MaxCmpError() { } /// /// The error code for this error. /// public ErrorCode Code { get; private set; } /// /// The error message for this error. /// public string Message { get; private set; } /// /// The error code returned by the CMP. /// public int CmpCode { get; private set; } /// /// The error message returned by the CMP. /// public string CmpMessage { get; private set; } }