diff --git a/Editor/QonversionDependencies.xml b/Editor/QonversionDependencies.xml index 1f6fd83..8e63191 100644 --- a/Editor/QonversionDependencies.xml +++ b/Editor/QonversionDependencies.xml @@ -1,11 +1,11 @@ - + - + diff --git a/Runtime/Android/AutomationsWrapperAndroid.cs b/Runtime/Android/AutomationsWrapperAndroid.cs new file mode 100644 index 0000000..4aa274a --- /dev/null +++ b/Runtime/Android/AutomationsWrapperAndroid.cs @@ -0,0 +1,55 @@ +using UnityEngine; + +namespace QonversionUnity +{ + internal class AutomationsWrapperAndroid : IAutomationsWrapper + { + public void Initialize(string gameObjectName) + { + CallAutomations("initialize", gameObjectName); + } + + public void SetNotificationsToken(string token) + { + CallAutomations("setNotificationsToken", token); + } + + public bool HandleNotification(string notification) + { + return CallAutomations("handleNotification", notification); + } + + public string GetNotificationCustomPayload(string notification) + { + return CallAutomations("getNotificationCustomPayload", notification); + } + + public void SubscribeOnAutomationEvents() + { + CallAutomations("subscribeOnAutomationEvents"); + } + + public void ShowScreen(string screenId, string callbackName) + { + CallAutomations("showScreen", screenId, callbackName); + } + + private const string AutomationsWrapper = "com.qonversion.unitywrapper.AutomationsWrapper"; + + private static T CallAutomations(string methodName, params object[] args) + { + using (var automations = new AndroidJavaClass(AutomationsWrapper)) + { + return automations.CallStatic(methodName, args); + } + } + + private static void CallAutomations(string methodName, params object[] args) + { + using (var automations = new AndroidJavaClass(AutomationsWrapper)) + { + automations.CallStatic(methodName, args); + } + } + } +} \ No newline at end of file diff --git a/Runtime/Android/AutomationsWrapperAndroid.cs.meta b/Runtime/Android/AutomationsWrapperAndroid.cs.meta new file mode 100644 index 0000000..70fa1d1 --- /dev/null +++ b/Runtime/Android/AutomationsWrapperAndroid.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bf1469979a8544c5b531368ea34cec2f +timeCreated: 1668776137 \ No newline at end of file diff --git a/Runtime/Android/Plugins/com/qonversion/unitywrapper/AutomationsWrapper.java b/Runtime/Android/Plugins/com/qonversion/unitywrapper/AutomationsWrapper.java index 3214d1c..613ecb7 100644 --- a/Runtime/Android/Plugins/com/qonversion/unitywrapper/AutomationsWrapper.java +++ b/Runtime/Android/Plugins/com/qonversion/unitywrapper/AutomationsWrapper.java @@ -6,6 +6,9 @@ import androidx.annotation.Nullable; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.jetbrains.annotations.NotNull; @@ -14,8 +17,11 @@ import io.qonversion.sandwich.AutomationsEventListener; import io.qonversion.sandwich.AutomationsSandwich; +import io.qonversion.sandwich.ResultListener; +import io.qonversion.sandwich.SandwichError; -public class AutomationsWrapper implements AutomationsEventListener { +@SuppressWarnings("UnnecessaryLocalVariable") +public class AutomationsWrapper { private static final String EVENT_SCREEN_SHOWN = "OnAutomationsScreenShown"; private static final String EVENT_ACTION_STARTED = "OnAutomationsActionStarted"; private static final String EVENT_ACTION_FAILED = "OnAutomationsActionFailed"; @@ -23,45 +29,107 @@ public class AutomationsWrapper implements AutomationsEventListener { private static final String EVENT_AUTOMATIONS_FINISHED = "OnAutomationsFinished"; public static String TAG = "AutomationsDelegate"; - private final MessageSender messageSender; - private final AutomationsSandwich automationsSandwich; + private static MessageSender messageSender; + private static AutomationsSandwich automationsSandwich; - public AutomationsWrapper(MessageSender messageSender) { - this.messageSender = messageSender; + public static synchronized void initialize(String unityListener) { + messageSender = new MessageSender(unityListener); automationsSandwich = new AutomationsSandwich(); } - public void subscribe() { - automationsSandwich.subscribe(this); + public static synchronized void subscribeOnAutomationEvents() { + automationsSandwich.setDelegate(new EventListener()); } - @Override - public void onAutomationEvent(@NonNull Event event, @Nullable Map data) { - String methodName = ""; - switch (event) { - case ScreenShown: - methodName = EVENT_SCREEN_SHOWN; - break; - case ActionStarted: - methodName = EVENT_ACTION_STARTED; - break; - case ActionFinished: - methodName = EVENT_ACTION_FINISHED; - break; - case ActionFailed: - methodName = EVENT_ACTION_FAILED; - break; - case AutomationsFinished: - methodName = EVENT_AUTOMATIONS_FINISHED; - break; - default: - return; + public static synchronized void setNotificationsToken(String token) { + automationsSandwich.setNotificationToken(token); + } + + public static synchronized boolean handleNotification(String notification) { + try { + ObjectMapper mapper = new ObjectMapper(); + + TypeReference> typeRef + = new TypeReference>() { + }; + Map notificationInfo = mapper.readValue(notification, typeRef); + + boolean result = automationsSandwich.handleNotification(notificationInfo); + + return result; + } catch (Exception e) { + return false; + } + } + + @Nullable + public static synchronized String getNotificationCustomPayload(String notification) { + try { + final ObjectMapper mapper = new ObjectMapper(); + + final TypeReference> typeRef + = new TypeReference>() { + }; + final Map notificationInfo = mapper.readValue(notification, typeRef); + + final Map payload = automationsSandwich.getNotificationCustomPayload(notificationInfo); + final String json = mapper.writeValueAsString(payload); + + return json; + } catch (Exception e) { + return null; } + } + + public static synchronized void showScreen(String screenId, String unityCallbackName) { + automationsSandwich.showScreen(screenId, new ResultListener() { + @Override + public void onSuccess(@NonNull Map data) { + sendMessageToUnity(data, unityCallbackName); + } + + @Override + public void onError(@NonNull SandwichError error) { + handleErrorResponse(error, unityCallbackName); + } + }); + } - sendMessageToUnity(data == null ? new HashMap<>() : data, methodName); + private static void handleErrorResponse(@NotNull SandwichError error, @NotNull String methodName) { + final ObjectNode rootNode = Utils.createErrorNode(error); + + sendMessageToUnity(rootNode, methodName); + } + + static class EventListener implements AutomationsEventListener { + @Override + public void onAutomationEvent(@NonNull Event event, @Nullable Map data) { + String methodName; + switch (event) { + case ScreenShown: + methodName = EVENT_SCREEN_SHOWN; + break; + case ActionStarted: + methodName = EVENT_ACTION_STARTED; + break; + case ActionFinished: + methodName = EVENT_ACTION_FINISHED; + break; + case ActionFailed: + methodName = EVENT_ACTION_FAILED; + break; + case AutomationsFinished: + methodName = EVENT_AUTOMATIONS_FINISHED; + break; + default: + return; + } + + sendMessageToUnity(data == null ? new HashMap<>() : data, methodName); + } } - private void sendMessageToUnity(@NotNull Object objectToConvert, @NotNull String methodName) { + private static void sendMessageToUnity(@NotNull Object objectToConvert, @NotNull String methodName) { try { messageSender.sendMessageToUnity(objectToConvert, methodName); } catch (JsonProcessingException e) { @@ -69,7 +137,7 @@ private void sendMessageToUnity(@NotNull Object objectToConvert, @NotNull String } } - private void handleException(Exception e) { + private static void handleException(Exception e) { Log.e(TAG, "An error occurred while processing automations flow: " + e.getLocalizedMessage()); } } diff --git a/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java b/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java index c545fa2..8508c59 100644 --- a/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java +++ b/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java @@ -27,10 +27,9 @@ public class QonversionWrapper { public static String TAG = "QonversionWrapper"; - public static String ON_UPDATED_PURCHASES_LISTENER = "OnReceiveUpdatedPurchases"; + public static String ENTITLEMENTS_UPDATE_LISTENER = "OnReceivedUpdatedEntitlements"; private static MessageSender messageSender; - private static AutomationsWrapper automationsWrapper; private static QonversionSandwich qonversionSandwich; public static synchronized void initialize(String unityListener) { @@ -40,27 +39,33 @@ public static synchronized void initialize(String unityListener) { qonversionSandwich = new QonversionSandwich( application, () -> UnityPlayer.currentActivity, - permissions -> sendMessageToUnity(permissions, ON_UPDATED_PURCHASES_LISTENER) + entitlements -> sendMessageToUnity(entitlements, ENTITLEMENTS_UPDATE_LISTENER) ); - automationsWrapper = new AutomationsWrapper(messageSender); } public static synchronized void storeSdkInfo(String version, String source) { qonversionSandwich.storeSdkInfo(source, version); } - public static synchronized void launch(String projectKey, boolean observerMode, String unityCallbackName) { - qonversionSandwich.launch(projectKey, observerMode, getResultListener(unityCallbackName)); + public static synchronized void initializeSdk( + String projectKey, + String launchModeKey, + @Nullable String environmentKey, + @Nullable String entitlementsCacheLifetimeKey + ) { + qonversionSandwich.initialize( + UnityPlayer.currentActivity, + projectKey, + launchModeKey, + environmentKey, + entitlementsCacheLifetimeKey + ); } public static synchronized void syncPurchases() { qonversionSandwich.syncPurchases(); } - public static synchronized void setDebugMode() { - qonversionSandwich.setDebugMode(); - } - public static synchronized void setProperty(String key, String value) { qonversionSandwich.setDefinedProperty(key, value); } @@ -69,7 +74,7 @@ public static synchronized void setUserProperty(String key, String value) { qonversionSandwich.setCustomProperty(key, value); } - public static synchronized void attribution(String conversionData, String attributionSource) { + public static synchronized void attribution(String conversionData, String attributionProvider) { try { ObjectMapper mapper = new ObjectMapper(); @@ -77,7 +82,7 @@ public static synchronized void attribution(String conversionData, String attrib = new TypeReference>() {}; Map conversionInfo = mapper.readValue(conversionData, typeRef); - qonversionSandwich.addAttributionData(attributionSource, conversionInfo); + qonversionSandwich.addAttributionData(attributionProvider, conversionInfo); } catch (JsonProcessingException e) { handleSerializationException(e); } @@ -91,8 +96,12 @@ public static synchronized void logout() { qonversionSandwich.logout(); } - public static synchronized void checkPermissions(String unityCallbackName) { - qonversionSandwich.checkPermissions(getResultListener(unityCallbackName)); + public static synchronized void userInfo(String unityCallbackName) { + qonversionSandwich.userInfo(getResultListener(unityCallbackName)); + } + + public static synchronized void checkEntitlements(String unityCallbackName) { + qonversionSandwich.checkEntitlements(getResultListener(unityCallbackName)); } public static synchronized void purchase(String productId, String unityCallbackName) { @@ -123,7 +132,7 @@ public static synchronized void offerings(String unityCallbackName) { qonversionSandwich.offerings(getResultListener(unityCallbackName)); } - public static synchronized void checkTrialIntroEligibilityForProductIds(String productIds, String unityCallbackName) { + public static synchronized void checkTrialIntroEligibility(String productIds, String unityCallbackName) { try { ObjectMapper mapper = new ObjectMapper(); TypeReference> typeRef = new TypeReference>() {}; @@ -135,53 +144,6 @@ public static synchronized void checkTrialIntroEligibilityForProductIds(String p } } - public static synchronized void setPermissionsCacheLifetime(String lifetimeKey) { - qonversionSandwich.setPermissionsCacheLifetime(lifetimeKey); - } - - public static synchronized void setNotificationsToken(String token) { - qonversionSandwich.setNotificationToken(token); - } - - public static synchronized boolean handleNotification(String notification) { - try { - ObjectMapper mapper = new ObjectMapper(); - - TypeReference> typeRef - = new TypeReference>() { - }; - Map notificationInfo = mapper.readValue(notification, typeRef); - - boolean result = qonversionSandwich.handleNotification(notificationInfo); - - return result; - } catch (Exception e) { - return false; - } - } - - @Nullable - public static synchronized Map getNotificationCustomPayload(String notification) { - try { - ObjectMapper mapper = new ObjectMapper(); - - TypeReference> typeRef - = new TypeReference>() { - }; - Map notificationInfo = mapper.readValue(notification, typeRef); - - Map payload = qonversionSandwich.getNotificationCustomPayload(notificationInfo); - - return payload; - } catch (Exception e) { - return null; - } - } - - public static synchronized void subscribeOnAutomationEvents() { - automationsWrapper.subscribe(); - } - private static ResultListener getResultListener(@NotNull String methodName) { return new ResultListener() { @Override @@ -206,7 +168,7 @@ public void onSuccess(@NonNull Map data) { @Override public void onError(@NonNull SandwichError error, boolean isCancelled) { final ObjectMapper mapper = new ObjectMapper(); - final ObjectNode rootNode = createErrorNode(error); + final ObjectNode rootNode = Utils.createErrorNode(error); final JsonNode isCancelledNode = mapper.convertValue(isCancelled, JsonNode.class); rootNode.set("isCancelled", isCancelledNode); sendMessageToUnity(rootNode, methodName); @@ -215,23 +177,11 @@ public void onError(@NonNull SandwichError error, boolean isCancelled) { } private static void handleErrorResponse(@NotNull SandwichError error, @NotNull String methodName) { - final ObjectNode rootNode = createErrorNode(error); + final ObjectNode rootNode = Utils.createErrorNode(error); sendMessageToUnity(rootNode, methodName); } - private static ObjectNode createErrorNode(@NotNull SandwichError error) { - ObjectMapper mapper = new ObjectMapper(); - ObjectNode errorNode = mapper.createObjectNode(); - errorNode.put("code", error.getCode()); - errorNode.put("description", error.getDescription()); - errorNode.put("additionalMessage", error.getAdditionalMessage()); - - ObjectNode rootNode = mapper.createObjectNode(); - rootNode.set("error", errorNode); - return rootNode; - } - private static void sendMessageToUnity(@NotNull Object objectToConvert, @NotNull String methodName) { try { messageSender.sendMessageToUnity(objectToConvert, methodName); diff --git a/Runtime/Android/Plugins/com/qonversion/unitywrapper/Utils.java b/Runtime/Android/Plugins/com/qonversion/unitywrapper/Utils.java new file mode 100644 index 0000000..987f443 --- /dev/null +++ b/Runtime/Android/Plugins/com/qonversion/unitywrapper/Utils.java @@ -0,0 +1,22 @@ +package com.qonversion.unitywrapper; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.jetbrains.annotations.NotNull; +import io.qonversion.sandwich.SandwichError; + +public class Utils { + + public static ObjectNode createErrorNode(@NotNull SandwichError error) { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode errorNode = mapper.createObjectNode(); + errorNode.put("code", error.getCode()); + errorNode.put("description", error.getDescription()); + errorNode.put("additionalMessage", error.getAdditionalMessage()); + + ObjectNode rootNode = mapper.createObjectNode(); + rootNode.set("error", errorNode); + return rootNode; + } +} diff --git a/Runtime/Android/Plugins/com/qonversion/unitywrapper/Utils.java.meta b/Runtime/Android/Plugins/com/qonversion/unitywrapper/Utils.java.meta new file mode 100644 index 0000000..a2747ed --- /dev/null +++ b/Runtime/Android/Plugins/com/qonversion/unitywrapper/Utils.java.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1b5c0dd49367425db4e808bbc38580bf +timeCreated: 1670833335 \ No newline at end of file diff --git a/Runtime/Android/QonversionWrapperAndroid.cs b/Runtime/Android/QonversionWrapperAndroid.cs index 3f29fe5..4ab59b9 100644 --- a/Runtime/Android/QonversionWrapperAndroid.cs +++ b/Runtime/Android/QonversionWrapperAndroid.cs @@ -1,6 +1,5 @@ using System; -using System.Collections.Generic; -using QonversionUnity.MiniJSON; +using JetBrains.Annotations; using UnityEngine; namespace QonversionUnity @@ -17,9 +16,9 @@ public void StoreSdkInfo(string version, string source) CallQonversion("storeSdkInfo", version, source); } - public void Launch(string projectKey, bool observerMode, string callbackName) + public void InitializeSdk(string projectKey, string launchMode, string environment, string entitlementsCacheLifetime) { - CallQonversion("launch", projectKey, observerMode, callbackName); + CallQonversion("initializeSdk", projectKey, launchMode, environment, entitlementsCacheLifetime); } public void SetDebugMode() @@ -61,29 +60,11 @@ public void SetAppleSearchAdsAttributionEnabled(bool enable) { } - public void AddAttributionData(string conversionData, AttributionSource source) + public void AddAttributionData(string conversionData, string providerName) { - string attibutionSource; - - switch (source) - { - case AttributionSource.AppsFlyer: - attibutionSource = "AppsFlyer"; - break; - case AttributionSource.Branch: - attibutionSource = "Branch"; - break; - case AttributionSource.Adjust: - attibutionSource = "Adjust"; - break; - default: - Debug.LogWarning(string.Format("[Qonversion] Not Supported AttributionSource.{0} on Android platform.", source)); - return; - } - try { - CallQonversion("attribution", conversionData, attibutionSource); + CallQonversion("attribution", conversionData, providerName); } catch (Exception e) { @@ -101,9 +82,14 @@ public void Logout() CallQonversion("logout"); } - public void CheckPermissions(string callbackName) + public void UserInfo(string callbackName) + { + CallQonversion("userInfo", callbackName); + } + + public void CheckEntitlements(string callbackName) { - CallQonversion("checkPermissions", callbackName); + CallQonversion("checkEntitlements", callbackName); } public void Purchase(string productId, string callbackName) @@ -141,29 +127,13 @@ public void Offerings(string callbackName) CallQonversion("offerings", callbackName); } - public void CheckTrialIntroEligibilityForProductIds(string productIdsJson, string callbackName) - { - CallQonversion("checkTrialIntroEligibilityForProductIds", productIdsJson, callbackName); - } - - public void SetNotificationsToken(string token) - { - CallQonversion("setNotificationsToken", token); - } - - public bool HandleNotification(string notification) - { - return CallQonversion("handleNotification", notification); - } - - public string GetNotificationCustomPayload(string notification) + public void CheckTrialIntroEligibility(string productIdsJson, string callbackName) { - return CallQonversion("getNotificationCustomPayload", notification); + CallQonversion("checkTrialIntroEligibility", productIdsJson, callbackName); } - public void SubscribeOnAutomationEvents() + public void PromoPurchase(string storeProductId, string callbackName) { - CallQonversion("subscribeOnAutomationEvents"); } private const string QonversionWrapper = "com.qonversion.unitywrapper.QonversionWrapper"; @@ -183,14 +153,5 @@ private static void CallQonversion(string methodName, params object[] args) qonversion.CallStatic(methodName, args); } } - - public void PromoPurchase(string storeProductId, string callbackName) - { - } - - public void SetPermissionsCacheLifetime(string lifetime) - { - CallQonversion("setPermissionsCacheLifetime", lifetime); - } } } \ No newline at end of file diff --git a/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/.gitignore b/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/.gitignore new file mode 100644 index 0000000..27bd7eb --- /dev/null +++ b/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/.idea.Scripts.iml +/projectSettingsUpdater.xml +/contentModel.xml +/modules.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/encodings.xml b/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/indexLayout.xml b/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/vcs.xml b/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Runtime/Scripts/Automations.cs b/Runtime/Scripts/Automations.cs index c9c464a..840b500 100644 --- a/Runtime/Scripts/Automations.cs +++ b/Runtime/Scripts/Automations.cs @@ -1,17 +1,39 @@ -using UnityEngine; +using System; +using JetBrains.Annotations; namespace QonversionUnity { - public partial class Automations : MonoBehaviour + public static class Automations { + [CanBeNull] private static IAutomations _backingInstance; + /// - /// The Automations delegate is responsible for handling in-app screens and actions when push notification is received. - /// Make sure the method is called before Qonversion.handleNotification. + /// Use this variable to get a current initialized instance of the Qonversion Automations. + /// Please, use Automations only after calling . + /// Otherwise, trying to access the variable will cause an error. /// - /// The delegate to handle automations events - public static void SetDelegate(AutomationsDelegate automationsDelegate) + /// Current initialized instance of the Qonversion Automations. + /// throws exception if Qonversion has not been initialized. + public static IAutomations GetSharedInstance() { - Qonversion.SetAutomationsDelegate(automationsDelegate); + if (_backingInstance == null) + { + try + { + Qonversion.GetSharedInstance(); + } + catch (Exception e) + { + throw new Exception("Qonversion has not been initialized. " + + "Automations should be used after Qonversion is initialized."); + } + + _backingInstance = AutomationsInternal.CreateInstance(); + } + + return _backingInstance; } + + public delegate void OnShowScreenResponseReceived(QonversionError error); } } diff --git a/Runtime/Scripts/Models.meta b/Runtime/Scripts/Dto.meta similarity index 100% rename from Runtime/Scripts/Models.meta rename to Runtime/Scripts/Dto.meta diff --git a/Runtime/Scripts/Models/ActionResult.cs b/Runtime/Scripts/Dto/ActionResult.cs similarity index 100% rename from Runtime/Scripts/Models/ActionResult.cs rename to Runtime/Scripts/Dto/ActionResult.cs diff --git a/Runtime/Scripts/Models/ActionResult.cs.meta b/Runtime/Scripts/Dto/ActionResult.cs.meta similarity index 100% rename from Runtime/Scripts/Models/ActionResult.cs.meta rename to Runtime/Scripts/Dto/ActionResult.cs.meta diff --git a/Runtime/Scripts/Models/ActionResultType.cs b/Runtime/Scripts/Dto/ActionResultType.cs similarity index 100% rename from Runtime/Scripts/Models/ActionResultType.cs rename to Runtime/Scripts/Dto/ActionResultType.cs diff --git a/Runtime/Scripts/Models/ActionResultType.cs.meta b/Runtime/Scripts/Dto/ActionResultType.cs.meta similarity index 100% rename from Runtime/Scripts/Models/ActionResultType.cs.meta rename to Runtime/Scripts/Dto/ActionResultType.cs.meta diff --git a/Runtime/Scripts/Dto/AttributionProvider.cs b/Runtime/Scripts/Dto/AttributionProvider.cs new file mode 100644 index 0000000..2041fce --- /dev/null +++ b/Runtime/Scripts/Dto/AttributionProvider.cs @@ -0,0 +1,11 @@ +namespace QonversionUnity +{ + public enum AttributionProvider + { + AppsFlyer = 0, + Branch, + Adjust, + AppleSearchAds, // ios only + AppleAdServices // ios only + } +} \ No newline at end of file diff --git a/Runtime/Scripts/Models/AttributionSource.cs.meta b/Runtime/Scripts/Dto/AttributionProvider.cs.meta similarity index 100% rename from Runtime/Scripts/Models/AttributionSource.cs.meta rename to Runtime/Scripts/Dto/AttributionProvider.cs.meta diff --git a/Runtime/Scripts/AutomationsDelegate.cs b/Runtime/Scripts/Dto/AutomationsDelegate.cs similarity index 91% rename from Runtime/Scripts/AutomationsDelegate.cs rename to Runtime/Scripts/Dto/AutomationsDelegate.cs index 0c569ae..566bb3a 100644 --- a/Runtime/Scripts/AutomationsDelegate.cs +++ b/Runtime/Scripts/Dto/AutomationsDelegate.cs @@ -28,7 +28,7 @@ public abstract class AutomationsDelegate : MonoBehaviour /// /// Called when Automations flow finishes executing an action /// For instance, if the user made a purchase then action.type == QONActionResultTypePurchase - /// Then you can use the method to get available permissions + /// Then you can use the method to get available permissions /// /// executed action public abstract void OnAutomationsActionFinished(ActionResult actionResult); diff --git a/Runtime/Scripts/AutomationsDelegate.cs.meta b/Runtime/Scripts/Dto/AutomationsDelegate.cs.meta similarity index 100% rename from Runtime/Scripts/AutomationsDelegate.cs.meta rename to Runtime/Scripts/Dto/AutomationsDelegate.cs.meta diff --git a/Runtime/Scripts/Models/AutomationsEvent.cs b/Runtime/Scripts/Dto/AutomationsEvent.cs similarity index 100% rename from Runtime/Scripts/Models/AutomationsEvent.cs rename to Runtime/Scripts/Dto/AutomationsEvent.cs diff --git a/Runtime/Scripts/Models/AutomationsEvent.cs.meta b/Runtime/Scripts/Dto/AutomationsEvent.cs.meta similarity index 100% rename from Runtime/Scripts/Models/AutomationsEvent.cs.meta rename to Runtime/Scripts/Dto/AutomationsEvent.cs.meta diff --git a/Runtime/Scripts/Models/AutomationsEventType.cs b/Runtime/Scripts/Dto/AutomationsEventType.cs similarity index 100% rename from Runtime/Scripts/Models/AutomationsEventType.cs rename to Runtime/Scripts/Dto/AutomationsEventType.cs diff --git a/Runtime/Scripts/Models/AutomationsEventType.cs.meta b/Runtime/Scripts/Dto/AutomationsEventType.cs.meta similarity index 100% rename from Runtime/Scripts/Models/AutomationsEventType.cs.meta rename to Runtime/Scripts/Dto/AutomationsEventType.cs.meta diff --git a/Runtime/Scripts/Models/Eligibility.cs b/Runtime/Scripts/Dto/Eligibility.cs similarity index 100% rename from Runtime/Scripts/Models/Eligibility.cs rename to Runtime/Scripts/Dto/Eligibility.cs diff --git a/Runtime/Scripts/Models/Eligibility.cs.meta b/Runtime/Scripts/Dto/Eligibility.cs.meta similarity index 100% rename from Runtime/Scripts/Models/Eligibility.cs.meta rename to Runtime/Scripts/Dto/Eligibility.cs.meta diff --git a/Runtime/Scripts/Models/EligibilityStatus.cs b/Runtime/Scripts/Dto/EligibilityStatus.cs similarity index 100% rename from Runtime/Scripts/Models/EligibilityStatus.cs rename to Runtime/Scripts/Dto/EligibilityStatus.cs diff --git a/Runtime/Scripts/Models/EligibilityStatus.cs.meta b/Runtime/Scripts/Dto/EligibilityStatus.cs.meta similarity index 100% rename from Runtime/Scripts/Models/EligibilityStatus.cs.meta rename to Runtime/Scripts/Dto/EligibilityStatus.cs.meta diff --git a/Runtime/Scripts/Models/Permission.cs b/Runtime/Scripts/Dto/Entitlement.cs similarity index 52% rename from Runtime/Scripts/Models/Permission.cs rename to Runtime/Scripts/Dto/Entitlement.cs index ecde528..5c3ccc3 100644 --- a/Runtime/Scripts/Models/Permission.cs +++ b/Runtime/Scripts/Dto/Entitlement.cs @@ -4,21 +4,21 @@ namespace QonversionUnity { - public class Permission + public class Entitlement { - /// Qonversion Permission ID, like premium. - [Tooltip("Create Permission: https://qonversion.io/docs/create-permission")] - public readonly string PermissionID; + /// Qonversion Entitlement ID, like premium. + [Tooltip("Create Entitlement: https://qonversion.io/docs/create-permission")] + public readonly string Id; /// Product ID created in Qonversion Dashboard. [Tooltip("Create Products: https://qonversion.io/docs/create-products")] - public readonly string ProductID; + public readonly string ProductId; - /// A renew state for an associate product that unlocked permission - public readonly QProductRenewState RenewState; + /// A renew state for an associate product that unlocked entitlement + public readonly QEntitlementRenewState RenewState; - /// A source determining where this permission is originally from - App Store, Play Store, Stripe, etc. - public readonly QPermissionSource Source; + /// A source determining where this entitlement is originally from - App Store, Play Store, Stripe, etc. + public readonly QEntitlementSource Source; /// Purchase date public readonly DateTime StartedDate; @@ -26,17 +26,17 @@ public class Permission /// Expiration date for subscription public readonly DateTime? ExpirationDate; - /// Use for checking permission for current user. + /// Use for checking entitlement for current user. /// Pay attention, isActive == true does not mean that subscription is renewable. - /// Subscription could be canceled, but the user could still have a permission + /// Subscription could be canceled, but the user could still have a entitlement public readonly bool IsActive; - public Permission(Dictionary dict) + public Entitlement(Dictionary dict) { - if (dict.TryGetValue("id", out object value)) PermissionID = value as string; - if (dict.TryGetValue("associatedProduct", out value)) ProductID = value as string; + if (dict.TryGetValue("id", out object value)) Id = value as string; + if (dict.TryGetValue("productId", out value)) ProductId = value as string; if (dict.TryGetValue("renewState", out value)) RenewState = FormatRenewState(value); - Source = dict.TryGetValue("source", out value) ? FormatPermissionSource(value) : QPermissionSource.Unknown; + Source = dict.TryGetValue("source", out value) ? FormatEntitlementSource(value) : QEntitlementSource.Unknown; if (dict.TryGetValue("active", out value)) IsActive = (bool)value; if (dict.TryGetValue("startedTimestamp", out value)) StartedDate = FormatDate(value); if (dict.TryGetValue("expirationTimestamp", out value) && value != null) ExpirationDate = FormatDate(value); @@ -44,8 +44,8 @@ public Permission(Dictionary dict) public override string ToString() { - return $"{nameof(PermissionID)}: {PermissionID}, " + - $"{nameof(ProductID)}: {ProductID}, " + + return $"{nameof(Id)}: {Id}, " + + $"{nameof(ProductId)}: {ProductId}, " + $"{nameof(RenewState)}: {RenewState}, " + $"{nameof(Source)}: {Source}, " + $"{nameof(StartedDate)}: {StartedDate}, " + @@ -61,17 +61,41 @@ private DateTime FormatDate(object time) { return Utils.FormatDate((long) time); } - private QProductRenewState FormatRenewState(object renewState) => - (QProductRenewState)Convert.ToInt32(renewState); + private QEntitlementRenewState FormatRenewState(object renewState) + { + string value = renewState as string; + QEntitlementRenewState result; + switch (value) + { + case "non_renewable": + result = QEntitlementRenewState.NonRenewable; + break; + case "will_renew": + result = QEntitlementRenewState.WillRenew; + break; + case "canceled": + result = QEntitlementRenewState.Canceled; + break; + case "billing_issue": + result = QEntitlementRenewState.BillingIssue; + break; + default: + result = QEntitlementRenewState.Unknown; + break; + } + + return result; + } - private QPermissionSource FormatPermissionSource(object source) { - return Enum.TryParse(source.ToString(), out QPermissionSource parsedSource) + private QEntitlementSource FormatEntitlementSource(object source) + { + return Enum.TryParse(source.ToString(), out QEntitlementSource parsedSource) ? parsedSource - : QPermissionSource.Unknown; + : QEntitlementSource.Unknown; } } - public enum QProductRenewState + public enum QEntitlementRenewState { /// For in-app purchases. NonRenewable = -1, @@ -87,7 +111,7 @@ public enum QProductRenewState BillingIssue = 3 } - public enum QPermissionSource + public enum QEntitlementSource { Unknown, AppStore, diff --git a/Runtime/Scripts/Models/Permission.cs.meta b/Runtime/Scripts/Dto/Entitlement.cs.meta similarity index 100% rename from Runtime/Scripts/Models/Permission.cs.meta rename to Runtime/Scripts/Dto/Entitlement.cs.meta diff --git a/Runtime/Scripts/Dto/EntitlementsCacheLifetime.cs b/Runtime/Scripts/Dto/EntitlementsCacheLifetime.cs new file mode 100644 index 0000000..b9c4593 --- /dev/null +++ b/Runtime/Scripts/Dto/EntitlementsCacheLifetime.cs @@ -0,0 +1,14 @@ +namespace QonversionUnity +{ + public enum EntitlementsCacheLifetime + { + Week, + TwoWeeks, + Month, + TwoMonths, + ThreeMonths, + SixMonths, + Year, + Unlimited + } +} \ No newline at end of file diff --git a/Runtime/Scripts/Models/PermissionsCacheLifetime.cs.meta b/Runtime/Scripts/Dto/EntitlementsCacheLifetime.cs.meta similarity index 100% rename from Runtime/Scripts/Models/PermissionsCacheLifetime.cs.meta rename to Runtime/Scripts/Dto/EntitlementsCacheLifetime.cs.meta diff --git a/Runtime/Scripts/Dto/Environment.cs b/Runtime/Scripts/Dto/Environment.cs new file mode 100644 index 0000000..f28363b --- /dev/null +++ b/Runtime/Scripts/Dto/Environment.cs @@ -0,0 +1,8 @@ +namespace QonversionUnity +{ + public enum Environment + { + Sandbox, + Production + } +} diff --git a/Runtime/Scripts/Dto/Environment.cs.meta b/Runtime/Scripts/Dto/Environment.cs.meta new file mode 100644 index 0000000..417ae4e --- /dev/null +++ b/Runtime/Scripts/Dto/Environment.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1b02fbe89ab349a59491d47e9ca2329d +timeCreated: 1668682691 \ No newline at end of file diff --git a/Runtime/Scripts/Dto/LaunchMode.cs b/Runtime/Scripts/Dto/LaunchMode.cs new file mode 100644 index 0000000..b847756 --- /dev/null +++ b/Runtime/Scripts/Dto/LaunchMode.cs @@ -0,0 +1,8 @@ +namespace QonversionUnity +{ + public enum LaunchMode + { + Analytics, + SubscriptionManagement + } +} \ No newline at end of file diff --git a/Runtime/Scripts/Dto/LaunchMode.cs.meta b/Runtime/Scripts/Dto/LaunchMode.cs.meta new file mode 100644 index 0000000..82beaa8 --- /dev/null +++ b/Runtime/Scripts/Dto/LaunchMode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 24dcbe0f097a40c59733cfbd46312398 +timeCreated: 1668682749 \ No newline at end of file diff --git a/Runtime/Scripts/Models/Offering.cs b/Runtime/Scripts/Dto/Offering.cs similarity index 95% rename from Runtime/Scripts/Models/Offering.cs rename to Runtime/Scripts/Dto/Offering.cs index e47490b..d6e5b0a 100644 --- a/Runtime/Scripts/Models/Offering.cs +++ b/Runtime/Scripts/Dto/Offering.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using JetBrains.Annotations; @@ -39,7 +39,8 @@ public override string ToString() public enum QOfferingTag { - None, - Main + Unknown = -1, + None = 0, + Main = 1 } } \ No newline at end of file diff --git a/Runtime/Scripts/Models/Offering.cs.meta b/Runtime/Scripts/Dto/Offering.cs.meta similarity index 100% rename from Runtime/Scripts/Models/Offering.cs.meta rename to Runtime/Scripts/Dto/Offering.cs.meta diff --git a/Runtime/Scripts/Models/Offerings.cs b/Runtime/Scripts/Dto/Offerings.cs similarity index 100% rename from Runtime/Scripts/Models/Offerings.cs rename to Runtime/Scripts/Dto/Offerings.cs diff --git a/Runtime/Scripts/Models/Offerings.cs.meta b/Runtime/Scripts/Dto/Offerings.cs.meta similarity index 100% rename from Runtime/Scripts/Models/Offerings.cs.meta rename to Runtime/Scripts/Dto/Offerings.cs.meta diff --git a/Runtime/Scripts/Models/Product.cs b/Runtime/Scripts/Dto/Product.cs similarity index 100% rename from Runtime/Scripts/Models/Product.cs rename to Runtime/Scripts/Dto/Product.cs diff --git a/Runtime/Scripts/Models/Product.cs.meta b/Runtime/Scripts/Dto/Product.cs.meta similarity index 100% rename from Runtime/Scripts/Models/Product.cs.meta rename to Runtime/Scripts/Dto/Product.cs.meta diff --git a/Runtime/Scripts/Models/ProrationMode.cs b/Runtime/Scripts/Dto/ProrationMode.cs similarity index 82% rename from Runtime/Scripts/Models/ProrationMode.cs rename to Runtime/Scripts/Dto/ProrationMode.cs index 707c3dd..5176a56 100644 --- a/Runtime/Scripts/Models/ProrationMode.cs +++ b/Runtime/Scripts/Dto/ProrationMode.cs @@ -9,7 +9,7 @@ public enum ProrationMode ImmediateAndChargeProratedPrice, /// Replacement takes effect immediately, and the new price will be charged on next recurrence time. ImmediateWithoutProration, - /// Replacement takes effect when the old plan expires, and the new price will be charged at the same time. + /// Replacement takes effect when the old plan expires, and the new price will be charged at the same time. Deferred } } \ No newline at end of file diff --git a/Runtime/Scripts/Models/ProrationMode.cs.meta b/Runtime/Scripts/Dto/ProrationMode.cs.meta similarity index 100% rename from Runtime/Scripts/Models/ProrationMode.cs.meta rename to Runtime/Scripts/Dto/ProrationMode.cs.meta diff --git a/Runtime/Scripts/Models/QonversionError.cs b/Runtime/Scripts/Dto/QonversionError.cs similarity index 100% rename from Runtime/Scripts/Models/QonversionError.cs rename to Runtime/Scripts/Dto/QonversionError.cs diff --git a/Runtime/Scripts/Models/QonversionError.cs.meta b/Runtime/Scripts/Dto/QonversionError.cs.meta similarity index 100% rename from Runtime/Scripts/Models/QonversionError.cs.meta rename to Runtime/Scripts/Dto/QonversionError.cs.meta diff --git a/Runtime/Scripts/Models/SkProduct.meta b/Runtime/Scripts/Dto/SkProduct.meta similarity index 100% rename from Runtime/Scripts/Models/SkProduct.meta rename to Runtime/Scripts/Dto/SkProduct.meta diff --git a/Runtime/Scripts/Models/SkProduct/SKProduct.cs b/Runtime/Scripts/Dto/SkProduct/SKProduct.cs similarity index 100% rename from Runtime/Scripts/Models/SkProduct/SKProduct.cs rename to Runtime/Scripts/Dto/SkProduct/SKProduct.cs diff --git a/Runtime/Scripts/Models/SkProduct/SKProduct.cs.meta b/Runtime/Scripts/Dto/SkProduct/SKProduct.cs.meta similarity index 100% rename from Runtime/Scripts/Models/SkProduct/SKProduct.cs.meta rename to Runtime/Scripts/Dto/SkProduct/SKProduct.cs.meta diff --git a/Runtime/Scripts/Models/SkProduct/SKProductDiscount.cs b/Runtime/Scripts/Dto/SkProduct/SKProductDiscount.cs similarity index 100% rename from Runtime/Scripts/Models/SkProduct/SKProductDiscount.cs rename to Runtime/Scripts/Dto/SkProduct/SKProductDiscount.cs diff --git a/Runtime/Scripts/Models/SkProduct/SKProductDiscount.cs.meta b/Runtime/Scripts/Dto/SkProduct/SKProductDiscount.cs.meta similarity index 100% rename from Runtime/Scripts/Models/SkProduct/SKProductDiscount.cs.meta rename to Runtime/Scripts/Dto/SkProduct/SKProductDiscount.cs.meta diff --git a/Runtime/Scripts/Models/SkProduct/SKProductSubscriptionPeriod.cs b/Runtime/Scripts/Dto/SkProduct/SKProductSubscriptionPeriod.cs similarity index 100% rename from Runtime/Scripts/Models/SkProduct/SKProductSubscriptionPeriod.cs rename to Runtime/Scripts/Dto/SkProduct/SKProductSubscriptionPeriod.cs diff --git a/Runtime/Scripts/Models/SkProduct/SKProductSubscriptionPeriod.cs.meta b/Runtime/Scripts/Dto/SkProduct/SKProductSubscriptionPeriod.cs.meta similarity index 100% rename from Runtime/Scripts/Models/SkProduct/SKProductSubscriptionPeriod.cs.meta rename to Runtime/Scripts/Dto/SkProduct/SKProductSubscriptionPeriod.cs.meta diff --git a/Runtime/Scripts/Models/SkuDetails.cs b/Runtime/Scripts/Dto/SkuDetails.cs similarity index 99% rename from Runtime/Scripts/Models/SkuDetails.cs rename to Runtime/Scripts/Dto/SkuDetails.cs index b943373..ed4a94b 100644 --- a/Runtime/Scripts/Models/SkuDetails.cs +++ b/Runtime/Scripts/Dto/SkuDetails.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace QonversionUnity diff --git a/Runtime/Scripts/Models/SkuDetails.cs.meta b/Runtime/Scripts/Dto/SkuDetails.cs.meta similarity index 100% rename from Runtime/Scripts/Models/SkuDetails.cs.meta rename to Runtime/Scripts/Dto/SkuDetails.cs.meta diff --git a/Runtime/Scripts/Dto/User.cs b/Runtime/Scripts/Dto/User.cs new file mode 100644 index 0000000..ff8e9e3 --- /dev/null +++ b/Runtime/Scripts/Dto/User.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace QonversionUnity +{ + public class User + { + public readonly string QonversionId; + [CanBeNull] public readonly string IdentityId; + + public User(string qonversionId, [CanBeNull] string identityId) + { + QonversionId = qonversionId; + IdentityId = identityId; + } + + public User(Dictionary dict) + { + if (dict.TryGetValue("qonversionId", out var qonversionId) && qonversionId != null) + { + QonversionId = qonversionId as string; + } + + if (dict.TryGetValue("identityId", out var identityId) && identityId != null) + { + IdentityId = identityId as string; + } + } + + public override string ToString() + { + return $"{nameof(QonversionId)}: {QonversionId}, " + + $"{nameof(IdentityId)}: {IdentityId}"; + } + } +} diff --git a/Runtime/Scripts/Dto/User.cs.meta b/Runtime/Scripts/Dto/User.cs.meta new file mode 100644 index 0000000..7eda00b --- /dev/null +++ b/Runtime/Scripts/Dto/User.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e90e3bc36aae4e069c0c373e53427b0c +timeCreated: 1668747828 \ No newline at end of file diff --git a/Runtime/Scripts/Models/UserProperty.cs b/Runtime/Scripts/Dto/UserProperty.cs similarity index 66% rename from Runtime/Scripts/Models/UserProperty.cs rename to Runtime/Scripts/Dto/UserProperty.cs index 6a569c8..46047a0 100644 --- a/Runtime/Scripts/Models/UserProperty.cs +++ b/Runtime/Scripts/Dto/UserProperty.cs @@ -4,12 +4,13 @@ public enum UserProperty { Email, Name, + KochavaDeviceId, AppsFlyerUserId, AdjustAdId, - KochavaDeviceId, CustomUserId, - FacebookAttribution, + FacebookAttribution, // Android only FirebaseAppInstanceId, - AppSetId + AppSetId, // Android only + AdvertisingId, // iOS only } } \ No newline at end of file diff --git a/Runtime/Scripts/Models/UserProperty.cs.meta b/Runtime/Scripts/Dto/UserProperty.cs.meta similarity index 100% rename from Runtime/Scripts/Models/UserProperty.cs.meta rename to Runtime/Scripts/Dto/UserProperty.cs.meta diff --git a/Runtime/Scripts/IAutomations.cs b/Runtime/Scripts/IAutomations.cs new file mode 100644 index 0000000..29d97aa --- /dev/null +++ b/Runtime/Scripts/IAutomations.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace QonversionUnity +{ + public interface IAutomations + { + /// + /// The Automations delegate is responsible for handling in-app screens and actions when push notification is received. + /// Make sure the method is called before Qonversion.handleNotification. + /// + /// The delegate to handle automations events + public void SetDelegate(AutomationsDelegate automationsDelegate); + + /// + /// Set push token to Qonversion to enable Qonversion push notifications + /// + /// Firebase device token for Android. APNs device token for iOS. + public void SetNotificationsToken(string token); + + /// + /// Call to handle push notifications sent by Qonversion Automations. + /// + /// notification payload data + /// true when a push notification was received from Qonversion. Otherwise, returns false, so you need to handle the notification yourself + /// Firebase RemoteMessage data + /// APNs notification data + public bool HandleNotification(Dictionary notification); + + /// + /// Get parsed custom payload, which you added to the notification in the dashboard + /// + /// notification payload data + /// a map with custom payload from the notification or null if it's not provided + [CanBeNull] + public Dictionary GetNotificationCustomPayload(Dictionary notification); + + /// + /// Show the screen using its ID. + /// + /// identifier of the screen which must be shown + /// callback that will be called when response is received + public void ShowScreen(string screenId, Automations.OnShowScreenResponseReceived callback); + } +} diff --git a/Runtime/Scripts/IAutomations.cs.meta b/Runtime/Scripts/IAutomations.cs.meta new file mode 100644 index 0000000..24849f2 --- /dev/null +++ b/Runtime/Scripts/IAutomations.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1bf6adea119149b5a8575fd688405c1d +timeCreated: 1670849785 \ No newline at end of file diff --git a/Runtime/Scripts/IQonversion.cs b/Runtime/Scripts/IQonversion.cs new file mode 100644 index 0000000..6536a31 --- /dev/null +++ b/Runtime/Scripts/IQonversion.cs @@ -0,0 +1,208 @@ +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace QonversionUnity +{ + public interface IQonversion + { + /// + /// This event will be fired when a user initiates a promotional in-app purchase from the App Store. + /// Declare a delegate for the event. + /// If you are not using the PromoPurchasesReceived event promo purchases will proceed automatically. + /// + public event Qonversion.OnPromoPurchasesReceived PromoPurchasesReceived; + + /// + /// This event will be fired for each asynchronous entitlements update, + /// for example, when a deferred transaction happens. + /// + public event Qonversion.OnUpdatedEntitlementsReceived UpdatedEntitlementsReceived; + + /// + /// Make a purchase and validate it through server-to-server using Qonversion's Backend. + /// + /// Qonversion product identifier for purchase. + /// Callback that will be called when response is received. + /// + public void Purchase(string productId, Qonversion.OnPurchaseResultReceived callback); + + /// + /// Make a purchase and validate it through server-to-server using Qonversion's Backend. + /// + /// Qonversion product for purchase. + /// Callback that will be called when response is received. + /// + public void PurchaseProduct([NotNull] Product product, Qonversion.OnPurchaseResultReceived callback); + + /// + /// Update (upgrade/downgrade) subscription and validate it through server-to-server using Qonversion's Backend. + /// + /// Qonversion product identifier for purchase + /// Qonversion product identifier from which the upgrade/downgrade will be initialized + /// Callback that will be called when response is received + /// Proration Mode + /// Proration Mode + /// Update Purchase + public void UpdatePurchase( + string productId, + string oldProductId, + Qonversion.OnPurchaseResultReceived callback, + ProrationMode prorationMode = ProrationMode.UnknownSubscriptionUpgradeDowngradePolicy + ); + + /// + /// Update (upgrade/downgrade) subscription and validate it through server-to-server using Qonversion's Backend. + /// + /// Qonversion product for purchase + /// Qonversion product identifier from which the upgrade/downgrade will be initialized + /// Callback that will be called when response is received + /// Proration Mode + /// Proration Mode + /// Update Purchase + public void UpdatePurchaseWithProduct( + [NotNull] Product product, + string oldProductId, + Qonversion.OnPurchaseResultReceived callback, + ProrationMode prorationMode = ProrationMode.UnknownSubscriptionUpgradeDowngradePolicy + ); + + /// + /// Returns Qonversion products in association with Apple and Google Play Store Products. + /// + /// Callback that will be called when response is received. + /// Product Center + public void Products(Qonversion.OnProductsReceived callback); + + /// + /// Return Qonversion Offerings Object. + /// + /// An offering is a group of products that you can offer to a user on a given paywall based on your business logic. + /// For example, you can offer one set of products on a paywall immediately after onboarding and another + /// set of products with discounts later on if a user has not converted. + /// Offerings allow changing the products offered remotely without releasing app updates. + /// + /// Offerings + /// Product Center + public void Offerings(Qonversion.OnOfferingsReceived callback); + + /// + /// You can check if a user is eligible for an introductory offer, including a free trial. + /// You can show only a regular price for users who are not eligible for an introductory offer. + /// + /// Products identifiers that must be checked. + /// Callback that will be called when response is received + public void CheckTrialIntroEligibility(IList productIds, Qonversion.OnEligibilitiesReceived callback); + + /// + /// You need to call the CheckEntitlements method at the start of your app to check if a user has the required + /// entitlement. + /// + /// This method will check the user receipt and will return the current entitlements. + /// + /// If Apple or Google servers are not responding at the time of the request, Qonversion provides the latest + /// entitlements data from its database. + /// + /// Callback that will be called when response is received + public void CheckEntitlements(Qonversion.OnEntitlementsReceived callback); + + /// + /// Restoring purchases restores users purchases in your app, to maintain access to purchased content. + /// Users sometimes need to restore purchased content, such as when they upgrade to a new phone. + /// + /// Callback that will be called when response is received + public void Restore(Qonversion.OnEntitlementsReceived callback); + + /// + /// This method will send all purchases to the Qonversion backend. Call this every time when purchase is handled + /// by your own implementation. + /// + /// //////Warning!////// + /// + /// This method works for Android only. + /// It should only be called if you're using Qonversion SDK in observer mode. + /// + /// Observer mode for Android SDK + public void SyncPurchases(); + + /// + /// Call this function to link a user to his unique ID in your system and share purchase data. + /// + /// An unique user ID in your system. + /// + public void Identify(string userID); + + /// + /// Call this function to unlink a user from his unique ID in your system and his purchase data. + /// + /// + public void Logout(); + + /// + /// This method returns information about the current Qonversion user. + /// + /// Callback that will be called when response is received + public void UserInfo(Qonversion.OnUserInfoReceived callback); + + /// + /// Sends your attribution data to the attribution source. + /// + /// An object containing your attribution data. + /// The attribution source to which the data will be sent. + public void Attribution( + Dictionary conversionData, + AttributionProvider attributionProvider + ); + + /// + /// Sends your attribution data to the attribution source. + /// + /// A json string containing your attribution data. + /// The attribution source to which the data will be sent. + public void Attribution(string conversionData, AttributionProvider attributionProvider); + + /// + /// Sets user property for pre-defined case property. + /// + /// User properties are attributes you can set on a user level. + /// You can send user properties to third party platforms as well as use them in Qonversion for customer segmentation + /// and analytics. + /// + /// Defined enum key that will be transformed to string. + /// Property value. + /// User Properties + public void SetProperty(UserProperty key, string value); + + /// + /// Adds custom user property. + /// + /// User properties are attributes you can set on a user level. + /// You can send user properties to third party platforms as well as use them in Qonversion for customer segmentation + /// and analytics. + /// + /// Custom user property key. + /// Property value. + /// User Properties + public void SetUserProperty(string key, string value); + + /// + /// iOS only. + /// On iOS 14.5+, after requesting the app tracking entitlement using ATT, you need to notify Qonversion if tracking + /// is allowed and IDFA is available. + /// + public void CollectAdvertisingId(); + + /// + /// Collecting Apple Search Ads attribution data. + /// + /// + public void CollectAppleSearchAdsAttribution(); + + /// + /// iOS only. + /// On iOS 14.0+ shows up a sheet for users to redeem AppStore offer codes. + /// + public void PresentCodeRedemptionSheet(); + + internal void InitializeInstance(QonversionConfig config); + } +} diff --git a/Runtime/Scripts/IQonversion.cs.meta b/Runtime/Scripts/IQonversion.cs.meta new file mode 100644 index 0000000..4c29c8a --- /dev/null +++ b/Runtime/Scripts/IQonversion.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9ded0a1938a14b2788563e72c5f7fbd6 +timeCreated: 1670849923 \ No newline at end of file diff --git a/Runtime/Scripts/IQonversionResultHandler.cs b/Runtime/Scripts/IQonversionResultHandler.cs deleted file mode 100644 index b057ae2..0000000 --- a/Runtime/Scripts/IQonversionResultHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace QonversionUnity -{ - internal interface IQonversionResultHandler - { - void onSuccessInit(string uid); - - void onErrorInit(string errorMessage); - } -} \ No newline at end of file diff --git a/Runtime/Scripts/IQonversionResultHandler.cs.meta b/Runtime/Scripts/IQonversionResultHandler.cs.meta deleted file mode 100644 index 9e1310e..0000000 --- a/Runtime/Scripts/IQonversionResultHandler.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0da42bd95a3b8ca4087c7fd255c437d5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Scripts/InitDelegate.cs b/Runtime/Scripts/InitDelegate.cs deleted file mode 100644 index c440e68..0000000 --- a/Runtime/Scripts/InitDelegate.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace QonversionUnity -{ - /// - /// Init delegate. - /// - public delegate void InitDelegate(); -} \ No newline at end of file diff --git a/Runtime/Scripts/InitEvent.cs b/Runtime/Scripts/InitEvent.cs deleted file mode 100644 index 36cb04e..0000000 --- a/Runtime/Scripts/InitEvent.cs +++ /dev/null @@ -1,8 +0,0 @@ -using UnityEngine.Events; - -namespace QonversionUnity -{ - [System.Serializable] - public class InitEvent : UnityEvent - {} -} \ No newline at end of file diff --git a/Runtime/Scripts/InitEvent.cs.meta b/Runtime/Scripts/InitEvent.cs.meta deleted file mode 100644 index ec73118..0000000 --- a/Runtime/Scripts/InitEvent.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e3083807ce0ef5d488edcd762c9afa93 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Scripts/Internal.meta b/Runtime/Scripts/Internal.meta new file mode 100644 index 0000000..43a7970 --- /dev/null +++ b/Runtime/Scripts/Internal.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 00384c60219c4bda98b08e4f7c65bc6f +timeCreated: 1668672384 \ No newline at end of file diff --git a/Runtime/Scripts/Internal/AutomationsInternal.cs b/Runtime/Scripts/Internal/AutomationsInternal.cs new file mode 100644 index 0000000..e10235f --- /dev/null +++ b/Runtime/Scripts/Internal/AutomationsInternal.cs @@ -0,0 +1,161 @@ +using System.Collections.Generic; +using QonversionUnity.MiniJSON; +using UnityEngine; + +namespace QonversionUnity +{ + internal class AutomationsInternal : MonoBehaviour, IAutomations + { + private const string GameObjectName = "QonvesrionAutomationsRuntimeGameObject"; + private const string OnShowScreenMethodName = "OnShowScreen"; + + private IAutomationsWrapper _nativeWrapperInstance; + private AutomationsDelegate _automationsDelegate; + + private Automations.OnShowScreenResponseReceived ShowScreenResponseReceivedCallback { get; set; } + + public static AutomationsInternal CreateInstance() + { + GameObject go = new GameObject(GameObjectName); + AutomationsInternal instance = go.AddComponent(); + DontDestroyOnLoad(go); + + return instance; + } + + public void SetDelegate(AutomationsDelegate automationsDelegate) + { + _automationsDelegate = automationsDelegate; + + IAutomationsWrapper instance = GetNativeWrapper(); + instance.SubscribeOnAutomationEvents(); + } + + public void SetNotificationsToken(string token) + { + IAutomationsWrapper instance = GetNativeWrapper(); + instance.SetNotificationsToken(token); + } + + public bool HandleNotification(Dictionary notification) + { + IAutomationsWrapper instance = GetNativeWrapper(); + return instance.HandleNotification(notification.toJson()); + } + + public Dictionary GetNotificationCustomPayload(Dictionary notification) + { + IAutomationsWrapper instance = GetNativeWrapper(); + var payloadJson = instance.GetNotificationCustomPayload(notification.toJson()); + + if (payloadJson == null) + { + return null; + } + + if (!(Json.Deserialize(payloadJson) is Dictionary response)) + { + Debug.LogError("Could not parse custom notification payload."); + return null; + } + + return response; + } + + public void ShowScreen(string screenId, Automations.OnShowScreenResponseReceived callback) + { + ShowScreenResponseReceivedCallback = callback; + + IAutomationsWrapper instance = GetNativeWrapper(); + instance.ShowScreen(screenId, OnShowScreenMethodName); + } + + private IAutomationsWrapper GetNativeWrapper() + { + if (_nativeWrapperInstance != null) + { + return _nativeWrapperInstance; + } + + switch (Application.platform) + { + case RuntimePlatform.Android: + _nativeWrapperInstance = new AutomationsWrapperAndroid(); + break; + case RuntimePlatform.IPhonePlayer: + _nativeWrapperInstance = new AutomationsWrapperIOS(); + break; + default: + _nativeWrapperInstance = new AutomationsWrapperNoop(); + break; + } + _nativeWrapperInstance.Initialize(GameObjectName); + + return _nativeWrapperInstance; + } + + // The below methods are called from native when Automations events occur + private void OnAutomationsScreenShown(string jsonString) + { + if (_automationsDelegate == null) + { + return; + } + + string screenId = Mapper.ScreenIdFromJson(jsonString); + + _automationsDelegate.OnAutomationsScreenShown(screenId); + } + + private void OnAutomationsActionStarted(string jsonString) + { + if (_automationsDelegate == null) + { + return; + } + + ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); + _automationsDelegate.OnAutomationsActionStarted(actionResult); + } + + private void OnAutomationsActionFailed(string jsonString) + { + if (_automationsDelegate == null) + { + return; + } + + ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); + _automationsDelegate.OnAutomationsActionFailed(actionResult); + } + + + private void OnAutomationsActionFinished(string jsonString) + { + if (_automationsDelegate == null) + { + return; + } + + ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); + _automationsDelegate.OnAutomationsActionFinished(actionResult); + } + + private void OnAutomationsFinished(string jsonString) + { + if (_automationsDelegate == null) + { + return; + } + + _automationsDelegate.OnAutomationsFinished(); + } + + private void OnShowScreen(string jsonString) + { + var error = Mapper.ErrorFromJson(jsonString); + ShowScreenResponseReceivedCallback(error); + ShowScreenResponseReceivedCallback = null; + } + } +} diff --git a/Runtime/Scripts/Internal/AutomationsInternal.cs.meta b/Runtime/Scripts/Internal/AutomationsInternal.cs.meta new file mode 100644 index 0000000..e936d9f --- /dev/null +++ b/Runtime/Scripts/Internal/AutomationsInternal.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c4a786ad04fb4a94b86844c34f317f23 +timeCreated: 1668753627 \ No newline at end of file diff --git a/Runtime/Scripts/Constants.cs b/Runtime/Scripts/Internal/Constants.cs similarity index 73% rename from Runtime/Scripts/Constants.cs rename to Runtime/Scripts/Internal/Constants.cs index 67b0cfc..e3bea8f 100644 --- a/Runtime/Scripts/Constants.cs +++ b/Runtime/Scripts/Internal/Constants.cs @@ -1,6 +1,6 @@ namespace QonversionUnity { - static class Constants + internal static class Constants { public const int SkuDetailsPriceRatio = 1000000; } diff --git a/Runtime/Scripts/Constants.cs.meta b/Runtime/Scripts/Internal/Constants.cs.meta similarity index 100% rename from Runtime/Scripts/Constants.cs.meta rename to Runtime/Scripts/Internal/Constants.cs.meta diff --git a/Runtime/Scripts/Mapper.cs b/Runtime/Scripts/Internal/Mapper.cs similarity index 76% rename from Runtime/Scripts/Mapper.cs rename to Runtime/Scripts/Internal/Mapper.cs index 035baf5..42e87a9 100644 --- a/Runtime/Scripts/Mapper.cs +++ b/Runtime/Scripts/Internal/Mapper.cs @@ -7,20 +7,6 @@ namespace QonversionUnity { internal class Mapper { - internal static string GetLifetimeKey(PermissionsCacheLifetime lifetime) { - var keys = new Dictionary() { - {PermissionsCacheLifetime.WEEK, "Week"}, - {PermissionsCacheLifetime.TWO_WEEKS, "TwoWeeks"}, - {PermissionsCacheLifetime.MONTH, "Month"}, - {PermissionsCacheLifetime.TWO_MONTHS, "TwoMonths"}, - {PermissionsCacheLifetime.THREE_MONTHS, "ThreeMonths"}, - {PermissionsCacheLifetime.SIX_MONTHS, "SixMonths"}, - {PermissionsCacheLifetime.YEAR, "Year"}, - {PermissionsCacheLifetime.UNLIMITED, "Unlimited"} - }; - return keys[lifetime]; - } - internal static bool GetIsCancelledFromJson(string jsonStr) { if (!(Json.Deserialize(jsonStr) is Dictionary result)) @@ -32,22 +18,22 @@ internal static bool GetIsCancelledFromJson(string jsonStr) return result.TryGetValue("isCancelled", out var isCancelled) && Convert.ToBoolean(isCancelled); } - internal static Dictionary PermissionsFromJson(string jsonStr) + internal static Dictionary EntitlementsFromJson(string jsonStr) { - var result = new Dictionary(); + var result = new Dictionary(); - if (!(Json.Deserialize(jsonStr) is Dictionary permissions)) + if (!(Json.Deserialize(jsonStr) is Dictionary entitlements)) { - Debug.LogError("Could not parse QPermissions"); + Debug.LogError("Could not parse QEntitlements"); return result; } - foreach (KeyValuePair permissionPair in permissions) + foreach (KeyValuePair entitlementPair in entitlements) { - if (permissionPair.Value is Dictionary permissionDict) + if (entitlementPair.Value is Dictionary entitlementDict) { - Permission permission = new Permission(permissionDict); - result.Add(permissionPair.Key, permission); + Entitlement entitlement = new Entitlement(entitlementDict); + result.Add(entitlementPair.Key, entitlement); } } @@ -131,6 +117,17 @@ internal static Dictionary EligibilitiesFromJson(string jso return result; } + internal static User UserFromJson(string jsonStr) + { + if (!(Json.Deserialize(jsonStr) is Dictionary userInfo)) + { + Debug.LogError("Could not parse User"); + return new User("", null); + } + + return new User(userInfo); + } + internal static QonversionError ErrorFromJson(string jsonStr) { if (!(Json.Deserialize(jsonStr) is Dictionary dict)) return null; diff --git a/Runtime/Scripts/Mapper.cs.meta b/Runtime/Scripts/Internal/Mapper.cs.meta similarity index 100% rename from Runtime/Scripts/Mapper.cs.meta rename to Runtime/Scripts/Internal/Mapper.cs.meta diff --git a/Runtime/Scripts/Internal/QonversionInternal.cs b/Runtime/Scripts/Internal/QonversionInternal.cs new file mode 100644 index 0000000..eea0c26 --- /dev/null +++ b/Runtime/Scripts/Internal/QonversionInternal.cs @@ -0,0 +1,453 @@ +using JetBrains.Annotations; +using QonversionUnity.MiniJSON; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace QonversionUnity +{ + internal class QonversionInternal : MonoBehaviour, IQonversion + { + private const string GameObjectName = "QonvesrionRuntimeGameObject"; + private const string OnCheckEntitlementsMethodName = "OnCheckEntitlements"; + private const string OnPurchaseMethodName = "OnPurchase"; + private const string OnPromoPurchaseMethodName = "OnPromoPurchase"; + private const string OnPurchaseProductMethodName = "OnPurchaseProduct"; + private const string OnUpdatePurchaseMethodName = "OnUpdatePurchase"; + private const string OnUpdatePurchaseWithProductMethodName = "OnUpdatePurchaseWithProduct"; + private const string OnRestoreMethodName = "OnRestore"; + private const string OnProductsMethodName = "OnProducts"; + private const string OnOfferingsMethodName = "OnOfferings"; + private const string OnEligibilitiesMethodName = "OnEligibilities"; + private const string OnUserInfoMethodName = "OnUserInfo"; + + private const string SdkVersion = "4.0.0"; + private const string SdkSource = "unity"; + + private IQonversionWrapper _nativeWrapperInstance; + private Qonversion.OnUpdatedEntitlementsReceived _onUpdatedEntitlementsReceived; + + private Qonversion.OnPromoPurchasesReceived _onPromoPurchasesReceived; + private string _storedPromoProductId = null; + + private List CheckEntitlementsCallbacks { get; } = new List(); + private List RestoreCallbacks { get; } = new List(); + private Qonversion.OnPurchaseResultReceived PurchaseCallback { get; set; } + private Qonversion.OnPurchaseResultReceived PurchaseProductCallback { get; set; } + private Qonversion.OnPurchaseResultReceived UpdatePurchaseCallback { get; set; } + private Qonversion.OnPurchaseResultReceived UpdatePurchaseWithProductCallback { get; set; } + private List ProductsCallbacks { get; } = new List(); + private List OfferingsCallbacks { get; } = new List(); + private Qonversion.OnEligibilitiesReceived EligibilitiesCallback { get; set; } + private Qonversion.OnEntitlementsReceived PromoPurchaseCallback { get; set; } + private Qonversion.OnUserInfoReceived UserInfoCallback { get; set; } + + public event Qonversion.OnPromoPurchasesReceived PromoPurchasesReceived + { + add + { + _onPromoPurchasesReceived += value; + } + remove + { + _onPromoPurchasesReceived -= value; + } + } + + public event Qonversion.OnUpdatedEntitlementsReceived UpdatedEntitlementsReceived + { + add + { + _onUpdatedEntitlementsReceived += value; + } + remove + { + _onUpdatedEntitlementsReceived -= value; + } + } + + public static QonversionInternal CreateInstance() + { + GameObject go = new GameObject(GameObjectName); + QonversionInternal instance = go.AddComponent(); + DontDestroyOnLoad(go); + + return instance; + } + + void IQonversion.InitializeInstance(QonversionConfig config) + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.StoreSdkInfo(SdkVersion, SdkSource); + + string launchModeKey = Enum.GetName(typeof(LaunchMode), config.LaunchMode); + string environmentKey = Enum.GetName(typeof(Environment), config.Environment); + string cacheLifetimeKey = Enum.GetName(typeof(EntitlementsCacheLifetime), config.EntitlementsCacheLifetime); + + instance.InitializeSdk(config.ProjectKey, launchModeKey, environmentKey, cacheLifetimeKey); + } + + public void Purchase(string productId, Qonversion.OnPurchaseResultReceived callback) + { + PurchaseCallback = callback; + IQonversionWrapper instance = GetNativeWrapper(); + instance.Purchase(productId, OnPurchaseMethodName); + } + + public void PurchaseProduct([NotNull] Product product, Qonversion.OnPurchaseResultReceived callback) + { + if (product == null) + { + callback(null, new QonversionError("PurchaseInvalid", "Product is null"), false); + return; + } + + PurchaseProductCallback = callback; + IQonversionWrapper instance = GetNativeWrapper(); + instance.PurchaseProduct(product.QonversionId, product.OfferingId, OnPurchaseProductMethodName); + } + + public void UpdatePurchase(string productId, string oldProductId, Qonversion.OnPurchaseResultReceived callback, ProrationMode prorationMode = ProrationMode.UnknownSubscriptionUpgradeDowngradePolicy) + { + UpdatePurchaseCallback = callback; + IQonversionWrapper instance = GetNativeWrapper(); + instance.UpdatePurchase(productId, oldProductId, prorationMode, OnUpdatePurchaseMethodName); + } + + public void UpdatePurchaseWithProduct([NotNull] Product product, string oldProductId, Qonversion.OnPurchaseResultReceived callback, ProrationMode prorationMode = ProrationMode.UnknownSubscriptionUpgradeDowngradePolicy) + { + if (product == null) + { + callback(null, new QonversionError("PurchaseInvalid", "Product is null"), false); + return; + } + + UpdatePurchaseWithProductCallback = callback; + IQonversionWrapper instance = GetNativeWrapper(); + instance.UpdatePurchaseWithProduct(product.QonversionId, product.OfferingId, oldProductId, prorationMode, OnUpdatePurchaseWithProductMethodName); + } + + public void Products(Qonversion.OnProductsReceived callback) + { + ProductsCallbacks.Add(callback); + IQonversionWrapper instance = GetNativeWrapper(); + instance.Products(OnProductsMethodName); + } + + public void Offerings(Qonversion.OnOfferingsReceived callback) + { + OfferingsCallbacks.Add(callback); + IQonversionWrapper instance = GetNativeWrapper(); + instance.Offerings(OnOfferingsMethodName); + } + + public void CheckTrialIntroEligibility(IList productIds, Qonversion.OnEligibilitiesReceived callback) + { + var productIdsJson = Json.Serialize(productIds); + + EligibilitiesCallback = callback; + IQonversionWrapper instance = GetNativeWrapper(); + instance.CheckTrialIntroEligibility(productIdsJson, OnEligibilitiesMethodName); + } + + public void CheckEntitlements(Qonversion.OnEntitlementsReceived callback) + { + CheckEntitlementsCallbacks.Add(callback); + IQonversionWrapper instance = GetNativeWrapper(); + instance.CheckEntitlements(OnCheckEntitlementsMethodName); + } + + public void Restore(Qonversion.OnEntitlementsReceived callback) + { + RestoreCallbacks.Add(callback); + IQonversionWrapper instance = GetNativeWrapper(); + instance.Restore(OnRestoreMethodName); + } + + public void SyncPurchases() + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.SyncPurchases(); + } + + public void Identify(string userID) + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.Identify(userID); + } + + public void Logout() + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.Logout(); + } + + public void UserInfo(Qonversion.OnUserInfoReceived callback) + { + UserInfoCallback = callback; + IQonversionWrapper instance = GetNativeWrapper(); + instance.UserInfo(OnUserInfoMethodName); + } + + public void Attribution(Dictionary conversionData, AttributionProvider attributionProvider) + { + Attribution(conversionData.toJson(), attributionProvider); + } + + public void Attribution(string conversionData, AttributionProvider attributionProvider) + { + string providerName = Enum.GetName(typeof(AttributionProvider), attributionProvider); + + IQonversionWrapper instance = GetNativeWrapper(); + + instance.AddAttributionData(conversionData, providerName); + } + + public void SetProperty(UserProperty key, string value) + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.SetProperty(key, value); + } + + public void SetUserProperty(string key, string value) + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.SetUserProperty(key, value); + } + + public void CollectAdvertisingId() + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.SetAdvertisingID(); + } + + public void CollectAppleSearchAdsAttribution() + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.SetAppleSearchAdsAttributionEnabled(true); + } + + public void PresentCodeRedemptionSheet() + { + IQonversionWrapper instance = GetNativeWrapper(); + instance.PresentCodeRedemptionSheet(); + } + + // Called from the native SDK - Called when entitlements received from the checkEntitlements() method + private void OnCheckEntitlements(string jsonString) + { + HandleEntitlements(CheckEntitlementsCallbacks, jsonString); + CheckEntitlementsCallbacks.Clear(); + } + + // Called from the native SDK - Called when purchase result received from the purchase() method + private void OnPurchase(string jsonString) + { + HandlePurchaseResult(PurchaseCallback, jsonString); + PurchaseCallback = null; + } + + // Called from the native SDK - Called when purchase result received from the purchaseProduct() method + private void OnPurchaseProduct(string jsonString) + { + HandlePurchaseResult(PurchaseProductCallback, jsonString); + PurchaseProductCallback = null; + } + + // Called from the native SDK - Called when entitlements received from the restore() method + private void OnRestore(string jsonString) + { + HandleEntitlements(RestoreCallbacks, jsonString); + RestoreCallbacks.Clear(); + } + + // Called from the native SDK - Called when purchase result received from the updatePurchase() method + private void OnUpdatePurchase(string jsonString) + { + HandlePurchaseResult(UpdatePurchaseCallback, jsonString); + UpdatePurchaseCallback = null; + } + + // Called from the native SDK - Called when purchase result received from the updatePurchaseWithProduct() method + private void OnUpdatePurchaseWithProduct(string jsonString) + { + HandlePurchaseResult(UpdatePurchaseWithProductCallback, jsonString); + UpdatePurchaseWithProductCallback = null; + } + + // Called from the native SDK - Called when entitlements received from the promoPurchase() method + private void OnPromoPurchase(string jsonString) + { + if (PromoPurchaseCallback != null) { + var callbacks = new List { PromoPurchaseCallback }; + HandleEntitlements(callbacks, jsonString); + } + + PromoPurchaseCallback = null; + _storedPromoProductId = null; + } + + // Called from the native SDK - Called when products received from the products() method + private void OnProducts(string jsonString) + { + if (ProductsCallbacks.Count == 0) return; + + var error = Mapper.ErrorFromJson(jsonString); + if (error != null) + { + ProductsCallbacks.ForEach(callback => callback(null, error)); + } + else + { + var products = Mapper.ProductsFromJson(jsonString); + ProductsCallbacks.ForEach(callback => callback(products, null)); + } + + ProductsCallbacks.Clear(); + } + + // Called from the native SDK - Called when offerings received from the offerings() method + private void OnOfferings(string jsonString) + { + if (OfferingsCallbacks.Count == 0) return; + + var error = Mapper.ErrorFromJson(jsonString); + if (error != null) + { + OfferingsCallbacks.ForEach(callback => callback(null, error)); + } + else + { + var offerings = Mapper.OfferingsFromJson(jsonString); + OfferingsCallbacks.ForEach(callback => callback(offerings, null)); + } + + OfferingsCallbacks.Clear(); + } + + // Called from the native SDK - Called when eligibilities received from the checkTrialIntroEligibilityForProductIds() method + private void OnEligibilities(string jsonString) + { + if (EligibilitiesCallback == null) return; + + var error = Mapper.ErrorFromJson(jsonString); + if (error != null) + { + EligibilitiesCallback(null, error); + } + else + { + Dictionary eligibilities = Mapper.EligibilitiesFromJson(jsonString); + EligibilitiesCallback(eligibilities, null); + } + + EligibilitiesCallback = null; + } + + // Called from the native SDK - Called when user info received from the UserInfo() method + private void OnUserInfo(string jsonString) + { + if (UserInfoCallback == null) return; + + var error = Mapper.ErrorFromJson(jsonString); + if (error != null) + { + UserInfoCallback(null, error); + } + else + { + User userInfo = Mapper.UserFromJson(jsonString); + UserInfoCallback(userInfo, null); + } + + UserInfoCallback = null; + } + + // Called from the native SDK - Called when entitlements update. For example, when pending purchases like SCA, Ask to buy, etc., happen. + private void OnReceivedUpdatedEntitlements(string jsonString) + { + if (_onUpdatedEntitlementsReceived == null) + { + return; + } + + Dictionary entitlements = Mapper.EntitlementsFromJson(jsonString); + _onUpdatedEntitlementsReceived(entitlements); + } + + private void OnReceivePromoPurchase(string storeProductId) + { + if (_onPromoPurchasesReceived == null) + { + return; + } + + _storedPromoProductId = storeProductId; + _onPromoPurchasesReceived(storeProductId, PromoPurchase); + } + + private void PromoPurchase(Qonversion.OnEntitlementsReceived callback) + { + PromoPurchaseCallback = callback; + IQonversionWrapper instance = GetNativeWrapper(); + instance.PromoPurchase(_storedPromoProductId, OnPromoPurchaseMethodName); + } + + private void HandleEntitlements(List callbacks, string jsonString) + { + if (callbacks.Count == 0) return; + + var error = Mapper.ErrorFromJson(jsonString); + if (error != null) + { + callbacks.ForEach(callback => callback(null, error)); + } + else + { + var entitlements = Mapper.EntitlementsFromJson(jsonString); + callbacks.ForEach(callback => callback(entitlements, null)); + } + } + + private void HandlePurchaseResult(Qonversion.OnPurchaseResultReceived callback, string jsonString) + { + if (callback == null) return; + + var error = Mapper.ErrorFromJson(jsonString); + if (error != null) + { + var isCancelled = Mapper.GetIsCancelledFromJson(jsonString); + callback(null, error, isCancelled); + } + else + { + var entitlements = Mapper.EntitlementsFromJson(jsonString); + callback(entitlements, null, false); + } + } + + private IQonversionWrapper GetNativeWrapper() + { + if (_nativeWrapperInstance != null) + { + return _nativeWrapperInstance; + } + + switch (Application.platform) + { + case RuntimePlatform.Android: + _nativeWrapperInstance = new QonversionWrapperAndroid(); + break; + case RuntimePlatform.IPhonePlayer: + _nativeWrapperInstance = new QonversionWrapperIOS(); + break; + default: + _nativeWrapperInstance = new QonversionWrapperNoop(); + break; + } + _nativeWrapperInstance.Initialize(GameObjectName); + + return _nativeWrapperInstance; + } + } +} diff --git a/Runtime/Scripts/InitDelegate.cs.meta b/Runtime/Scripts/Internal/QonversionInternal.cs.meta similarity index 83% rename from Runtime/Scripts/InitDelegate.cs.meta rename to Runtime/Scripts/Internal/QonversionInternal.cs.meta index 3fe0152..3d73b36 100644 --- a/Runtime/Scripts/InitDelegate.cs.meta +++ b/Runtime/Scripts/Internal/QonversionInternal.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 67b89adb9ad50f74a8161204ac657b36 +guid: 38c50778583feeb4da0934f2fa914b96 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Runtime/Scripts/Utils.cs b/Runtime/Scripts/Internal/Utils.cs similarity index 100% rename from Runtime/Scripts/Utils.cs rename to Runtime/Scripts/Internal/Utils.cs diff --git a/Runtime/Scripts/Utils.cs.meta b/Runtime/Scripts/Internal/Utils.cs.meta similarity index 100% rename from Runtime/Scripts/Utils.cs.meta rename to Runtime/Scripts/Internal/Utils.cs.meta diff --git a/Runtime/Scripts/Internal/wrappers.meta b/Runtime/Scripts/Internal/wrappers.meta new file mode 100644 index 0000000..7be01f6 --- /dev/null +++ b/Runtime/Scripts/Internal/wrappers.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bc8c98aad7534db3bf2a3733e1e9b9eb +timeCreated: 1668776043 \ No newline at end of file diff --git a/Runtime/Scripts/Internal/wrappers/automations.meta b/Runtime/Scripts/Internal/wrappers/automations.meta new file mode 100644 index 0000000..5c9d6fa --- /dev/null +++ b/Runtime/Scripts/Internal/wrappers/automations.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d39ad171d37c4033a7b7a4c23c0ea18a +timeCreated: 1668776048 \ No newline at end of file diff --git a/Runtime/Scripts/Internal/wrappers/automations/AutomationsWrapperNoop.cs b/Runtime/Scripts/Internal/wrappers/automations/AutomationsWrapperNoop.cs new file mode 100644 index 0000000..8929d12 --- /dev/null +++ b/Runtime/Scripts/Internal/wrappers/automations/AutomationsWrapperNoop.cs @@ -0,0 +1,31 @@ +namespace QonversionUnity +{ + internal class AutomationsWrapperNoop : IAutomationsWrapper + { + public void Initialize(string gameObjectName) + { + } + + public void SetNotificationsToken(string token) + { + } + + public bool HandleNotification(string notification) + { + return false; + } + + public string GetNotificationCustomPayload(string notification) + { + return null; + } + + public void SubscribeOnAutomationEvents() + { + } + + public void ShowScreen(string screenId, string callbackName) + { + } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/Internal/wrappers/automations/AutomationsWrapperNoop.cs.meta b/Runtime/Scripts/Internal/wrappers/automations/AutomationsWrapperNoop.cs.meta new file mode 100644 index 0000000..cb58df1 --- /dev/null +++ b/Runtime/Scripts/Internal/wrappers/automations/AutomationsWrapperNoop.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: efc8a0074ad9d48879dfbbec563b3225 +timeCreated: 1668776080 \ No newline at end of file diff --git a/Runtime/Scripts/Internal/wrappers/automations/IAutomationsWrapper.cs b/Runtime/Scripts/Internal/wrappers/automations/IAutomationsWrapper.cs new file mode 100644 index 0000000..af52d4c --- /dev/null +++ b/Runtime/Scripts/Internal/wrappers/automations/IAutomationsWrapper.cs @@ -0,0 +1,14 @@ +using JetBrains.Annotations; + +namespace QonversionUnity +{ + internal interface IAutomationsWrapper + { + void Initialize(string gameObjectName); + void SetNotificationsToken(string token); + bool HandleNotification(string notification); + [CanBeNull] string GetNotificationCustomPayload(string notification); + void SubscribeOnAutomationEvents(); + void ShowScreen(string screenId, string callbackName); + } +} diff --git a/Runtime/Scripts/Internal/wrappers/automations/IAutomationsWrapper.cs.meta b/Runtime/Scripts/Internal/wrappers/automations/IAutomationsWrapper.cs.meta new file mode 100644 index 0000000..317587d --- /dev/null +++ b/Runtime/Scripts/Internal/wrappers/automations/IAutomationsWrapper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e55580a6da23457280c02026ad96b05d +timeCreated: 1668776004 \ No newline at end of file diff --git a/Runtime/Scripts/Internal/wrappers/qonversion.meta b/Runtime/Scripts/Internal/wrappers/qonversion.meta new file mode 100644 index 0000000..8c5f0cb --- /dev/null +++ b/Runtime/Scripts/Internal/wrappers/qonversion.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b14757828b514a959d4e299c27c50782 +timeCreated: 1668776059 \ No newline at end of file diff --git a/Runtime/Scripts/IQonversionWrapper.cs b/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs similarity index 65% rename from Runtime/Scripts/IQonversionWrapper.cs rename to Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs index 6fce157..72b9be1 100644 --- a/Runtime/Scripts/IQonversionWrapper.cs +++ b/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs @@ -5,15 +5,14 @@ namespace QonversionUnity internal interface IQonversionWrapper { void Initialize(string gameObjectName); + void InitializeSdk(string projectKey, string launchMode, [CanBeNull] string environment, [CanBeNull] string entitlementsCacheLifetime); void StoreSdkInfo(string version, string source); - void SetDebugMode(); void SetAdvertisingID(); - void Launch(string projectKey, bool observerMode, string callbackName); void SetUserProperty(string key, string value); void SetProperty(UserProperty key, string value); void SyncPurchases(); - void AddAttributionData(string conversionData, AttributionSource source); - void CheckPermissions(string callbackName); + void AddAttributionData(string conversionData, string providerName); + void CheckEntitlements(string callbackName); void Purchase(string productId, string callbackName); void PurchaseProduct(string productId, string offeringId, string callbackName); void Restore(string callbackName); @@ -21,16 +20,12 @@ internal interface IQonversionWrapper void UpdatePurchaseWithProduct(string productId, string offeringId, string oldProductId, ProrationMode prorationMode, string callbackName); void Products(string callbackName); void Offerings(string callbackName); - void CheckTrialIntroEligibilityForProductIds(string productIdsJson, string callbackName); + void CheckTrialIntroEligibility(string productIdsJson, string callbackName); void SetAppleSearchAdsAttributionEnabled(bool enable); void Identify(string userID); void Logout(); + void UserInfo(string callbackName); void PromoPurchase(string storeProductId, string callbackName); - void SetNotificationsToken(string token); - bool HandleNotification(string notification); - [CanBeNull] string GetNotificationCustomPayload(string notification); - void SubscribeOnAutomationEvents(); void PresentCodeRedemptionSheet(); - void SetPermissionsCacheLifetime(string lifetime); } } \ No newline at end of file diff --git a/Runtime/Scripts/IQonversionWrapper.cs.meta b/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs.meta similarity index 100% rename from Runtime/Scripts/IQonversionWrapper.cs.meta rename to Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs.meta diff --git a/Runtime/Scripts/QonversionWrapperNoop.cs b/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs similarity index 67% rename from Runtime/Scripts/QonversionWrapperNoop.cs rename to Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs index 58cb925..d27f65e 100644 --- a/Runtime/Scripts/QonversionWrapperNoop.cs +++ b/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs @@ -1,15 +1,12 @@ namespace QonversionUnity - { +{ internal class QonversionWrapperNoop : IQonversionWrapper { public void Initialize(string gameObjectName) { } - public void Launch(string projectKey, bool observerMode, string callbackName) - { - } - public void SetDebugMode() + public void InitializeSdk(string projectKey, string launchMode, string environment, string entitlementsCacheLifetime) { } @@ -21,7 +18,7 @@ public void SetProperty(UserProperty key, string value) { } - public void AddAttributionData(string conversionData, AttributionSource source) + public void AddAttributionData(string conversionData, string providerName) { } @@ -33,7 +30,7 @@ public void SetAdvertisingID() { } - public void CheckPermissions(string callbackName) + public void CheckEntitlements(string callbackName) { } @@ -69,7 +66,7 @@ public void StoreSdkInfo(string version, string source) { } - public void CheckTrialIntroEligibilityForProductIds(string productIdsJson, string callbackName) + public void CheckTrialIntroEligibility(string productIdsJson, string callbackName) { } @@ -85,35 +82,16 @@ public void Logout() { } - public void PromoPurchase(string storeProductId, string callbackName) - { - } - - public void SetNotificationsToken(string token) - { - } - - public bool HandleNotification(string notification) + public void UserInfo(string callbackName) { - return false; } - public string GetNotificationCustomPayload(string notification) - { - return null; - } - - public void SubscribeOnAutomationEvents() - { + public void PromoPurchase(string storeProductId, string callbackName) + { } public void PresentCodeRedemptionSheet() { } - - public void SetPermissionsCacheLifetime(string lifetime) - { - - } } - } \ No newline at end of file +} \ No newline at end of file diff --git a/Runtime/Scripts/QonversionWrapperNoop.cs.meta b/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs.meta similarity index 100% rename from Runtime/Scripts/QonversionWrapperNoop.cs.meta rename to Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs.meta diff --git a/Runtime/Scripts/Models/AttributionSource.cs b/Runtime/Scripts/Models/AttributionSource.cs deleted file mode 100644 index 75b4474..0000000 --- a/Runtime/Scripts/Models/AttributionSource.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace QonversionUnity -{ - public enum AttributionSource - { - AppsFlyer = 0, - Branch, - Adjust - } -} \ No newline at end of file diff --git a/Runtime/Scripts/Models/PermissionsCacheLifetime.cs b/Runtime/Scripts/Models/PermissionsCacheLifetime.cs deleted file mode 100644 index 2560404..0000000 --- a/Runtime/Scripts/Models/PermissionsCacheLifetime.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace QonversionUnity -{ - public enum PermissionsCacheLifetime - { - WEEK, - TWO_WEEKS, - MONTH, - TWO_MONTHS, - THREE_MONTHS, - SIX_MONTHS, - YEAR, - UNLIMITED - } -} \ No newline at end of file diff --git a/Runtime/Scripts/Qonversion.cs b/Runtime/Scripts/Qonversion.cs index 712af99..e3d2129 100644 --- a/Runtime/Scripts/Qonversion.cs +++ b/Runtime/Scripts/Qonversion.cs @@ -1,814 +1,80 @@ -using JetBrains.Annotations; -using QonversionUnity.MiniJSON; using System; using System.Collections.Generic; -using UnityEngine; +using JetBrains.Annotations; namespace QonversionUnity { - public class Qonversion : MonoBehaviour + public static class Qonversion { - public delegate void OnPurchaseResultReceived(Dictionary permissions, QonversionError error, bool isCancelled); - public delegate void OnPermissionsReceived(Dictionary permissions, QonversionError error); - public delegate void OnProductsReceived(Dictionary products, QonversionError error); - public delegate void OnOfferingsReceived(Offerings offerings, QonversionError error); - public delegate void OnEligibilitiesReceived(Dictionary eligibilities, QonversionError error); - - /// - /// Delegate fires each time a promo purchase from the App Store happens. - /// Be sure you define a delegate for the event . - /// Call StartPromoPurchase in case of your app is ready to start promo purchase. - /// Or cache that delegate and call later when you need. - /// - /// StoreKit product identifier - /// A delegate that will start a promo purchase flow. - /// - /// - public delegate void OnPromoPurchasesReceived(string productId, StartPromoPurchase purchaseDelegate); + [CanBeNull] private static IQonversion _backingInstance; /// - /// Call the function if your app can handle a promo purchase at the current time. - /// Or you can cache the delegate, and call it when the app is ready to make the purchase. + /// Use this variable to get a current initialized instance of the Qonversion SDK. + /// Please, use the property only after calling . + /// Otherwise, trying to access the variable will cause an exception. /// - /// Callback that will be called when response is received. Returns permissions or potentially a QonversionError. - /// - /// - public delegate void StartPromoPurchase(OnPermissionsReceived callback); - - /// - /// Delegate fires each time a deferred transaction happens - /// - public delegate void OnUpdatedPurchasesReceived(Dictionary permissions); - - private const string GameObjectName = "QonvesrionRuntimeGameObject"; - private const string OnLaunchMethodName = "OnLaunch"; - private const string OnCheckPermissionsMethodName = "OnCheckPermissions"; - private const string OnPurchaseMethodName = "OnPurchase"; - private const string OnPromoPurchaseMethodName = "OnPromoPurchase"; - private const string OnPurchaseProductMethodName = "OnPurchaseProduct"; - private const string OnUpdatePurchaseMethodName = "OnUpdatePurchase"; - private const string OnUpdatePurchaseWithProductMethodName = "OnUpdatePurchaseWithProduct"; - private const string OnRestoreMethodName = "OnRestore"; - private const string OnProductsMethodName = "OnProducts"; - private const string OnOfferingsMethodName = "OnOfferings"; - private const string OnEligibilitiesMethodName = "OnEligibilities"; - - private const string SdkVersion = "3.7.1"; - private const string SdkSource = "unity"; - - private static IQonversionWrapper _Instance; - private static OnUpdatedPurchasesReceived _onUpdatedPurchasesReceived; - - private static OnPromoPurchasesReceived _onPromoPurchasesReceived; - private static string _storedPromoProductId = null; - private static AutomationsDelegate _automationsDelegate; - - private static List CheckPermissionsCallbacks { get; } = new List(); - private static List RestoreCallbacks { get; } = new List(); - private static OnPurchaseResultReceived PurchaseCallback { get; set; } - private static OnPurchaseResultReceived PurchaseProductCallback { get; set; } - private static OnPurchaseResultReceived UpdatePurchaseCallback { get; set; } - private static OnPurchaseResultReceived UpdatePurchaseWithProductCallback { get; set; } - private static List ProductsCallbacks { get; } = new List(); - private static List OfferingsCallbacks { get; } = new List(); - private static OnEligibilitiesReceived EligibilitiesCallback { get; set; } - private static OnPermissionsReceived PromoPurchaseCallback { get; set; } - - private static IQonversionWrapper getFinalInstance() + /// Current initialized instance of the Qonversion SDK. + /// throws exception if the instance has not been initialized + public static IQonversion GetSharedInstance() { - if (_Instance == null) + if (_backingInstance == null) { - switch (Application.platform) - { - case RuntimePlatform.Android: - _Instance = new QonversionWrapperAndroid(); - break; - case RuntimePlatform.IPhonePlayer: - _Instance = new QonversionWrapperIOS(); - break; - default: - _Instance = new QonversionWrapperNoop(); - break; - } - _Instance.Initialize(GameObjectName); - - GameObject go = new GameObject(GameObjectName); - go.AddComponent(); - DontDestroyOnLoad(go); + throw new Exception( + "Qonversion has not been initialized. You should call " + + "the initialize method before accessing the shared instance of Qonversion." + ); } - return _Instance; - } - - /// - /// This event will be fired when a user initiates a promotional in-app purchase from the App Store. - /// Declare a delegate for the event. - /// If you are not using the PromoPurchasesReceived event promo purchases will proceed automatically. - /// - public static event OnPromoPurchasesReceived PromoPurchasesReceived - { - add - { - _onPromoPurchasesReceived += value; - } - remove - { - _onPromoPurchasesReceived -= value; - } - } - - /// - /// This event will be fired each time a deferred transaction happens. - /// - public static event OnUpdatedPurchasesReceived UpdatedPurchasesReceived - { - add - { - _onUpdatedPurchasesReceived += value; - } - remove - { - _onUpdatedPurchasesReceived -= value; - } - } - - internal static void SetAutomationsDelegate(AutomationsDelegate automationsDelegate) - { - _automationsDelegate = automationsDelegate; - - IQonversionWrapper instance = getFinalInstance(); - instance.SubscribeOnAutomationEvents(); - } - - /// - /// Initializes Qonversion SDK with the given API key. - /// You can get one in your account on https://dash.qonversion.io. - /// - /// Project key to setup the SDK. - /// Set true if you are using observer mode only. - /// Observer mode - /// Installing the Android SDK - public static void Launch(string apiKey, bool observerMode) - { - IQonversionWrapper instance = getFinalInstance(); - instance.StoreSdkInfo(SdkVersion, SdkSource); - instance.Launch(apiKey, observerMode, OnLaunchMethodName); - } - - /// - /// You can set the flag to distinguish sandbox and production users. - /// To see the sandbox users turn on the Viewing test Data toggle on Qonversion Dashboard - /// - public static void SetDebugMode() - { - IQonversionWrapper instance = getFinalInstance(); - instance.SetDebugMode(); - } - - /// - /// iOS only. - /// On iOS 14.5+, after requesting the app tracking permission using ATT, you need to notify Qonversion if tracking - /// is allowed and IDFA is available. - /// - public static void SetAdvertisingID() - { - IQonversionWrapper instance = getFinalInstance(); - instance.SetAdvertisingID(); - } - - /// - /// Qonversion SDK provides an asynchronous method to set your side User ID that can be used to match users in - /// third-party integrations. - /// - /// Your database user ID. - /// User Identifiers - [Obsolete("Deprecated. Will be removed in a future major release. Use SetProperty(UserProperty.CustomUserId, value) instead.")] - public static void SetUserID(string userID) - { - IQonversionWrapper instance = getFinalInstance(); - instance.SetProperty(UserProperty.CustomUserId, userID); + return _backingInstance; } /// - /// Adds custom user property. - /// - /// User properties are attributes you can set on a user level. - /// You can send user properties to third party platforms as well as use them in Qonversion for customer segmentation - /// and analytics. - /// - /// Custom user property key. - /// Property value. - /// User Properties - public static void SetUserProperty(string key, string value) - { - IQonversionWrapper instance = getFinalInstance(); - instance.SetUserProperty(key, value); - } - - /// - /// Sets user property for pre-defined case property. - /// - /// User properties are attributes you can set on a user level. - /// You can send user properties to third party platforms as well as use them in Qonversion for customer segmentation - /// and analytics. + /// An entry point to use Qonversion SDK. Call to initialize Qonversion SDK with required and extra configs. + /// The function is the best way to set additional configs you need to use Qonversion SDK. + /// You still have an option to set a part of additional configs later via calling separate setters. /// - /// Defined enum key that will be transformed to string. - /// Property value. - /// User Properties - public static void SetProperty(UserProperty key, string value) + /// a config that contains key SDK settings. + /// Call to configure and create a QonversionConfig instance. + /// Initialized instance of the Qonversion SDK. + public static IQonversion Initialize(QonversionConfig config) { - IQonversionWrapper instance = getFinalInstance(); - instance.SetProperty(key, value); + _backingInstance = QonversionInternal.CreateInstance(); + _backingInstance?.InitializeInstance(config); + return _backingInstance; } - /// - /// This method will send all purchases to the Qonversion backend. Call this every time when purchase is handled - /// by your own implementation. - /// - /// //////Warning!////// - /// - /// This method works for Android only. - /// It should only be called if you're using Qonversion SDK in observer mode. - /// - /// Observer mode for Android SDK - public static void SyncPurchases() - { - IQonversionWrapper instance = getFinalInstance(); - instance.SyncPurchases(); - } - - /// - /// iOS only. - /// On iOS 14.0+ shows up a sheet for users to redeem AppStore offer codes. - /// - public static void PresentCodeRedemptionSheet() - { - IQonversionWrapper instance = getFinalInstance(); - instance.PresentCodeRedemptionSheet(); - } - - /// - /// Sends your attribution data to the attribution source. - /// - /// An object containing your attribution data. - /// The attribution source to which the data will be sent. - public static void AddAttributionData(Dictionary conversionData, AttributionSource attributionSource) - { - AddAttributionData(conversionData.toJson(), attributionSource); - } - - /// - /// Sends your attribution data to the attribution source. - /// - /// A json string containing your attribution data. - /// The attribution source to which the data will be sent. - public static void AddAttributionData(string conversionData, AttributionSource attributionSource) - { - IQonversionWrapper instance = getFinalInstance(); - - instance.AddAttributionData(conversionData, attributionSource); - } - - /// - /// Enable collecting Apple Search Ads attribution data. "false" by default. - /// - /// A bool value indicating whether Qonversion should collect attribution from Apple Search Ads. - /// - public static void SetAppleSearchAdsAttributionEnabled(bool enable) - { - IQonversionWrapper instance = getFinalInstance(); - instance.SetAppleSearchAdsAttributionEnabled(enable); - } - - /// - /// Call this function to link a user to his unique ID in your system and share purchase data. - /// - /// An unique user ID in your system. - /// - public static void Identify(string userID) - { - IQonversionWrapper instance = getFinalInstance(); - instance.Identify(userID); - } - - /// - /// Call this function to unlink a user from his unique ID in your system and his purchase data. - /// - /// - public static void Logout() - { - IQonversionWrapper instance = getFinalInstance(); - instance.Logout(); - } - - /// - /// You need to call the CheckPermissions method at the start of your app to check if a user has the required - /// permission. - /// - /// This method will check the user receipt and will return the current permissions. - /// - /// If Apple or Google servers are not responding at the time of the request, Qonversion provides the latest - /// permissions data from its database. - /// - /// Callback that will be called when response is received - public static void CheckPermissions(OnPermissionsReceived callback) - { - CheckPermissionsCallbacks.Add(callback); - IQonversionWrapper instance = getFinalInstance(); - instance.CheckPermissions(OnCheckPermissionsMethodName); - } - - /// - /// Make a purchase and validate that through server-to-server using Qonversion's Backend. - /// - /// Qonversion product identifier for purchase. - /// Callback that will be called when response is received. - /// - [Obsolete("Purchase with OnPermissionsReceived callback is deprecated. Consider using Purchase with OnPurchaseResultReceivedCallback instead.")] - public static void Purchase(string productId, OnPermissionsReceived callback) - { - var convertedCallback = ConvertPermissionsCallbackToPurchaseResultCallback(callback); - Purchase(productId, convertedCallback); - } - - /// - /// Make a purchase and validate that through server-to-server using Qonversion's Backend. - /// - /// Qonversion product identifier for purchase. - /// Callback that will be called when response is received. - /// - public static void Purchase(string productId, OnPurchaseResultReceived callback) - { - PurchaseCallback = callback; - IQonversionWrapper instance = getFinalInstance(); - instance.Purchase(productId, OnPurchaseMethodName); - } - - /// - /// Make a purchase and validate that through server-to-server using Qonversion's Backend. - /// - /// Qonversion product for purchase. - /// Callback that will be called when response is received. - /// - [Obsolete("PurchaseProduct with OnPermissionsReceived callback is deprecated. Consider using PurchaseProduct with OnPurchaseResultReceivedCallback instead.")] - public static void PurchaseProduct([NotNull] Product product, OnPermissionsReceived callback) - { - var convertedCallback = ConvertPermissionsCallbackToPurchaseResultCallback(callback); - PurchaseProduct(product, convertedCallback); - } - - /// - /// Make a purchase and validate that through server-to-server using Qonversion's Backend. - /// - /// Qonversion product for purchase. - /// Callback that will be called when response is received. - /// - public static void PurchaseProduct([NotNull] Product product, OnPurchaseResultReceived callback) - { - if (product == null) - { - callback(null, new QonversionError("PurchaseInvalid", "Product is null"), false); - return; - } - - PurchaseProductCallback = callback; - IQonversionWrapper instance = getFinalInstance(); - instance.PurchaseProduct(product.QonversionId, product.OfferingId, OnPurchaseProductMethodName); - } - - /// - /// Restoring purchases restores users purchases in your app, to maintain access to purchased content. - /// Users sometimes need to restore purchased content, such as when they upgrade to a new phone. - /// - /// Callback that will be called when response is received - public static void Restore(OnPermissionsReceived callback) - { - RestoreCallbacks.Add(callback); - IQonversionWrapper instance = getFinalInstance(); - instance.Restore(OnRestoreMethodName); - } - - /// - /// Update (upgrade/downgrade) subscription and validate that through server-to-server using Qonversion's Backend. - /// - /// Qonversion product identifier for purchase - /// Qonversion product identifier from which the upgrade/downgrade will be initialized - /// Callback that will be called when response is received - /// Proration Mode - /// Proration Mode - /// Update Purchase - [Obsolete("UpdatePurchase with OnPermissionsReceived callback is deprecated. Consider using UpdatePurchase with OnPurchaseResultReceivedCallback instead.")] - public static void UpdatePurchase(string productId, string oldProductId, OnPermissionsReceived callback, ProrationMode prorationMode = ProrationMode.UnknownSubscriptionUpgradeDowngradePolicy) - { - var convertedCallback = ConvertPermissionsCallbackToPurchaseResultCallback(callback); - UpdatePurchase(productId, oldProductId, convertedCallback, prorationMode); - } - - /// - /// Update (upgrade/downgrade) subscription and validate that through server-to-server using Qonversion's Backend. - /// - /// Qonversion product identifier for purchase - /// Qonversion product identifier from which the upgrade/downgrade will be initialized - /// Callback that will be called when response is received - /// Proration Mode - /// Proration Mode - /// Update Purchase - public static void UpdatePurchase(string productId, string oldProductId, OnPurchaseResultReceived callback, ProrationMode prorationMode = ProrationMode.UnknownSubscriptionUpgradeDowngradePolicy) - { - UpdatePurchaseCallback = callback; - IQonversionWrapper instance = getFinalInstance(); - instance.UpdatePurchase(productId, oldProductId, prorationMode, OnUpdatePurchaseMethodName); - } - - /// - /// Update (upgrade/downgrade) subscription and validate that through server-to-server using Qonversion's Backend. - /// - /// Qonversion product for purchase - /// Qonversion product identifier from which the upgrade/downgrade will be initialized - /// Callback that will be called when response is received - /// Proration Mode - /// Proration Mode - /// Update Purchase - [Obsolete("UpdatePurchaseWithProduct with OnPermissionsReceived callback is deprecated. Consider using UpdatePurchaseWithProduct with OnPurchaseResultReceivedCallback instead.")] - public static void UpdatePurchaseWithProduct([NotNull] Product product, string oldProductId, OnPermissionsReceived callback, ProrationMode prorationMode = ProrationMode.UnknownSubscriptionUpgradeDowngradePolicy) - { - var convertedCallback = ConvertPermissionsCallbackToPurchaseResultCallback(callback); - UpdatePurchaseWithProduct(product, oldProductId, convertedCallback, prorationMode); - } - - /// - /// Update (upgrade/downgrade) subscription and validate that through server-to-server using Qonversion's Backend. - /// - /// Qonversion product for purchase - /// Qonversion product identifier from which the upgrade/downgrade will be initialized - /// Callback that will be called when response is received - /// Proration Mode - /// Proration Mode - /// Update Purchase - public static void UpdatePurchaseWithProduct([NotNull] Product product, string oldProductId, OnPurchaseResultReceived callback, ProrationMode prorationMode = ProrationMode.UnknownSubscriptionUpgradeDowngradePolicy) - { - if (product == null) - { - callback(null, new QonversionError("PurchaseInvalid", "Product is null"), false); - return; - } - - UpdatePurchaseWithProductCallback = callback; - IQonversionWrapper instance = getFinalInstance(); - instance.UpdatePurchaseWithProduct(product.QonversionId, product.OfferingId, oldProductId, prorationMode, OnUpdatePurchaseWithProductMethodName); - } - - /// - /// Returns Qonversion products in association with Apple and Google Play Store Products. - /// - /// Callback that will be called when response is received. - /// Product Center - public static void Products(OnProductsReceived callback) - { - ProductsCallbacks.Add(callback); - IQonversionWrapper instance = getFinalInstance(); - instance.Products(OnProductsMethodName); - } + public delegate void OnPurchaseResultReceived(Dictionary entitlements, QonversionError error, bool isCancelled); + public delegate void OnEntitlementsReceived(Dictionary entitlements, QonversionError error); + public delegate void OnProductsReceived(Dictionary products, QonversionError error); + public delegate void OnOfferingsReceived(Offerings offerings, QonversionError error); + public delegate void OnEligibilitiesReceived(Dictionary eligibilities, QonversionError error); + public delegate void OnUserInfoReceived(User userInfo, QonversionError error); /// - /// Return Qonversion Offerings Object. - /// - /// An offering is a group of products that you can offer to a user on a given paywall based on your business logic. - /// For example, you can offer one set of products on a paywall immediately after onboarding and another - /// set of products with discounts later on if a user has not converted. - /// Offerings allow changing the products offered remotely without releasing app updates. + /// Delegate fires each time a promo purchase from the App Store happens. + /// Be sure you define a delegate for the event . + /// Call StartPromoPurchase in case of your app is ready to start promo purchase. + /// Or cache that delegate and call later when you need. /// - /// Offerings - /// Product Center - public static void Offerings(OnOfferingsReceived callback) - { - OfferingsCallbacks.Add(callback); - IQonversionWrapper instance = getFinalInstance(); - instance.Offerings(OnOfferingsMethodName); - } + /// StoreKit product identifier + /// A delegate that will start a promo purchase flow. + /// + /// + public delegate void OnPromoPurchasesReceived(string productId, StartPromoPurchase purchaseDelegate); /// - /// You can check if a user is eligible for an introductory offer, including a free trial. - /// You can show only a regular price for users who are not eligible for an introductory offer. + /// Call the function if your app can handle a promo purchase at the current time. + /// Or you can cache the delegate, and call it when the app is ready to make the purchase. /// - /// Products identifiers that must be checked. - /// Callback that will be called when response is received - public static void CheckTrialIntroEligibilityForProductIds(IList productIds, OnEligibilitiesReceived callback) - { - var productIdsJson = Json.Serialize(productIds); - - EligibilitiesCallback = callback; - IQonversionWrapper instance = getFinalInstance(); - instance.CheckTrialIntroEligibilityForProductIds(productIdsJson, OnEligibilitiesMethodName); - } + /// Callback that will be called when response is received. Returns entitlements or potentially a QonversionError. + /// + /// + public delegate void StartPromoPurchase(OnEntitlementsReceived callback); /// - /// Permissions cache is used when there are problems with the Qonversion API - /// or internet connection. If so, Qonversion will return the last successfully loaded - /// permissions. The current method allows you to configure how long that cache may be used. - /// The default value is Desired permissions cache lifetime duration. - public static void SetPermissionsCacheLifetime(PermissionsCacheLifetime lifetime) { - var lifetimeKey = Mapper.GetLifetimeKey(lifetime); - IQonversionWrapper instance = getFinalInstance(); - instance.SetPermissionsCacheLifetime(lifetimeKey); - } - - /// - /// Set push token to Qonversion to enable Qonversion push notifications + /// Delegate fires each time a user entitlements change asynchronously, + /// for example, when pending purchases like SCA, Ask to buy, etc., happen. /// - /// Firebase device token on Android. APNs device token on iOS. - public static void SetNotificationsToken(string token) - { - IQonversionWrapper instance = getFinalInstance(); - instance.SetNotificationsToken(token); - } - - public static bool HandleNotification(Dictionary notification) - { - IQonversionWrapper instance = getFinalInstance(); - return instance.HandleNotification(notification.toJson()); - } - - [CanBeNull] - public static Dictionary GetNotificationCustomPayload(Dictionary notification) - { - IQonversionWrapper instance = getFinalInstance(); - var payloadJson = instance.GetNotificationCustomPayload(notification.toJson()); - - if (payloadJson == null) - { - return null; - } - - if (!(Json.Deserialize(payloadJson) is Dictionary response)) - { - Debug.LogError("Could not parse custom notification payload."); - return null; - } - - return response; - } - - // Called from the native SDK - Called when launch completed - private void OnLaunch(string jsonString) - { - Debug.Log("OnLaunch " + jsonString); - } - - // Called from the native SDK - Called when permissions received from the checkPermissions() method - private void OnCheckPermissions(string jsonString) - { - Debug.Log("OnCheckPermissions " + jsonString); - HandlePermissions(CheckPermissionsCallbacks, jsonString); - CheckPermissionsCallbacks.Clear(); - } - - // Called from the native SDK - Called when purchase result received from the purchase() method - private void OnPurchase(string jsonString) - { - Debug.Log("OnPurchase callback " + jsonString); - HandlePurchaseResult(PurchaseCallback, jsonString); - PurchaseCallback = null; - } - - // Called from the native SDK - Called when purchase result received from the purchaseProduct() method - private void OnPurchaseProduct(string jsonString) - { - Debug.Log("OnPurchaseProduct callback " + jsonString); - HandlePurchaseResult(PurchaseProductCallback, jsonString); - PurchaseProductCallback = null; - } - - // Called from the native SDK - Called when permissions received from the restore() method - private void OnRestore(string jsonString) - { - Debug.Log("OnRestore " + jsonString); - HandlePermissions(RestoreCallbacks, jsonString); - RestoreCallbacks.Clear(); - } - - // Called from the native SDK - Called when purchase result received from the updatePurchase() method - private void OnUpdatePurchase(string jsonString) - { - Debug.Log("OnUpdatePurchase " + jsonString); - HandlePurchaseResult(UpdatePurchaseCallback, jsonString); - UpdatePurchaseCallback = null; - } - - // Called from the native SDK - Called when purchase result received from the updatePurchaseWithProduct() method - private void OnUpdatePurchaseWithProduct(string jsonString) - { - Debug.Log("OnUpdatePurchaseWithProduct " + jsonString); - HandlePurchaseResult(UpdatePurchaseWithProductCallback, jsonString); - UpdatePurchaseWithProductCallback = null; - } - - // Called from the native SDK - Called when permissions received from the promoPurchase() method - private void OnPromoPurchase(string jsonString) - { - Debug.Log("OnPromoPurchase callback " + jsonString); - if (PromoPurchaseCallback != null) { - var callbacks = new List { PromoPurchaseCallback }; - HandlePermissions(callbacks, jsonString); - } - - PromoPurchaseCallback = null; - _storedPromoProductId = null; - } - - // Called from the native SDK - Called when products received from the products() method - private void OnProducts(string jsonString) - { - Debug.Log("OnProducts " + jsonString); - - if (ProductsCallbacks.Count == 0) return; - - var error = Mapper.ErrorFromJson(jsonString); - if (error != null) - { - ProductsCallbacks.ForEach(callback => callback(null, error)); - } - else - { - var products = Mapper.ProductsFromJson(jsonString); - ProductsCallbacks.ForEach(callback => callback(products, null)); - } - - ProductsCallbacks.Clear(); - } - - // Called from the native SDK - Called when offerings received from the offerings() method - private void OnOfferings(string jsonString) - { - Debug.Log("OnOfferings " + jsonString); - - if (OfferingsCallbacks.Count == 0) return; - - var error = Mapper.ErrorFromJson(jsonString); - if (error != null) - { - OfferingsCallbacks.ForEach(callback => callback(null, error)); - } - else - { - var offerings = Mapper.OfferingsFromJson(jsonString); - OfferingsCallbacks.ForEach(callback => callback(offerings, null)); - } - - OfferingsCallbacks.Clear(); - } - - // Called from the native SDK - Called when eligibilities received from the checkTrialIntroEligibilityForProductIds() method - private void OnEligibilities(string jsonString) - { - Debug.Log("OnEligibilities " + jsonString); - - if (EligibilitiesCallback == null) return; - - var error = Mapper.ErrorFromJson(jsonString); - if (error != null) - { - EligibilitiesCallback(null, error); - } - else - { - Dictionary eligibilities = Mapper.EligibilitiesFromJson(jsonString); - EligibilitiesCallback(eligibilities, null); - } - - EligibilitiesCallback = null; - } - - // Called from the native SDK - Called when deferred or pending purchase occured - private void OnReceiveUpdatedPurchases(string jsonString) - { - Debug.Log("OnReceiveUpdatedPurchases " + jsonString); - - if (_onUpdatedPurchasesReceived == null) - { - return; - } - - Dictionary permissions = Mapper.PermissionsFromJson(jsonString); - _onUpdatedPurchasesReceived(permissions); - } - - private void OnReceivePromoPurchase(string storeProductId) - { - Debug.Log("OnReceivePromoPurchase " + storeProductId); - - if (_onPromoPurchasesReceived == null) - { - return; - } - - _storedPromoProductId = storeProductId; - _onPromoPurchasesReceived(storeProductId, PromoPurchase); - } - - private void PromoPurchase(OnPermissionsReceived callback) - { - PromoPurchaseCallback = callback; - IQonversionWrapper instance = getFinalInstance(); - instance.PromoPurchase(_storedPromoProductId, OnPromoPurchaseMethodName); - } - - private void HandlePermissions(List callbacks, string jsonString) - { - if (callbacks.Count == 0) return; - - var error = Mapper.ErrorFromJson(jsonString); - if (error != null) - { - callbacks.ForEach(callback => callback(null, error)); - } - else - { - var permissions = Mapper.PermissionsFromJson(jsonString); - callbacks.ForEach(callback => callback(permissions, null)); - } - } - - private void HandlePurchaseResult(OnPurchaseResultReceived callback, string jsonString) - { - if (callback == null) return; - - var error = Mapper.ErrorFromJson(jsonString); - if (error != null) - { - var isCancelled = Mapper.GetIsCancelledFromJson(jsonString); - callback(null, error, isCancelled); - } - else - { - var permissions = Mapper.PermissionsFromJson(jsonString); - callback(permissions, null, false); - } - } - - private void OnAutomationsScreenShown(string jsonString) - { - if (_automationsDelegate == null) - { - return; - } - - string screenId = Mapper.ScreenIdFromJson(jsonString); - - _automationsDelegate.OnAutomationsScreenShown(screenId); - } - - private void OnAutomationsActionStarted(string jsonString) - { - if (_automationsDelegate == null) - { - return; - } - - ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); - _automationsDelegate.OnAutomationsActionStarted(actionResult); - } - - private void OnAutomationsActionFailed(string jsonString) - { - if (_automationsDelegate == null) - { - return; - } - - ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); - _automationsDelegate.OnAutomationsActionFailed(actionResult); - } - - - private void OnAutomationsActionFinished(string jsonString) - { - if (_automationsDelegate == null) - { - return; - } - - ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); - _automationsDelegate.OnAutomationsActionFinished(actionResult); - } - - private void OnAutomationsFinished(string jsonString) - { - if (_automationsDelegate == null) - { - return; - } - - _automationsDelegate.OnAutomationsFinished(); - } - - private static OnPurchaseResultReceived ConvertPermissionsCallbackToPurchaseResultCallback(OnPermissionsReceived callback) - { - return delegate(Dictionary permissions, QonversionError error, bool isCancelled) { - callback(permissions, error); - }; - } + public delegate void OnUpdatedEntitlementsReceived(Dictionary entitlements); } } diff --git a/Runtime/Scripts/Qonversion.cs.meta b/Runtime/Scripts/Qonversion.cs.meta index 3d73b36..cd102dc 100644 --- a/Runtime/Scripts/Qonversion.cs.meta +++ b/Runtime/Scripts/Qonversion.cs.meta @@ -1,11 +1,3 @@ fileFormatVersion: 2 -guid: 38c50778583feeb4da0934f2fa914b96 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +guid: 3d153a0da53e4ab38cd2815b94987e82 +timeCreated: 1668681655 \ No newline at end of file diff --git a/Runtime/Scripts/QonversionAndroidHandler.cs b/Runtime/Scripts/QonversionAndroidHandler.cs deleted file mode 100644 index 1ff099e..0000000 --- a/Runtime/Scripts/QonversionAndroidHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UnityEngine; - -namespace QonversionUnity -{ - internal class QonversionAndroidHandler : AndroidJavaProxy, IQonversionResultHandler - { - private const string QONVERSION_WRAPPER_INTERFACE_PATH = "com.qonversion.unitywrapper.IQonversionResultHandler"; - - public InitDelegate InitComplete; - - public QonversionAndroidHandler(InitDelegate onInitComplete) : base(QONVERSION_WRAPPER_INTERFACE_PATH) - { - InitComplete = onInitComplete; - } - - public void onSuccessInit(string uid) - { - InitComplete?.Invoke(); - } - - public void onErrorInit(string errorMessage) - { - Debug.LogError(string.Format("[Qonversion] onErrorInit Error: {0}", errorMessage)); - } - } -} \ No newline at end of file diff --git a/Runtime/Scripts/QonversionAndroidHandler.cs.meta b/Runtime/Scripts/QonversionAndroidHandler.cs.meta deleted file mode 100644 index 57140d9..0000000 --- a/Runtime/Scripts/QonversionAndroidHandler.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5ce88f53397a401488b208d6a1c156d8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/Scripts/QonversionConfig.cs b/Runtime/Scripts/QonversionConfig.cs new file mode 100644 index 0000000..341f97e --- /dev/null +++ b/Runtime/Scripts/QonversionConfig.cs @@ -0,0 +1,18 @@ +namespace QonversionUnity +{ + public class QonversionConfig + { + public readonly string ProjectKey; + public readonly LaunchMode LaunchMode; + public readonly Environment Environment; + public readonly EntitlementsCacheLifetime EntitlementsCacheLifetime; + + public QonversionConfig(string projectKey, LaunchMode launchMode, Environment environment, EntitlementsCacheLifetime entitlementsCacheLifetime) + { + ProjectKey = projectKey; + LaunchMode = launchMode; + Environment = environment; + EntitlementsCacheLifetime = entitlementsCacheLifetime; + } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/QonversionConfig.cs.meta b/Runtime/Scripts/QonversionConfig.cs.meta new file mode 100644 index 0000000..d0b0f96 --- /dev/null +++ b/Runtime/Scripts/QonversionConfig.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 081671b389ce42258e66635391aa5c2f +timeCreated: 1668682590 \ No newline at end of file diff --git a/Runtime/Scripts/QonversionConfigBuilder.cs b/Runtime/Scripts/QonversionConfigBuilder.cs new file mode 100644 index 0000000..8f8e023 --- /dev/null +++ b/Runtime/Scripts/QonversionConfigBuilder.cs @@ -0,0 +1,55 @@ +namespace QonversionUnity +{ + public class QonversionConfigBuilder + { + private readonly string _projectKey; + private readonly LaunchMode _launchMode; + private Environment _environment = Environment.Production; + private EntitlementsCacheLifetime _entitlementsCacheLifetime = EntitlementsCacheLifetime.Month; + + public QonversionConfigBuilder(string projectKey, LaunchMode launchMode) + { + _projectKey = projectKey; + _launchMode = launchMode; + } + + /// + /// Set current application . Used to distinguish sandbox and production users. + /// + /// current environment. + /// builder instance for chain calls. + public QonversionConfigBuilder SetEnvironment(Environment environment) + { + _environment = environment; + return this; + } + + /// + /// Entitlements cache is used when there are problems with the Qonversion API + /// or internet connection. If so, Qonversion will return the last successfully loaded + /// entitlements. The current method allows you to configure how long that cache may be used. + /// The default value is . + /// + /// desired entitlements cache lifetime duration. + /// builder instance for chain calls. + public QonversionConfigBuilder SetEntitlementsCacheLifetime(EntitlementsCacheLifetime lifetime) + { + _entitlementsCacheLifetime = lifetime; + return this; + } + + /// + /// Generate instance with all the provided configurations. + /// + /// the complete instance. + public QonversionConfig Build() + { + return new QonversionConfig( + _projectKey, + _launchMode, + _environment, + _entitlementsCacheLifetime + ); + } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/QonversionConfigBuilder.cs.meta b/Runtime/Scripts/QonversionConfigBuilder.cs.meta new file mode 100644 index 0000000..019c21b --- /dev/null +++ b/Runtime/Scripts/QonversionConfigBuilder.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e965105671494d86988de6e150a1a2a3 +timeCreated: 1668683063 \ No newline at end of file diff --git a/Runtime/Scripts/QonversionLauncher.cs b/Runtime/Scripts/QonversionLauncher.cs deleted file mode 100644 index 3956c64..0000000 --- a/Runtime/Scripts/QonversionLauncher.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UnityEngine; - -namespace QonversionUnity -{ - public class QonversionLauncher : MonoBehaviour - { - [Tooltip("Your Qonversion Application Access Key. Get from https://dash.qonversion.io/")] - [SerializeField] - protected string m_ApplicationAccessKey; - - [Tooltip("Debug Mode: https://documentation.qonversion.io/docs/debug-mode")] - [SerializeField] - protected bool m_DebugMode; - - [Tooltip("Observer Mode: https://documentation.qonversion.io/docs/observer-mode")] - [SerializeField] - protected bool m_ObserverMode; - - private void Start() - { - if (m_DebugMode) - { - Qonversion.SetDebugMode(); - } - - Qonversion.Launch(m_ApplicationAccessKey, m_ObserverMode); - } - } -} \ No newline at end of file diff --git a/Runtime/Scripts/QonversionLauncher.cs.meta b/Runtime/Scripts/QonversionLauncher.cs.meta deleted file mode 100644 index 1650602..0000000 --- a/Runtime/Scripts/QonversionLauncher.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2a8972452586ad74b907e03decfa6f7b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/iOS/AutomationsWrapperIOS.cs b/Runtime/iOS/AutomationsWrapperIOS.cs new file mode 100644 index 0000000..ce17f2e --- /dev/null +++ b/Runtime/iOS/AutomationsWrapperIOS.cs @@ -0,0 +1,77 @@ +#if UNITY_IOS +using System.Runtime.InteropServices; +#endif + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace QonversionUnity +{ + internal class AutomationsWrapperIOS : IAutomationsWrapper + { +#if UNITY_IOS + [DllImport("__Internal")] + private static extern void _initializeAutomations(string gameObjectName); + + [DllImport("__Internal")] + private static extern void _setNotificationsToken(string token); + + [DllImport("__Internal")] + private static extern bool _handleNotification(string notification); + + [DllImport("__Internal")] + private static extern string _getNotificationCustomPayload(string notification); + + [DllImport("__Internal")] + private static extern void _subscribeOnAutomationEvents(); + + [DllImport("__Internal")] + private static extern void _showScreen(string screenId, string callbackName); +#endif + + public void Initialize(string gameObjectName) + { +#if UNITY_IOS + _initializeAutomations(gameObjectName); +#endif + } + public void SetNotificationsToken(string token) + { +#if UNITY_IOS + _setNotificationsToken(token); +#endif + } + + public bool HandleNotification(string notification) + { +#if UNITY_IOS + return _handleNotification(notification); +#else + return false; +#endif + } + + public string GetNotificationCustomPayload(string notification) + { +#if UNITY_IOS + return _getNotificationCustomPayload(notification); +#else + return null; +#endif + } + + public void SubscribeOnAutomationEvents() + { +#if UNITY_IOS + _subscribeOnAutomationEvents(); +#endif + } + public void ShowScreen(string screenId, string callbackName) + { +#if UNITY_IOS + _showScreen(screenId, callbackName); +#endif + } + } +} \ No newline at end of file diff --git a/Runtime/iOS/AutomationsWrapperIOS.cs.meta b/Runtime/iOS/AutomationsWrapperIOS.cs.meta new file mode 100644 index 0000000..4a3fc2f --- /dev/null +++ b/Runtime/iOS/AutomationsWrapperIOS.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 833a9b7bdb0a43228b1153c40421e900 +timeCreated: 1668776223 \ No newline at end of file diff --git a/Runtime/iOS/Plugins/AutomationsBridge.m b/Runtime/iOS/Plugins/AutomationsBridge.m new file mode 100644 index 0000000..8f5e777 --- /dev/null +++ b/Runtime/iOS/Plugins/AutomationsBridge.m @@ -0,0 +1,55 @@ +#import "UtilityBridge.h" +#import "QNUAutomationsDelegate.h" +@import QonversionSandwich; + +char* automationsUnityListenerName = nil; + +static QNUAutomationsDelegate *automationsBridge; + +void _initializeAutomations(const char* unityListener) { + unsigned long len = strlen(unityListener); + automationsUnityListenerName = malloc(len + 1); + strcpy(automationsUnityListenerName, unityListener); + + automationsBridge = [[QNUAutomationsDelegate alloc] initWithListenerName:automationsUnityListenerName]; +} + +void _setNotificationsToken(const char* token) { + NSString *tokenStr = [UtilityBridge сonvertCStringToNSString:token]; + [automationsBridge setNotificationsToken:tokenStr]; +} + +bool _handleNotification(const char* notification) { + NSDictionary *notificationInfo = [UtilityBridge dictionaryFromJsonString: [UtilityBridge сonvertCStringToNSString: notification]]; + + BOOL isQonversionNotification = [automationsBridge handleNotification:notificationInfo]; + + return isQonversionNotification; +} + +char* _getNotificationCustomPayload(const char* notification) { + NSDictionary *notificationInfo = [UtilityBridge dictionaryFromJsonString: [UtilityBridge сonvertCStringToNSString: notification]]; + + NSDictionary *payload = [automationsBridge getNotificationCustomPayload:notificationInfo]; + + if (payload == nil) { + return nil; + } + + const char *data = [UtilityBridge jsonStringFromObject:payload]; + + char* cString = (char*)malloc(strlen(data) + 1); + strcpy(cString, data); + + return cString; +} + +void _showScreen(const char* screenId, const char* unityCallbackName) { + NSString *callbackName = [UtilityBridge сonvertCStringToNSString:unityCallbackName]; + NSString *screenIdStr = [UtilityBridge сonvertCStringToNSString:screenId]; + [automationsBridge showScreenWithId:screenIdStr callbackName:callbackName]; +} + +void _subscribeOnAutomationEvents() { + [automationsBridge subscribe]; +} diff --git a/Runtime/iOS/Plugins/AutomationsBridge.m.meta b/Runtime/iOS/Plugins/AutomationsBridge.m.meta new file mode 100644 index 0000000..fe55fb6 --- /dev/null +++ b/Runtime/iOS/Plugins/AutomationsBridge.m.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: 3274bd50e96104e20b153fb581760138 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.h b/Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.h index 3535d4c..692820f 100644 --- a/Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.h +++ b/Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.h @@ -14,6 +14,10 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithListenerName:(char *)unityListenerName; - (void)subscribe; +- (void)setNotificationsToken:(NSString *)token; +- (BOOL)handleNotification:(NSDictionary *)notificationInfo; +- (NSDictionary *)getNotificationCustomPayload:(NSDictionary *)payload; +- (void)showScreenWithId:(NSString *)screenId callbackName:(NSString *)callbackName; @end diff --git a/Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.m b/Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.m index 10e4f5f..55235e0 100644 --- a/Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.m +++ b/Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.m @@ -47,10 +47,28 @@ - (void)subscribe { [self.automationsSandwich subscribe:self]; } +- (void)setNotificationsToken:(NSString *)token { + [self.automationsSandwich setNotificationToken:token]; +} + +- (BOOL)handleNotification:(NSDictionary *)notificationInfo { + return [self.automationsSandwich handleNotification:notificationInfo]; +} + +- (NSDictionary *)getNotificationCustomPayload:(NSDictionary *)payload { + return [self.automationsSandwich getNotificationCustomPayload:payload]; +} + - (void)automationDidTriggerWithEvent:(NSString * _Nonnull)event payload:(NSDictionary * _Nullable)payload { NSString *methodName = self.automationEvents[event]; [UtilityBridge sendUnityMessage:payload ?: @{} toMethod:methodName unityListener: listenerName]; } +- (void)showScreenWithId:(NSString *)screenId callbackName:(NSString *)callbackName { + [self.automationsSandwich showScreen:screenId completion:^(NSDictionary * _Nullable result, SandwichError * _Nullable error) { + [UtilityBridge handleResult:result error:error callbackName:callbackName unityListener:listenerName]; + }]; +} + @end diff --git a/Runtime/iOS/Plugins/QonversionBridge.m b/Runtime/iOS/Plugins/QonversionBridge.m index 89237ae..7247469 100644 --- a/Runtime/iOS/Plugins/QonversionBridge.m +++ b/Runtime/iOS/Plugins/QonversionBridge.m @@ -1,29 +1,27 @@ #import "UtilityBridge.h" -#import "QNUAutomationsDelegate.h" @import QonversionSandwich; char* unityListenerName = nil; @interface QonversionEventListenerWrapper : NSObject -- (void)qonversionDidReceiveUpdatedPermissions:(NSDictionary * _Nonnull)permissions; +- (void)qonversionDidReceiveUpdatedEntitlements:(NSDictionary * _Nonnull)entitlements; - (void)shouldPurchasePromoProductWith:(NSString * _Nonnull)productId; @end @implementation QonversionEventListenerWrapper -- (void)qonversionDidReceiveUpdatedPermissions:(NSDictionary * _Nonnull)permissions { - [UtilityBridge sendUnityMessage:permissions toMethod:@"OnReceiveUpdatedPurchases" unityListener: unityListenerName]; -} - - (void)shouldPurchasePromoProductWith:(NSString * _Nonnull)productId { UnitySendMessage(unityListenerName, "OnReceivePromoPurchase", productId.UTF8String); } +- (void)qonversionDidReceiveUpdatedEntitlements:(NSDictionary * _Nonnull)entitlements { + [UtilityBridge sendUnityMessage:entitlements toMethod:@"OnReceivedUpdatedEntitlements" unityListener: unityListenerName]; +} + @end -static QNUAutomationsDelegate *automationsDelegate; static QonversionSandwich *qonversionSandwich; void _initialize(const char* unityListener) { @@ -32,7 +30,15 @@ void _initialize(const char* unityListener) { strcpy(unityListenerName, unityListener); qonversionSandwich = [[QonversionSandwich alloc] initWithQonversionEventListener:[QonversionEventListenerWrapper new]]; - automationsDelegate = [[QNUAutomationsDelegate alloc] initWithListenerName:unityListenerName]; +} + +void _initializeSdk(const char* projectKey, const char* launchMode, const char* environment, const char* entitlementsCacheLifetime) { + NSString *keyStr = [UtilityBridge сonvertCStringToNSString:projectKey]; + NSString *launchModeStr = [UtilityBridge сonvertCStringToNSString:launchMode]; + NSString *envStr = [UtilityBridge сonvertCStringToNSString:environment]; + NSString *cacheLifetimeStr = [UtilityBridge сonvertCStringToNSString:entitlementsCacheLifetime]; + + [qonversionSandwich initializeWithProjectKey:keyStr launchModeKey:launchModeStr environmentKey:envStr entitlementsCacheLifetimeKey:cacheLifetimeStr]; } void _storeSdkInfo(const char* version, const char* source) { @@ -42,22 +48,8 @@ void _storeSdkInfo(const char* version, const char* source) { [qonversionSandwich storeSdkInfoWithSource:sourceStr version:versionStr]; } -void _setDebugMode() { - [qonversionSandwich setDebugMode]; -} - -void _launchWithKey(const char* key, const char* unityCallbackName) { - NSString *callbackName = [UtilityBridge сonvertCStringToNSString:unityCallbackName]; - - NSString *projectKey = [UtilityBridge сonvertCStringToNSString:key]; - - [qonversionSandwich launchWithProjectKey:projectKey completion:^(NSDictionary * _Nullable result, SandwichError * _Nullable error) { - [UtilityBridge handleResult:result error:error callbackName:callbackName unityListener:unityListenerName]; - }]; -} - void _setAdvertisingID() { - [qonversionSandwich setAdvertisingId]; + [qonversionSandwich collectAdvertisingId]; } void _presentCodeRedemptionSheet() { @@ -67,7 +59,7 @@ void _presentCodeRedemptionSheet() { } void _setAppleSearchAdsAttributionEnabled(const bool enable) { - [qonversionSandwich setAppleSearchAdsAttributionEnabled:enable]; + [qonversionSandwich collectAppleSearchAdsAttribution]; } void _setProperty(const char* propertyName, const char* value) { @@ -88,7 +80,7 @@ void _addAttributionData(const char* conversionData, const char* provider) { NSDictionary *conversionInfo = [UtilityBridge dictionaryFromJsonString: [UtilityBridge сonvertCStringToNSString: conversionData]]; NSString *providerStr = [UtilityBridge сonvertCStringToNSString:provider]; - [qonversionSandwich addAttributionDataWithSourceKey:providerStr value:conversionInfo]; + [qonversionSandwich attributionWithProviderKey:providerStr value:conversionInfo]; } void _identify(const char* userId) { @@ -96,6 +88,14 @@ void _identify(const char* userId) { [qonversionSandwich identify:userIdStr]; } +void _userInfo(const char* unityCallbackName) { + NSString *callbackName = [UtilityBridge сonvertCStringToNSString:unityCallbackName]; + + [qonversionSandwich userInfo:^(NSDictionary * _Nullable result, SandwichError * _Nullable error) { + [UtilityBridge handleResult:result error:error callbackName:callbackName unityListener:unityListenerName]; + }]; +} + void _logout() { [qonversionSandwich logout]; } @@ -103,7 +103,7 @@ void _logout() { void _checkPermissions(const char* unityCallbackName) { NSString *callbackName = [UtilityBridge сonvertCStringToNSString:unityCallbackName]; - [qonversionSandwich checkPermissions:^(NSDictionary * _Nullable result, SandwichError * _Nullable error) { + [qonversionSandwich checkEntitlements:^(NSDictionary * _Nullable result, SandwichError * _Nullable error) { [UtilityBridge handleResult:result error:error callbackName:callbackName unityListener:unityListenerName]; }]; } @@ -151,7 +151,7 @@ void _offerings(const char* unityCallbackName) { }]; } -void _checkTrialIntroEligibilityForProductIds(const char* productIdsJson, const char* unityCallbackName) { +void _checkTrialIntroEligibility(const char* productIdsJson, const char* unityCallbackName) { NSString *callbackName = [UtilityBridge сonvertCStringToNSString:unityCallbackName]; NSString *productIdsJsonStr = [UtilityBridge сonvertCStringToNSString:productIdsJson]; @@ -178,39 +178,3 @@ void _promoPurchase(const char* storeProductId, const char* unityCallbackName) { [UtilityBridge handleResult:result error:error callbackName:callbackName unityListener:unityListenerName]; }]; } - -void _setPermissionsCacheLifetime(const char* lifetimeName) { - NSString *lifetimeNameStr = [UtilityBridge сonvertCStringToNSString:lifetimeName]; - [qonversionSandwich setPermissionsCacheLifetime:lifetimeNameStr]; -} - -void _setNotificationsToken(const char* token) { - NSString *tokenStr = [UtilityBridge сonvertCStringToNSString:token]; - [qonversionSandwich setNotificationToken:tokenStr]; -} - -bool _handleNotification(const char* notification) { - NSDictionary *notificationInfo = [UtilityBridge dictionaryFromJsonString: [UtilityBridge сonvertCStringToNSString: notification]]; - - BOOL isQonversionNotification = [qonversionSandwich handleNotification:notificationInfo]; - - return isQonversionNotification; -} - -const char* _getNotificationCustomPayload(const char* notification) { - NSDictionary *notificationInfo = [UtilityBridge dictionaryFromJsonString: [UtilityBridge сonvertCStringToNSString: notification]]; - - NSDictionary *payload = [qonversionSandwich getNotificationCustomPayload:notificationInfo]; - - if (payload == nil) { - return nil; - } - - const char *data = [UtilityBridge jsonStringFromObject:payload]; - - return data; -} - -void _subscribeOnAutomationEvents() { - [automationsDelegate subscribe]; -} diff --git a/Runtime/iOS/QonversionWrapperIOS.cs b/Runtime/iOS/QonversionWrapperIOS.cs index c4ec360..2624c89 100644 --- a/Runtime/iOS/QonversionWrapperIOS.cs +++ b/Runtime/iOS/QonversionWrapperIOS.cs @@ -15,10 +15,10 @@ internal class QonversionWrapperIOS : IQonversionWrapper private static extern void _initialize(string gameObjectName); [DllImport("__Internal")] - private static extern void _storeSdkInfo(string version, string source); + private static extern void _initializeSdk(string projectKey, string launchMode, string environment, string entitlementsCacheLifetime); [DllImport("__Internal")] - private static extern void _setDebugMode(); + private static extern void _storeSdkInfo(string version, string source); [DllImport("__Internal")] private static extern void _setAdvertisingID(); @@ -38,9 +38,6 @@ internal class QonversionWrapperIOS : IQonversionWrapper [DllImport("__Internal")] private static extern void _setUserProperty(string key, string value); - [DllImport("__Internal")] - private static extern void _launchWithKey(string key, string callbackName); - [DllImport("__Internal")] private static extern void _addAttributionData(string conversionData, string providerName); @@ -50,6 +47,9 @@ internal class QonversionWrapperIOS : IQonversionWrapper [DllImport("__Internal")] private static extern void _restore(string callbackName); + [DllImport("__Internal")] + private static extern void _userInfo(string callbackName); + [DllImport("__Internal")] private static extern void _purchase(string productID, string callbackName); @@ -63,28 +63,13 @@ internal class QonversionWrapperIOS : IQonversionWrapper private static extern void _offerings(string callbackName); [DllImport("__Internal")] - private static extern void _checkTrialIntroEligibilityForProductIds(string productIdsJson, string callbackName); + private static extern void _checkTrialIntroEligibility(string productIdsJson, string callbackName); [DllImport("__Internal")] private static extern void _promoPurchase(string storeProductId, string callbackName); - [DllImport("__Internal")] - private static extern void _setNotificationsToken(string token); - - [DllImport("__Internal")] - private static extern bool _handleNotification(string notification); - - [DllImport("__Internal")] - private static extern string _getNotificationCustomPayload(string notification); - - [DllImport("__Internal")] - private static extern void _subscribeOnAutomationEvents(); - [DllImport("__Internal")] private static extern void _presentCodeRedemptionSheet(); - - [DllImport("__Internal")] - private static extern void _setPermissionsCacheLifetime(string lifetimeKey); #endif public void Initialize(string gameObjectName) @@ -101,10 +86,10 @@ public void StoreSdkInfo(string version, string source) #endif } - public void Launch(string projectKey, bool observerMode, string callbackName) + public void InitializeSdk(string projectKey, string launchMode, string environment, string entitlementsCacheLifetime) { #if UNITY_IOS - _launchWithKey(projectKey, callbackName); + _initializeSdk(projectKey, launchMode, environment, entitlementsCacheLifetime); #endif } @@ -112,13 +97,6 @@ public void SyncPurchases() { } - public void SetDebugMode() - { -#if UNITY_IOS - _setDebugMode(); -#endif - } - public void SetAdvertisingID() { #if UNITY_IOS @@ -141,11 +119,10 @@ public void SetProperty(UserProperty key, string value) #endif } - public void AddAttributionData(string conversionData, AttributionSource source) + public void AddAttributionData(string conversionData, string providerName) { #if UNITY_IOS - string sourceName = Enum.GetName(typeof(AttributionSource), source); - _addAttributionData(conversionData, sourceName); + _addAttributionData(conversionData, providerName); #endif } @@ -170,6 +147,13 @@ public void Logout() #endif } + public void UserInfo(string callbackName) + { +#if UNITY_IOS + _userInfo(callbackName); +#endif + } + public void PresentCodeRedemptionSheet() { #if UNITY_IOS @@ -177,7 +161,7 @@ public void PresentCodeRedemptionSheet() #endif } - public void CheckPermissions(string callbackName) + public void CheckEntitlements(string callbackName) { #if UNITY_IOS _checkPermissions(callbackName); @@ -227,10 +211,10 @@ public void Offerings(string callbackName) #endif } - public void CheckTrialIntroEligibilityForProductIds(string productIdsJson, string callbackName) + public void CheckTrialIntroEligibility(string productIdsJson, string callbackName) { #if UNITY_IOS - _checkTrialIntroEligibilityForProductIds(productIdsJson, callbackName); + _checkTrialIntroEligibility(productIdsJson, callbackName); #endif } @@ -238,45 +222,6 @@ public void PromoPurchase(string storeProductId, string callbackName) { #if UNITY_IOS _promoPurchase(storeProductId, callbackName); -#endif - } - - public void SetNotificationsToken(string token) - { -#if UNITY_IOS - _setNotificationsToken(token); -#endif - } - - public bool HandleNotification(string notification) - { -#if UNITY_IOS - return _handleNotification(notification); -#else - return false; -#endif - } - - public string GetNotificationCustomPayload(string notification) - { -#if UNITY_IOS - return _getNotificationCustomPayload(notification); -#else - return null; -#endif - } - - public void SubscribeOnAutomationEvents() - { -#if UNITY_IOS - _subscribeOnAutomationEvents(); -#endif - } - - public void SetPermissionsCacheLifetime(string lifetime) - { -#if UNITY_IOS - _setPermissionsCacheLifetime(lifetime); #endif } } diff --git a/fastlane.meta b/fastlane.meta new file mode 100644 index 0000000..c89bbe8 --- /dev/null +++ b/fastlane.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 089159a4944c04210aeeacfd063d3601 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/fastlane/README.md.meta b/fastlane/README.md.meta new file mode 100644 index 0000000..cce087c --- /dev/null +++ b/fastlane/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0f7d66a11e8894098917aa1f4ef1507a +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/fastlane/fastfile b/fastlane/fastfile index 5df9606..ed6cdd9 100644 --- a/fastlane/fastfile +++ b/fastlane/fastfile @@ -7,7 +7,7 @@ def update_package_json(new_version) end def update_constant(new_version) - path = "../Runtime/Scripts/Qonversion.cs" + path = "../Runtime/Scripts/Internal/QonversionInternal.cs" regex = /private const string SdkVersion = ".*";/ result_value = "private const string SdkVersion = \"#{new_version}\";" diff --git a/fastlane/fastfile.meta b/fastlane/fastfile.meta new file mode 100644 index 0000000..a3d1619 --- /dev/null +++ b/fastlane/fastfile.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0490d362f09d34421838ef526cb8839d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/fastlane/report.xml.meta b/fastlane/report.xml.meta new file mode 100644 index 0000000..a220bb7 --- /dev/null +++ b/fastlane/report.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ce3590874b3444ee79db9c2164fd95be +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/img/UnityQonversionLauncher.png.meta b/img/UnityQonversionLauncher.png.meta new file mode 100644 index 0000000..e1575e5 --- /dev/null +++ b/img/UnityQonversionLauncher.png.meta @@ -0,0 +1,98 @@ +fileFormatVersion: 2 +guid: 721fa4cd076d647b7a88c24f5c0e1aec +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json index 2fb7af6..ab6f250 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.qonversion.unity", "displayName": "Qonversion", - "version": "3.7.1", + "version": "4.0.0", "unity": "2018.3", "description": "Empower your mobile app marketing and product decisions with precise subscription data.", "author": { @@ -29,5 +29,6 @@ "/Runtime.meta", "/Editor", "/Editor.meta" - ] + ], + "dependencies": {} }