From 37abcfd1d332a8702a51d178db8f8b6b4089c248 Mon Sep 17 00:00:00 2001 From: "piyush.kukadiya" Date: Mon, 6 Nov 2023 17:45:03 +0530 Subject: [PATCH] feat(inapp) - check hasInAppFrequencyLimitsMaxedOut logic after removing in-app from queue and before display, remove old session based logic SDK-3385 --- .../clevertap/android/sdk/InAppFCManager.java | 63 ++++++------------- .../android/sdk/inapp/InAppController.java | 13 +++- 2 files changed, 30 insertions(+), 46 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppFCManager.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppFCManager.java index 287996e78..ec8c659ed 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppFCManager.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppFCManager.java @@ -4,27 +4,22 @@ import android.content.Context; import android.content.SharedPreferences; - import androidx.annotation.RestrictTo; import androidx.annotation.RestrictTo.Scope; - import com.clevertap.android.sdk.inapp.CTInAppNotification; import com.clevertap.android.sdk.inapp.ImpressionManager; import com.clevertap.android.sdk.inapp.SharedPreferencesMigration; import com.clevertap.android.sdk.task.CTExecutorFactory; import com.clevertap.android.sdk.task.Task; - -import org.json.JSONArray; -import org.json.JSONObject; - import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.Locale; import java.util.Map; import java.util.concurrent.Callable; - import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function2; +import org.json.JSONArray; +import org.json.JSONObject; @RestrictTo(Scope.LIBRARY) public class InAppFCManager { @@ -37,15 +32,8 @@ public class InAppFCManager { private String deviceId; - private final ArrayList mDismissedThisSession = new ArrayList<>(); - -// private final HashMap mShownThisSession = new HashMap<>(); -// -// private int mShownThisSessionCount = 0; -// private ImpressionManager impressionManager; - InAppFCManager(Context context, CleverTapInstanceConfig config, String deviceId/*, ImpressionManager impressionManager*/) { this.config = config; this.context = context; @@ -53,7 +41,7 @@ public class InAppFCManager { /*this.impressionManager = impressionManager;*/ // TODO Task task = CTExecutorFactory.executors(config).postAsyncSafelyTask(); - task.execute("initInAppFCManager",new Callable() { + task.execute("initInAppFCManager", new Callable() { @Override public Void call() { init(InAppFCManager.this.deviceId); @@ -62,7 +50,9 @@ public Void call() { }); } - public boolean canShow(CTInAppNotification inapp) { + + public boolean canShow(CTInAppNotification inapp, + Function2 hasInAppFrequencyLimitsMaxedOut) { try { if (inapp == null) { return false; @@ -73,13 +63,20 @@ public boolean canShow(CTInAppNotification inapp) { return true; } + + /* Evaluate frequency limits again (without Nth triggers) + in case the message was added multiple times before being displayed, + or queue was paused and the message was added multiple times in the meantime + */ + if (hasInAppFrequencyLimitsMaxedOut.invoke(inapp.getJsonDescription(), id)) { + return false; + } + // Exclude from all caps? if (inapp.isExcludeFromCaps()) { return true; } - // TODO check new flag for exclude from caps - if (!hasSessionCapacityMaxedOut(inapp) && !hasLifetimeCapacityMaxedOut(inapp) && !hasDailyCapacityMaxedOut(inapp)) { @@ -93,19 +90,13 @@ public boolean canShow(CTInAppNotification inapp) { public void changeUser(String deviceId) { // reset counters -// mShownThisSession.clear(); -// mShownThisSessionCount = 0; impressionManager.clearSessionData(); // TODO change deviceId in manager - mDismissedThisSession.clear(); this.deviceId = deviceId; init(deviceId); } public void didDismiss(CTInAppNotification inapp) { - final Object id = inapp.getId(); - if (id != null) { - mDismissedThisSession.add(id.toString()); - } + // NO-OP } public void didShow(final Context context, CTInAppNotification inapp) { @@ -115,14 +106,6 @@ public void didShow(final Context context, CTInAppNotification inapp) { } impressionManager.recordImpression(id); -// mShownThisSessionCount++; - -// Integer count = mShownThisSession.get(id); -// if (count == null) { -// count = 1; -// } - -// mShownThisSession.put(id, ++count); incrementInAppCountsInPersistentStore(id); @@ -229,7 +212,7 @@ private int[] getInAppCountsFromPersistentStore(String inappID) { } } - private String getInAppID(CTInAppNotification inapp) { + public String getInAppID(CTInAppNotification inapp) { if (inapp.getId() == null) { return null; } @@ -329,19 +312,12 @@ private boolean hasSessionCapacityMaxedOut(CTInAppNotification inapp) { return false; } - // TODO mDismissedThisSession should be removed - // 1. Has this been dismissed? - if (mDismissedThisSession.contains(id)) { - return true; - } - // 2. Has the session max count for this inapp been breached? try { final int maxPerSession = inapp.getMaxPerSession() >= 0 ? inapp.getMaxPerSession() : 1000; - //Integer c = mShownThisSession.get(id); int c = impressionManager.perSession(id); - if (/*c != null && */c >= maxPerSession) { + if (c >= maxPerSession) { return true; } } catch (Throwable t) { @@ -352,7 +328,6 @@ private boolean hasSessionCapacityMaxedOut(CTInAppNotification inapp) { final int c = getIntFromPrefs(getKeyWithDeviceId(Constants.INAPP_MAX_PER_SESSION_KEY, deviceId), 1); int sessionTotal = impressionManager.perSessionTotal(); return (sessionTotal >= c); -// return (mShownThisSessionCount >= c); } private void incrementInAppCountsInPersistentStore(String inappID) { diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index d23cbc6c4..2b638ffbb 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -35,8 +35,10 @@ import com.clevertap.android.sdk.PushPermissionResponseListener; import com.clevertap.android.sdk.StorageHelper; import com.clevertap.android.sdk.Utils; -import com.clevertap.android.sdk.inapp.evaluation.EvaluationManager; +import com.clevertap.android.sdk.inapp.data.InAppResponseAdapter; import com.clevertap.android.sdk.inapp.data.InAppServerSide; +import com.clevertap.android.sdk.inapp.evaluation.EvaluationManager; +import com.clevertap.android.sdk.inapp.evaluation.LimitAdapter; import com.clevertap.android.sdk.task.CTExecutorFactory; import com.clevertap.android.sdk.task.MainLooperHandler; import com.clevertap.android.sdk.task.Task; @@ -52,6 +54,7 @@ import java.util.concurrent.Callable; import kotlin.Unit; import kotlin.jvm.functions.Function0; +import kotlin.jvm.functions.Function2; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -523,7 +526,13 @@ public void run() { } if (controllerManager.getInAppFCManager() != null) { - if (!controllerManager.getInAppFCManager().canShow(inAppNotification)) { + + final Function2 hasInAppFrequencyLimitsMaxedOut = (inAppJSON, inAppId) -> { + final List listOfWhenLimits = InAppResponseAdapter.getListOfWhenLimits(inAppJSON); + return evaluationManager.matchWhenLimitsBeforeDisplay(listOfWhenLimits, inAppId); + }; + + if (!controllerManager.getInAppFCManager().canShow(inAppNotification, hasInAppFrequencyLimitsMaxedOut)) { logger.verbose(config.getAccountId(), "InApp has been rejected by FC, not showing " + inAppNotification.getCampaignId()); showInAppNotificationIfAny();