From b374b1208dbd241ee0400625c3ea5fd1da417aab Mon Sep 17 00:00:00 2001 From: Akshay Ayyanchira Date: Wed, 14 Jun 2023 13:24:37 -0700 Subject: [PATCH 1/4] [MOB 5730] Add callbacks to reading/removing in-app messages (#557) (#583) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [MOB 5730] Add callbacks to reading/removing in-app messages (#557) * add callback for setRead/removeMessage * modify test for setRead and added test for removeMessage * fixes * Update build.gradle * removed resultcallbackhandler * Update IterableInAppManager.java * fixes --------- Co-authored-by: Akshay Ayyanchira Co-authored-by: Hardik Mashru * Fixing and adding test method --------- Co-authored-by: devcsomnicg <129495456+devcsomnicg@users.noreply.github.com> Co-authored-by: Hardik Mashru Co-authored-by: “Akshay <“ayyanchira.akshay@gmail.com”> --- .../ui/inbox/IterableInboxFragment.java | 4 +- .../com/iterable/iterableapi/IterableApi.java | 40 ++++++++- .../iterableapi/IterableApiClient.java | 4 +- ...IterableInAppFragmentHTMLNotification.java | 2 +- .../iterableapi/IterableInAppManager.java | 20 +++-- .../iterableapi/IterableInboxTest.java | 88 ++++++++++++++++++- 6 files changed, 143 insertions(+), 15 deletions(-) diff --git a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java index b57e8e8d1..7a0eb4fb3 100644 --- a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java +++ b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java @@ -244,7 +244,7 @@ public void onInboxUpdated() { @Override public void onListItemTapped(@NonNull IterableInAppMessage message) { - IterableApi.getInstance().getInAppManager().setRead(message, true); + IterableApi.getInstance().getInAppManager().setRead(message, true, null); if (inboxMode == InboxMode.ACTIVITY) { startActivity(new Intent(getContext(), IterableInboxMessageActivity.class).putExtra(IterableInboxMessageActivity.ARG_MESSAGE_ID, message.getMessageId())); @@ -255,7 +255,7 @@ public void onListItemTapped(@NonNull IterableInAppMessage message) { @Override public void onListItemDeleted(@NonNull IterableInAppMessage message, @NonNull IterableInAppDeleteActionType source) { - IterableApi.getInstance().getInAppManager().removeMessage(message, source, IterableInAppLocation.INBOX); + IterableApi.getInstance().getInAppManager().removeMessage(message, source, IterableInAppLocation.INBOX, null, null); } @Override diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java index d793b9621..5aa76d727 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java @@ -725,7 +725,26 @@ public void inAppConsume(@NonNull String messageId) { IterableLogger.e(TAG, "inAppConsume: message is null"); return; } - inAppConsume(message, null, null); + inAppConsume(message, null, null, null, null); + IterableLogger.printInfo(); + } + + /** + * Consumes an InApp message. + * @param messageId + * @param successHandler The callback which returns `success`. + * @param failureHandler The callback which returns `failure`. + */ + public void inAppConsume(@NonNull String messageId, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { + IterableInAppMessage message = getInAppManager().getMessageById(messageId); + if (message == null) { + IterableLogger.e(TAG, "inAppConsume: message is null"); + if (failureHandler != null) { + failureHandler.onFailure("inAppConsume: message is null", null); + } + return; + } + inAppConsume(message, null, null, successHandler, failureHandler); IterableLogger.printInfo(); } @@ -742,8 +761,25 @@ public void inAppConsume(@NonNull IterableInAppMessage message, @Nullable Iterab if (!checkSDKInitialization()) { return; } + apiClient.inAppConsume(message, source, clickLocation, inboxSessionId, null, null); + } - apiClient.inAppConsume(message, source, clickLocation, inboxSessionId); + /** + * Tracks InApp delete. + * This method from informs Iterable about inApp messages deleted with additional paramters. + * Call this method from places where inApp deletion are invoked by user. The messages can be swiped to delete or can be deleted using the link to delete button. + * + * @param message message object + * @param source An enum describing how the in App delete was triggered + * @param clickLocation The module in which the action happened + * @param successHandler The callback which returns `success`. + * @param failureHandler The callback which returns `failure`. + */ + public void inAppConsume(@NonNull IterableInAppMessage message, @Nullable IterableInAppDeleteActionType source, @Nullable IterableInAppLocation clickLocation, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { + if (!checkSDKInitialization()) { + return; + } + apiClient.inAppConsume(message, source, clickLocation, inboxSessionId, successHandler, failureHandler); } /** diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApiClient.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApiClient.java index 0a3d9914f..e190c0aa0 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApiClient.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApiClient.java @@ -317,7 +317,7 @@ void trackInAppDelivery(@NonNull IterableInAppMessage message) { } } - public void inAppConsume(@NonNull IterableInAppMessage message, @Nullable IterableInAppDeleteActionType source, @Nullable IterableInAppLocation clickLocation, @Nullable String inboxSessionId) { + public void inAppConsume(@NonNull IterableInAppMessage message, @Nullable IterableInAppDeleteActionType source, @Nullable IterableInAppLocation clickLocation, @Nullable String inboxSessionId, @Nullable final IterableHelper.SuccessHandler successHandler, @Nullable final IterableHelper.FailureHandler failureHandler) { JSONObject requestJSON = new JSONObject(); try { @@ -336,7 +336,7 @@ public void inAppConsume(@NonNull IterableInAppMessage message, @Nullable Iterab addInboxSessionID(requestJSON, inboxSessionId); } - sendPostRequest(IterableConstants.ENDPOINT_INAPP_CONSUME, requestJSON); + sendPostRequest(IterableConstants.ENDPOINT_INAPP_CONSUME, requestJSON, successHandler, failureHandler); } catch (JSONException e) { e.printStackTrace(); } diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java index ba11b3c2e..d5ca9655a 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java @@ -417,7 +417,7 @@ private void processMessageRemoval() { } if (message.isMarkedForDeletion() && !message.isConsumed()) { - IterableApi.sharedInstance.getInAppManager().removeMessage(message); + IterableApi.sharedInstance.getInAppManager().removeMessage(message, null, null); } } diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppManager.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppManager.java index 8fc294497..05c292a6d 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppManager.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppManager.java @@ -132,9 +132,13 @@ public synchronized int getUnreadInboxMessagesCount() { * Set the read flag on an inbox message * @param message Inbox message object retrieved from {@link IterableInAppManager#getInboxMessages()} * @param read Read state flag. true = read, false = unread + * @param successHandler The callback which returns `success`. */ - public synchronized void setRead(@NonNull IterableInAppMessage message, boolean read) { + public synchronized void setRead(@NonNull IterableInAppMessage message, boolean read, @Nullable IterableHelper.SuccessHandler successHandler) { message.setRead(read); + if (successHandler != null) { + successHandler.onSuccess(new JSONObject()); // passing blank json object here as onSuccess is @Nonnull + } notifyOnChange(); } @@ -239,7 +243,7 @@ public void execute(Uri url) { scheduleProcessing(); } })) { - setRead(message, true); + setRead(message, true, null); if (consume) { message.markForDeletion(true); } @@ -249,17 +253,19 @@ public void execute(Uri url) { /** * Remove message from the list * @param message The message to be removed + * @param successHandler The callback which returns `success`. + * @param failureHandler The callback which returns `failure`. */ - public synchronized void removeMessage(@NonNull IterableInAppMessage message) { + public synchronized void removeMessage(@NonNull IterableInAppMessage message, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { message.setConsumed(true); - api.inAppConsume(message.getMessageId()); + api.inAppConsume(message.getMessageId(), successHandler, failureHandler); notifyOnChange(); } - public synchronized void removeMessage(@NonNull IterableInAppMessage message, @NonNull IterableInAppDeleteActionType source, @NonNull IterableInAppLocation clickLocation) { + public synchronized void removeMessage(@NonNull IterableInAppMessage message, @NonNull IterableInAppDeleteActionType source, @NonNull IterableInAppLocation clickLocation, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { IterableLogger.printInfo(); message.setConsumed(true); - api.inAppConsume(message, source, clickLocation); + api.inAppConsume(message, source, clickLocation, successHandler, failureHandler); notifyOnChange(); } @@ -432,7 +438,7 @@ private boolean canShowInAppAfterPrevious() { private void handleIterableCustomAction(String actionName, IterableInAppMessage message) { if (IterableConstants.ITERABLE_IN_APP_ACTION_DELETE.equals(actionName)) { - removeMessage(message, IterableInAppDeleteActionType.DELETE_BUTTON, IterableInAppLocation.IN_APP); + removeMessage(message, IterableInAppDeleteActionType.DELETE_BUTTON, IterableInAppLocation.IN_APP, null, null); } } diff --git a/iterableapi/src/test/java/com/iterable/iterableapi/IterableInboxTest.java b/iterableapi/src/test/java/com/iterable/iterableapi/IterableInboxTest.java index 3e324208c..1697c381d 100644 --- a/iterableapi/src/test/java/com/iterable/iterableapi/IterableInboxTest.java +++ b/iterableapi/src/test/java/com/iterable/iterableapi/IterableInboxTest.java @@ -2,8 +2,12 @@ import android.app.Activity; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.iterable.iterableapi.unit.PathBasedQueueDispatcher; +import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -11,6 +15,8 @@ import java.io.IOException; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; @@ -78,18 +84,98 @@ public void testInboxMessageOrdering() throws Exception { assertEquals("message4", inboxMessages.get(1).getMessageId()); } + @Test + public void testRemoveMessageSuccessCallbackOnSuccessfulResponse() throws Exception { + final CountDownLatch signal = new CountDownLatch(1); + dispatcher.enqueueResponse("/inApp/getMessages", new MockResponse().setBody(IterableTestUtils.getResourceString("inapp_payload_inbox_multiple.json"))); + final IterableInAppManager inAppManager = IterableApi.getInstance().getInAppManager(); + inAppManager.syncInApp(); + shadowOf(getMainLooper()).idle(); + List inboxMessages = inAppManager.getInboxMessages(); + assertEquals(2, inboxMessages.size()); + assertEquals(1, inAppManager.getUnreadInboxMessagesCount()); + + final JSONObject responseData = new JSONObject("{\"key\":\"value\"}"); + dispatcher.enqueueResponse("/events/inAppConsume", new MockResponse().setResponseCode(200).setBody(responseData.toString())); + + inAppManager.removeMessage(inboxMessages.get(0), new IterableHelper.SuccessHandler() { + @Override + public void onSuccess(@NonNull JSONObject data) { + signal.countDown(); + } + }, new IterableHelper.FailureHandler() { + @Override + public void onFailure(@NonNull String reason, @Nullable JSONObject data) { + assertFalse(true); + } + }); + shadowOf(getMainLooper()).idle(); + assertTrue("Message remove success callback called", signal.await(1, TimeUnit.SECONDS)); + } + + @Test + public void testRemoveMessageFailureCallbackOnFailedResponse() throws Exception { + final CountDownLatch signal = new CountDownLatch(1); + dispatcher.enqueueResponse("/inApp/getMessages", new MockResponse().setBody(IterableTestUtils.getResourceString("inapp_payload_inbox_multiple.json"))); + final IterableInAppManager inAppManager = IterableApi.getInstance().getInAppManager(); + inAppManager.syncInApp(); + shadowOf(getMainLooper()).idle(); + List inboxMessages = inAppManager.getInboxMessages(); + assertEquals(2, inboxMessages.size()); + assertEquals(1, inAppManager.getUnreadInboxMessagesCount()); + + final JSONObject responseData = new JSONObject("{\"key\":\"value\"}"); + dispatcher.enqueueResponse("/events/inAppConsume", new MockResponse().setResponseCode(500).setBody(responseData.toString())); + + inAppManager.removeMessage(inboxMessages.get(0), new IterableHelper.SuccessHandler() { + @Override + public void onSuccess(@NonNull JSONObject data) { + assertFalse(true); + } + }, new IterableHelper.FailureHandler() { + @Override + public void onFailure(@NonNull String reason, @Nullable JSONObject data) { + signal.countDown(); + } + }); + shadowOf(getMainLooper()).idle(); + assertTrue("Message remove failure callback called", signal.await(1, TimeUnit.SECONDS)); + } + @Test public void testSetRead() throws Exception { + // Set up mock response dispatcher.enqueueResponse("/inApp/getMessages", new MockResponse().setBody(IterableTestUtils.getResourceString("inapp_payload_inbox_multiple.json"))); + + // Initialize in-app manager and wait for messages to be synced IterableInAppManager inAppManager = IterableApi.getInstance().getInAppManager(); inAppManager.syncInApp(); shadowOf(getMainLooper()).idle(); + + // Get inbox messages List inboxMessages = inAppManager.getInboxMessages(); + + // Verify initial state assertEquals(1, inAppManager.getUnreadInboxMessagesCount()); assertEquals(2, inboxMessages.size()); assertFalse(inboxMessages.get(0).isRead()); assertTrue(inboxMessages.get(1).isRead()); - inAppManager.setRead(inboxMessages.get(0), true); + + // Set first message as read with a callback + final boolean[] callbackCalled = { false }; + inAppManager.setRead(inboxMessages.get(0), true, new IterableHelper.SuccessHandler() { + @Override + public void onSuccess(@NonNull JSONObject data) { + callbackCalled[0] = true; + assertTrue(callbackCalled[0]); + } + }); + + // Wait for callback to be called + shadowOf(getMainLooper()).idle(); + + // Verify that callback was called and that message is marked as read + assertTrue(callbackCalled[0]); assertEquals(0, inAppManager.getUnreadInboxMessagesCount()); assertEquals(2, inAppManager.getInboxMessages().size()); assertTrue(inboxMessages.get(0).isRead()); From efa8d3ac35948aa514ac368ffcaa9bc18beb3eb5 Mon Sep 17 00:00:00 2001 From: Akshay Ayyanchira Date: Wed, 12 Jul 2023 06:35:59 -0700 Subject: [PATCH 2/4] [MOB - 6493] - Message read and remove bug fix (#592) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: “Akshay <“ayyanchira.akshay@gmail.com”> --- .../ui/inbox/IterableInboxFragment.java | 4 +-- .../iterableapi/IterableInAppManager.java | 35 ++++++++++++++----- .../iterableapi/IterableInboxTest.java | 9 +++-- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java index 7a0eb4fb3..3c5f2aa1e 100644 --- a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java +++ b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/inbox/IterableInboxFragment.java @@ -244,7 +244,7 @@ public void onInboxUpdated() { @Override public void onListItemTapped(@NonNull IterableInAppMessage message) { - IterableApi.getInstance().getInAppManager().setRead(message, true, null); + IterableApi.getInstance().getInAppManager().setRead(message, true, null, null); if (inboxMode == InboxMode.ACTIVITY) { startActivity(new Intent(getContext(), IterableInboxMessageActivity.class).putExtra(IterableInboxMessageActivity.ARG_MESSAGE_ID, message.getMessageId())); @@ -255,7 +255,7 @@ public void onListItemTapped(@NonNull IterableInAppMessage message) { @Override public void onListItemDeleted(@NonNull IterableInAppMessage message, @NonNull IterableInAppDeleteActionType source) { - IterableApi.getInstance().getInAppManager().removeMessage(message, source, IterableInAppLocation.INBOX, null, null); + IterableApi.getInstance().getInAppManager().removeMessage(message, source, IterableInAppLocation.INBOX); } @Override diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppManager.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppManager.java index 05c292a6d..d5c06bfc8 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppManager.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppManager.java @@ -128,13 +128,16 @@ public synchronized int getUnreadInboxMessagesCount() { return unreadInboxMessageCount; } + public synchronized void setRead(@NonNull IterableInAppMessage message, boolean read) { + setRead(message, read, null, null); + } /** * Set the read flag on an inbox message * @param message Inbox message object retrieved from {@link IterableInAppManager#getInboxMessages()} * @param read Read state flag. true = read, false = unread * @param successHandler The callback which returns `success`. */ - public synchronized void setRead(@NonNull IterableInAppMessage message, boolean read, @Nullable IterableHelper.SuccessHandler successHandler) { + public synchronized void setRead(@NonNull IterableInAppMessage message, boolean read, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { message.setRead(read); if (successHandler != null) { successHandler.onSuccess(new JSONObject()); // passing blank json object here as onSuccess is @Nonnull @@ -243,7 +246,7 @@ public void execute(Uri url) { scheduleProcessing(); } })) { - setRead(message, true, null); + setRead(message, true, null, null); if (consume) { message.markForDeletion(true); } @@ -253,16 +256,30 @@ public void execute(Uri url) { /** * Remove message from the list * @param message The message to be removed - * @param successHandler The callback which returns `success`. - * @param failureHandler The callback which returns `failure`. */ - public synchronized void removeMessage(@NonNull IterableInAppMessage message, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { - message.setConsumed(true); - api.inAppConsume(message.getMessageId(), successHandler, failureHandler); - notifyOnChange(); + public synchronized void removeMessage(@NonNull IterableInAppMessage message) { + removeMessage(message, null, null, null, null); } - public synchronized void removeMessage(@NonNull IterableInAppMessage message, @NonNull IterableInAppDeleteActionType source, @NonNull IterableInAppLocation clickLocation, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { + /** + * Remove message from the list + * @param message The message to be removed + * @param source Source from where the message removal occured. Use IterableInAppDeleteActionType for available sources + * @param clickLocation Where was the message clicked. Use IterableInAppLocation for available Click Locations + */ + public synchronized void removeMessage(@NonNull IterableInAppMessage message, @NonNull IterableInAppDeleteActionType source, @NonNull IterableInAppLocation clickLocation) { + removeMessage(message, source, clickLocation, null, null); + } + + /** + * Remove message from the list + * @param message The message to be removed + * @param source Source from where the message removal occured. Use IterableInAppDeleteActionType for available sources + * @param clickLocation Where was the message clicked. Use IterableInAppLocation for available Click Locations + * @param successHandler The callback which returns `success`. + * @param failureHandler The callback which returns `failure`. + */ + public synchronized void removeMessage(@NonNull IterableInAppMessage message, @Nullable IterableInAppDeleteActionType source, @Nullable IterableInAppLocation clickLocation, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { IterableLogger.printInfo(); message.setConsumed(true); api.inAppConsume(message, source, clickLocation, successHandler, failureHandler); diff --git a/iterableapi/src/test/java/com/iterable/iterableapi/IterableInboxTest.java b/iterableapi/src/test/java/com/iterable/iterableapi/IterableInboxTest.java index 1697c381d..868cb12b6 100644 --- a/iterableapi/src/test/java/com/iterable/iterableapi/IterableInboxTest.java +++ b/iterableapi/src/test/java/com/iterable/iterableapi/IterableInboxTest.java @@ -98,7 +98,7 @@ public void testRemoveMessageSuccessCallbackOnSuccessfulResponse() throws Except final JSONObject responseData = new JSONObject("{\"key\":\"value\"}"); dispatcher.enqueueResponse("/events/inAppConsume", new MockResponse().setResponseCode(200).setBody(responseData.toString())); - inAppManager.removeMessage(inboxMessages.get(0), new IterableHelper.SuccessHandler() { + inAppManager.removeMessage(inboxMessages.get(0), null, null, new IterableHelper.SuccessHandler() { @Override public void onSuccess(@NonNull JSONObject data) { signal.countDown(); @@ -127,7 +127,7 @@ public void testRemoveMessageFailureCallbackOnFailedResponse() throws Exception final JSONObject responseData = new JSONObject("{\"key\":\"value\"}"); dispatcher.enqueueResponse("/events/inAppConsume", new MockResponse().setResponseCode(500).setBody(responseData.toString())); - inAppManager.removeMessage(inboxMessages.get(0), new IterableHelper.SuccessHandler() { + inAppManager.removeMessage(inboxMessages.get(0), null, null, new IterableHelper.SuccessHandler() { @Override public void onSuccess(@NonNull JSONObject data) { assertFalse(true); @@ -169,6 +169,11 @@ public void onSuccess(@NonNull JSONObject data) { callbackCalled[0] = true; assertTrue(callbackCalled[0]); } + }, new IterableHelper.FailureHandler() { + @Override + public void onFailure(@NonNull String reason, @Nullable JSONObject data) { + assertFalse(true); + } }); // Wait for callback to be called From b780ec4e91562653bf14fef719fca63a7439e0e1 Mon Sep 17 00:00:00 2001 From: Akshay Ayyanchira Date: Wed, 12 Jul 2023 06:52:12 -0700 Subject: [PATCH 3/4] MOB-5132: Fix deep link issue after app is opened from notification (#546) (#593) Co-authored-by: devcsomnicg <129495456+devcsomnicg@users.noreply.github.com> --- .../com/iterable/iterableapi/IterableNotificationHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java index f005010c2..2625b32bf 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java @@ -194,7 +194,7 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex trampolineActivityIntent.setClass(context, IterableTrampolineActivity.class); trampolineActivityIntent.putExtras(extras); trampolineActivityIntent.putExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, IterableConstants.ITERABLE_ACTION_DEFAULT); - trampolineActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + trampolineActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // Action buttons if (notificationData.getActionButtons() != null) { From 6f5a80579a019f47a108f795e72effd728dd6cba Mon Sep 17 00:00:00 2001 From: Evan Takeo Kanaiaupuni Greer <56953678+evantk91@users.noreply.github.com> Date: Mon, 17 Jul 2023 11:20:49 -0600 Subject: [PATCH 4/4] [MOB-6309] prepares EUDC updates for release (#572) * stashed changes * adds data center to config and associated unit tests * adds excluding kotlin files to javadoc check * moves IterableDataRegion to IterableConstants.java * gets rid of extra lines * removes jacoco.exe * adds endpoint override to IterableApi * removes logging statement * sets up base url at IterableRequestTask * minor edits * refactors to pull endpoint directly from config value * removes unfinished unit test * removes jacoco.exec * removes white space --------- Co-authored-by: evan.greer@iterable.com --- iterableapi/build.gradle | 3 +++ .../iterable/iterableapi/IterableConfig.java | 20 ++++++++++++++-- .../iterableapi/IterableConstants.java | 2 +- .../iterableapi/IterableDataRegion.java | 16 +++++++++++++ .../iterableapi/IterableRequestTask.java | 17 +++++++++++--- .../iterableapi/IterableConfigTest.kt | 23 +++++++++++++++++++ 6 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 iterableapi/src/main/java/com/iterable/iterableapi/IterableDataRegion.java create mode 100644 iterableapi/src/test/java/com/iterable/iterableapi/IterableConfigTest.kt diff --git a/iterableapi/build.gradle b/iterableapi/build.gradle index 16f001e99..51609aa78 100644 --- a/iterableapi/build.gradle +++ b/iterableapi/build.gradle @@ -51,6 +51,7 @@ dependencies { testImplementation 'org.khronos:opengl-api:gl1.1-android-2.1_r1' testImplementation 'com.squareup.okhttp3:mockwebserver:4.2.2' testImplementation 'org.skyscreamer:jsonassert:1.5.0' + testImplementation project(path: ':iterableapi') androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test:rules:1.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' @@ -90,6 +91,8 @@ if(hasProperty("mavenPublishEnabled")) { task javadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + + exclude '**/*.kt' } tasks.withType(Test) { diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java index 78eaaf5c9..a0945962c 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java @@ -71,6 +71,11 @@ public class IterableConfig { */ final String[] allowedProtocols; + /** + * Data region determining which data center and endpoints are used by the SDK. + */ + final IterableDataRegion dataRegion; + /** * This controls whether the in-app content should be saved to disk, or only kept in memory. * By default, the SDK will save in-apps to disk. @@ -89,6 +94,7 @@ private IterableConfig(Builder builder) { authHandler = builder.authHandler; expiringAuthTokenRefreshPeriod = builder.expiringAuthTokenRefreshPeriod; allowedProtocols = builder.allowedProtocols; + dataRegion = builder.dataRegion; useInMemoryStorageForInApps = builder.useInMemoryStorageForInApps; } @@ -104,6 +110,7 @@ public static class Builder { private IterableAuthHandler authHandler; private long expiringAuthTokenRefreshPeriod = 60000L; private String[] allowedProtocols = new String[0]; + private IterableDataRegion dataRegion = IterableDataRegion.US; private boolean useInMemoryStorageForInApps = false; public Builder() {} @@ -226,6 +233,16 @@ public Builder setAllowedProtocols(@NonNull String[] allowedProtocols) { return this; } + /** + * Set the data region used by the SDK + * @param dataRegion enum value that determines which endpoint to use, defaults to IterableDataRegion.US + */ + @NonNull + public Builder setDataRegion(@NonNull IterableDataRegion dataRegion) { + this.dataRegion = dataRegion; + return this; + } + /** * Set whether the SDK should store in-apps only in memory, or in file storage * @param useInMemoryStorageForInApps `true` will have in-apps be only in memory @@ -242,5 +259,4 @@ public IterableConfig build() { return new IterableConfig(this); } } - -} +} \ No newline at end of file diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConstants.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConstants.java index fabd9a3f4..985d60480 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConstants.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConstants.java @@ -252,4 +252,4 @@ public final class IterableConstants { public static final String NO_MESSAGES_TITLE = "noMessagesTitle"; public static final String NO_MESSAGES_BODY = "noMessagesBody"; -} +} \ No newline at end of file diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableDataRegion.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableDataRegion.java new file mode 100644 index 000000000..aec57c0f2 --- /dev/null +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableDataRegion.java @@ -0,0 +1,16 @@ +package com.iterable.iterableapi; + +public enum IterableDataRegion { + US("https://api.iterable.com/api/"), + EU("https://api.eu.iterable.com/api/"); + + private final String endpoint; + + IterableDataRegion(String endpoint) { + this.endpoint = endpoint; + } + + public String getEndpoint() { + return this.endpoint; + } +} diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableRequestTask.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableRequestTask.java index b0fd7ffe6..d5fe00046 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableRequestTask.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableRequestTask.java @@ -27,7 +27,6 @@ */ class IterableRequestTask extends AsyncTask { static final String TAG = "IterableRequest"; - static final String ITERABLE_BASE_URL = "https://api.iterable.com/api/"; static String overrideUrl; @@ -65,8 +64,8 @@ static IterableApiResponse executeApiRequest(IterableApiRequest iterableApiReque HttpURLConnection urlConnection = null; IterableLogger.v(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - String baseUrl = (iterableApiRequest.baseUrl != null && !iterableApiRequest.baseUrl.isEmpty()) ? iterableApiRequest.baseUrl : - ITERABLE_BASE_URL; + String baseUrl = getBaseUrl(); + try { if (overrideUrl != null && !overrideUrl.isEmpty()) { baseUrl = overrideUrl; @@ -225,6 +224,18 @@ static IterableApiResponse executeApiRequest(IterableApiRequest iterableApiReque return apiResponse; } + private static String getBaseUrl() { + IterableConfig config = IterableApi.getInstance().config; + IterableDataRegion dataRegion = config.dataRegion; + String baseUrl = dataRegion.getEndpoint(); + + if (overrideUrl != null && !overrideUrl.isEmpty()) { + baseUrl = overrideUrl; + } + + return baseUrl; + } + private static boolean matchesErrorCode(JSONObject jsonResponse, String errorCode) { try { return jsonResponse != null && jsonResponse.has("code") && jsonResponse.getString("code").equals(errorCode); diff --git a/iterableapi/src/test/java/com/iterable/iterableapi/IterableConfigTest.kt b/iterableapi/src/test/java/com/iterable/iterableapi/IterableConfigTest.kt new file mode 100644 index 000000000..1d5124815 --- /dev/null +++ b/iterableapi/src/test/java/com/iterable/iterableapi/IterableConfigTest.kt @@ -0,0 +1,23 @@ +package com.iterable.iterableapi + +import org.hamcrest.Matchers.`is` +import org.junit.Assert.* +import org.junit.Test + +class IterableConfigTest { + + @Test + fun defaultDataRegion() { + val configBuilder: IterableConfig.Builder = IterableConfig.Builder() + val config: IterableConfig = configBuilder.build() + assertThat(config.dataRegion, `is`(IterableDataRegion.US)) + } + + @Test + fun setDataRegionToEU() { + val configBuilder: IterableConfig.Builder = IterableConfig.Builder() + .setDataRegion(IterableDataRegion.EU) + val config: IterableConfig = configBuilder.build() + assertThat(config.dataRegion, `is`(IterableDataRegion.EU)) + } +} \ No newline at end of file