using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using UnityEngine; using ConsentManager.Common; namespace ConsentManager.Platforms.Android { #if UNITY_ANDROID [SuppressMessage("ReSharper", "InconsistentNaming")] public class AndroidConsentManager : IConsentManager { private AndroidJavaObject consentManagerInstance; private AndroidJavaObject activity; private AndroidJavaObject getInstance() { return consentManagerInstance ?? (consentManagerInstance = new AndroidJavaObject("com.appodeal.consent.ConsentManager")); } private AndroidJavaObject getActivity() { return activity ?? (activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic("currentActivity")); } public void requestConsentInfoUpdate(string appodealAppKey, IConsentInfoUpdateListener listener) { getInstance().CallStatic("requestConsentInfoUpdate", getActivity(), appodealAppKey, new ConsentInfoUpdateCallbacks(listener)); } public void setCustomVendor(Vendor customVendor) { var androidVendor = (AndroidVendor) customVendor.getNativeVendor(); getInstance().CallStatic("getCustomVendors").Call("put", androidVendor.getBundle(), androidVendor.getVendor()); } public Vendor getCustomVendor(string bundle) { return new Vendor(new AndroidVendor(getInstance().CallStatic("getCustomVendors").Call("get", Helper.getJavaObject(bundle)))); } public ConsentManager.Storage getStorage() { var storage = ConsentManager.Storage.NONE; switch (getInstance().CallStatic("getStorage").Call("name")) { case "NONE": storage = ConsentManager.Storage.NONE; break; case "SHARED_PREFERENCE": storage = ConsentManager.Storage.SHARED_PREFERENCE; break; } return storage; } public void setStorage(ConsentManager.Storage iabStorage) { switch (iabStorage) { case ConsentManager.Storage.NONE: getInstance().CallStatic("setStorage", new AndroidJavaClass("com.appodeal.consent.ConsentManager$Storage").GetStatic("NONE")); break; case ConsentManager.Storage.SHARED_PREFERENCE: getInstance().CallStatic("setStorage", new AndroidJavaClass("com.appodeal.consent.ConsentManager$Storage").GetStatic("SHARED_PREFERENCE")); break; default: throw new ArgumentOutOfRangeException(nameof(iabStorage), iabStorage, null); } } public Consent.ShouldShow shouldShowConsentDialog() { var shouldShow = Consent.ShouldShow.UNKNOWN; switch (getInstance().CallStatic("getShouldShow")) { case true: shouldShow = Consent.ShouldShow.TRUE; break; case false: shouldShow = Consent.ShouldShow.FALSE; break; } return shouldShow; } public Consent.Zone getConsentZone() { var zone = Consent.Zone.UNKNOWN; switch (getInstance().CallStatic("getConsentZone").Call("name")) { case "UNKNOWN": zone = Consent.Zone.UNKNOWN; break; case "NONE": zone = Consent.Zone.NONE; break; case "GDPR": zone = Consent.Zone.GDPR; break; case "CCPA": zone = Consent.Zone.CCPA; break; } return zone; } public Consent.Status getConsentStatus() { var status = Consent.Status.UNKNOWN; switch (getInstance().CallStatic("getConsentStatus").Call("name")) { case "UNKNOWN": status = Consent.Status.UNKNOWN; break; case "PERSONALIZED": status = Consent.Status.PERSONALIZED; break; case "NON_PERSONALIZED": status = Consent.Status.NON_PERSONALIZED; break; case "PARTLY_PERSONALIZED": status = Consent.Status.PARTLY_PERSONALIZED; break; } return status; } public Consent getConsent() { return new Consent(new AndroidConsent(getInstance().CallStatic("getConsent"))); } public void disableAppTrackingTransparencyRequest() { Debug.Log("Not supported on Android platform"); } } [SuppressMessage("ReSharper", "InconsistentNaming")] public class AndroidVendorBuilder : IVendorBuilder { private readonly AndroidJavaObject builder; private AndroidJavaObject vendor; public AndroidVendorBuilder(string name, string bundle, string policyUrl) { builder = new AndroidJavaObject("com.appodeal.consent.Vendor$Builder", name, bundle, policyUrl); } private AndroidJavaObject getBuilder() { return builder; } public IVendor build() { vendor = getBuilder().Call("build"); return new AndroidVendor(vendor); } public void setPurposeIds(IEnumerable purposeIds) { setNativeList(purposeIds, "purposeIds"); } public void setFeatureIds(IEnumerable featureIds) { setNativeList(featureIds, "featureIds"); } public void setLegitimateInterestPurposeIds(IEnumerable legitimateInterestPurposeIds) { setNativeList(legitimateInterestPurposeIds, "legitimateInterestPurposeIds"); } private void setNativeList(IEnumerable list, string methodName) { var androidJavaObject = new AndroidJavaObject("java.util.ArrayList"); foreach (var obj in list) { androidJavaObject.Call("add", Helper.getJavaObject(obj)); } getBuilder().Call(methodName, androidJavaObject); } } [SuppressMessage("ReSharper", "InconsistentNaming")] public class AndroidVendor : IVendor { private readonly AndroidJavaObject vendor; public AndroidVendor(AndroidJavaObject vendor) { this.vendor = vendor; } public AndroidJavaObject getVendor() { return vendor; } public string getName() { return getVendor().Call("getName"); } public string getBundle() { return getVendor().Call("getBundle"); } public string getPolicyUrl() { return getVendor().Call("getPolicyUrl"); } public List getPurposeIds() { return getNativeList("getPurposeIds", getVendor()); } public List getFeatureIds() { return getNativeList("getFeatureIds", getVendor()); } public List getLegitimateInterestPurposeIds() { return getNativeList("getLegitimateInterestPurposeIds", getVendor()); } private static List getNativeList(string methodName, AndroidJavaObject androidJavaObject) { var purposeIdsList = new List(); AndroidJNI.PushLocalFrame(100); using (var joPurposeIdsList = androidJavaObject.Call(methodName)) { for (var i = 0; i < joPurposeIdsList.Call("size"); i++) { using (var PurposeId = joPurposeIdsList.Call("get", i)) { purposeIdsList.Add(PurposeId.Call("intValue")); } } } AndroidJNI.PopLocalFrame(IntPtr.Zero); return purposeIdsList; } } [SuppressMessage("ReSharper", "InconsistentNaming")] public class AndroidConsentForm : IConsentForm { private readonly AndroidJavaObject consentForm; private AndroidJavaObject activity; public AndroidConsentForm(AndroidJavaObject builder) { consentForm = builder; } public AndroidConsentForm(IConsentFormListener consentFormListener) { consentForm = new AndroidJavaObject("com.appodeal.consent.ConsentForm", getActivity(), new ConsentFormCallbacks(consentFormListener)); } private AndroidJavaObject getConsentForm() { return consentForm; } private AndroidJavaObject getActivity() { return activity ?? (activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic("currentActivity")); } public void load() { getConsentForm().Call("load"); } public void show() { getConsentForm().Call("show"); } public bool isLoaded() { return getConsentForm().Call("isLoaded"); } public bool isShowing() { return getConsentForm().Call("isShowing"); } } [SuppressMessage("ReSharper", "InconsistentNaming")] public class AndroidConsentManagerException : IConsentManagerException { private readonly AndroidJavaObject consentManagerException; public AndroidConsentManagerException(AndroidJavaObject androidJavaObject) { consentManagerException = androidJavaObject; } public AndroidConsentManagerException() { consentManagerException = new AndroidJavaObject("com.appodeal.consent.ConsentManagerError"); } private AndroidJavaObject getConsentManagerException() { return consentManagerException; } public string getReason() { return getConsentManagerException().Call("getMessage"); } public int getCode() { string reason = getConsentManagerException().Call("getEvent"); return reason == "LoadingError" ? 2 : 1; } } [SuppressMessage("ReSharper", "InconsistentNaming")] [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] [SuppressMessage("ReSharper", "UnusedMember.Local")] public class AndroidConsent : IConsent { private readonly AndroidJavaObject consent; public AndroidConsent(AndroidJavaObject joConsent) { consent = joConsent; } public AndroidJavaObject getConsent() { return consent; } public Consent.Zone getZone() { var zone = Consent.Zone.UNKNOWN; switch (getConsent().Call("getZone").Call("name")) { case "UNKNOWN": zone = Consent.Zone.UNKNOWN; break; case "NONE": zone = Consent.Zone.NONE; break; case "GDPR": zone = Consent.Zone.GDPR; break; case "CCPA": zone = Consent.Zone.CCPA; break; } return zone; } public Consent.Status getStatus() { var status = Consent.Status.UNKNOWN; switch (getConsent().Call("getStatus").Call("name")) { case "UNKNOWN": status = Consent.Status.UNKNOWN; break; case "NON_PERSONALIZED": status = Consent.Status.NON_PERSONALIZED; break; case "PARTLY_PERSONALIZED": status = Consent.Status.PARTLY_PERSONALIZED; break; case "PERSONALIZED": status = Consent.Status.PERSONALIZED; break; } return status; } public Consent.AuthorizationStatus getAuthorizationStatus() { Debug.Log("Not supported on this platform"); return Consent.AuthorizationStatus.NOT_DETERMINED; } public Consent.HasConsent hasConsentForVendor(string bundle) { var hasConsent = Consent.HasConsent.UNKNOWN; switch (getConsent().Call("hasConsentForVendor", Helper.getJavaObject(bundle))) { case true: hasConsent = Consent.HasConsent.TRUE; break; case false: hasConsent = Consent.HasConsent.FALSE; break; } return hasConsent; } public List getAcceptedVendors() { var vendors = new List(); AndroidJNI.PushLocalFrame(100); using (var joPurposeIdsList = getConsent().Call("getAcceptedVendors")) { for (var i = 0; i < joPurposeIdsList.Call("size"); i++) { using (var vendor = joPurposeIdsList.Call("get", i)) { vendors.Add(new Vendor(new AndroidVendor(vendor))); } } } AndroidJNI.PopLocalFrame(IntPtr.Zero); return vendors; } public string getIabConsentString() { return getConsent().Call("getIABConsentString"); } } [SuppressMessage("ReSharper", "InconsistentNaming")] [SuppressMessage("ReSharper", "ConstantNullCoalescingCondition")] public static class Helper { public static object getJavaObject(object value) { if (value is string) { return value; } if (value is char) { return new AndroidJavaObject("java.lang.Character", value); } if ((value is bool)) { return new AndroidJavaObject("java.lang.Boolean", value); } if (value is int) { return new AndroidJavaObject("java.lang.Integer", value); } if (value is long) { return new AndroidJavaObject("java.lang.Long", value); } if (value is float) { return new AndroidJavaObject("java.lang.Float", value); } if (value is double) { return new AndroidJavaObject("java.lang.Float", value); } return value ?? null; } } #endif }