Skip to content

Commit a538083

Browse files
[SDK-302] New IterableEmbeddedUpdateHandler methods for sync failure and success. (#989)
1 parent 72060ae commit a538083

4 files changed

Lines changed: 90 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
55
## Unreleased
66
- Replaced the deprecated `AsyncTask`-based push notification handling with `WorkManager` for improved reliability and compatibility with modern Android versions. No action is required.
77
- Fixed lost event tracking and missed API calls with an auto-retry feature for JWT token failures.
8+
- Added `onEmbeddedMessagingSyncSucceeded()` and `onEmbeddedMessagingSyncFailed()` callbacks to `IterableEmbeddedUpdateHandler` for monitoring embedded message sync results.
89

910
## [3.6.6]
1011
### Fixed

iterableapi/src/main/java/com/iterable/iterableapi/IterableEmbeddedManager.kt

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.iterable.iterableapi
22

33
import android.content.Context
4-
import com.iterable.iterableapi.IterableHelper.SuccessHandler
54
import org.json.JSONException
65
import org.json.JSONObject
76

@@ -80,12 +79,8 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
8079
return localPlacementIds
8180
}
8281

83-
fun syncMessages() {
84-
syncMessages(emptyArray<Long>())
85-
}
86-
87-
//Network call to get the embedded messages
88-
fun syncMessages(placementIds: Array<Long>) {
82+
@JvmOverloads
83+
fun syncMessages(placementIds: Array<Long> = emptyArray()) {
8984
if (iterableApi.config.enableEmbeddedMessaging) {
9085
IterableLogger.v(TAG, "Syncing messages...")
9186

@@ -141,8 +136,10 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
141136
//store placements from payload for next comparison
142137
localPlacementIds = currentPlacementIds
143138

139+
notifySyncSucceeded()
144140
} catch (e: JSONException) {
145141
IterableLogger.e(TAG, e.toString())
142+
notifySyncFailed(e.message)
146143
}
147144
}, object : IterableHelper.FailureHandler {
148145
override fun onFailure(reason: String, data: JSONObject?) {
@@ -154,10 +151,9 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
154151
IterableLogger.e(TAG, "Subscription is inactive. Stopping sync")
155152
broadcastSubscriptionInactive()
156153
return
157-
} else {
158-
//TODO: Instead of generic condition, have the retry only in certain situation
159-
IterableLogger.e(TAG, "Error while fetching embedded messages: $reason")
160154
}
155+
IterableLogger.e(TAG, "Error while fetching embedded messages: $reason")
156+
notifySyncFailed(reason)
161157
}
162158
})
163159
}
@@ -191,6 +187,18 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
191187
}
192188
}
193189

190+
private fun notifySyncSucceeded() {
191+
updateHandleListeners.forEach {
192+
it.onEmbeddedMessagingSyncSucceeded()
193+
}
194+
}
195+
196+
private fun notifySyncFailed(reason: String?) {
197+
updateHandleListeners.forEach {
198+
it.onEmbeddedMessagingSyncFailed(reason)
199+
}
200+
}
201+
194202
private fun broadcastSubscriptionInactive() {
195203
updateHandleListeners.forEach {
196204
IterableLogger.d(TAG, "Broadcasting subscription inactive to the views")
@@ -263,7 +271,8 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
263271
public interface IterableEmbeddedUpdateHandler {
264272
fun onMessagesUpdated()
265273
fun onEmbeddedMessagingDisabled()
274+
fun onEmbeddedMessagingSyncSucceeded() {}
275+
fun onEmbeddedMessagingSyncFailed(reason: String?) {}
266276
}
267277

268278
// endregion
269-

iterableapi/src/test/java/com/iterable/iterableapi/IterableEmbeddedManagerTest.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import static android.os.Looper.getMainLooper;
44
import static junit.framework.Assert.assertEquals;
55
import static org.junit.Assert.assertNull;
6+
import static org.mockito.ArgumentMatchers.anyString;
7+
import static org.mockito.Mockito.clearInvocations;
68
import static org.mockito.Mockito.mock;
79
import static org.mockito.Mockito.never;
810
import static org.mockito.Mockito.spy;
@@ -265,4 +267,64 @@ public void testOnEmbeddedMessagingDisabled() throws Exception {
265267
verify(mockHandler1).onEmbeddedMessagingDisabled();
266268
}
267269

270+
@Test
271+
public void testOnEmbeddedMessagingSyncSucceeded() throws Exception {
272+
dispatcher.enqueueResponse("/embedded-messaging/messages", new MockResponse().setBody(IterableTestUtils.getResourceString("embedded_payload_single_1.json")));
273+
IterableEmbeddedManager embeddedManager = IterableApi.getInstance().getEmbeddedManager();
274+
// Flush all automatic syncs (init + foreground) before adding listener
275+
shadowOf(getMainLooper()).idle();
276+
277+
IterableEmbeddedUpdateHandler mockHandler = mock(IterableEmbeddedUpdateHandler.class);
278+
embeddedManager.addUpdateListener(mockHandler);
279+
280+
dispatcher.enqueueResponse("/embedded-messaging/messages", new MockResponse().setBody(IterableTestUtils.getResourceString("embedded_payload_single_1.json")));
281+
embeddedManager.syncMessages();
282+
shadowOf(getMainLooper()).idle();
283+
284+
verify(mockHandler).onEmbeddedMessagingSyncSucceeded();
285+
verify(mockHandler, never()).onEmbeddedMessagingSyncFailed(anyString());
286+
}
287+
288+
@Test
289+
public void testOnEmbeddedMessagingSyncFailedOnParseError() throws Exception {
290+
// Enqueue malformed responses so auto-syncs also fail (avoiding mixed success/failure)
291+
dispatcher.enqueueResponse("/embedded-messaging/messages", new MockResponse().setBody(IterableTestUtils.getResourceString("embedded_payload_malformed.json")));
292+
dispatcher.enqueueResponse("/embedded-messaging/messages", new MockResponse().setBody(IterableTestUtils.getResourceString("embedded_payload_malformed.json")));
293+
IterableEmbeddedManager embeddedManager = IterableApi.getInstance().getEmbeddedManager();
294+
295+
IterableEmbeddedUpdateHandler mockHandler = mock(IterableEmbeddedUpdateHandler.class);
296+
embeddedManager.addUpdateListener(mockHandler);
297+
shadowOf(getMainLooper()).idle();
298+
clearInvocations(mockHandler);
299+
300+
dispatcher.enqueueResponse("/embedded-messaging/messages", new MockResponse().setBody(IterableTestUtils.getResourceString("embedded_payload_malformed.json")));
301+
embeddedManager.syncMessages();
302+
shadowOf(getMainLooper()).idle();
303+
304+
verify(mockHandler).onEmbeddedMessagingSyncFailed(anyString());
305+
verify(mockHandler, never()).onEmbeddedMessagingSyncSucceeded();
306+
}
307+
308+
@Test
309+
public void testOnEmbeddedMessagingSyncFailed() throws Exception {
310+
// Enqueue 500 responses so auto-syncs also fail (avoiding mixed success/failure)
311+
// Note: 401 + "Invalid API Key" triggers the subscription-inactive path
312+
// (onEmbeddedMessagingDisabled), not the generic failure path (onEmbeddedMessagingSyncFailed)
313+
dispatcher.enqueueResponse("/embedded-messaging/messages", new MockResponse().setResponseCode(500));
314+
dispatcher.enqueueResponse("/embedded-messaging/messages", new MockResponse().setResponseCode(500));
315+
IterableEmbeddedManager embeddedManager = IterableApi.getInstance().getEmbeddedManager();
316+
317+
IterableEmbeddedUpdateHandler mockHandler = mock(IterableEmbeddedUpdateHandler.class);
318+
embeddedManager.addUpdateListener(mockHandler);
319+
shadowOf(getMainLooper()).idle();
320+
clearInvocations(mockHandler);
321+
322+
dispatcher.enqueueResponse("/embedded-messaging/messages", new MockResponse().setResponseCode(500));
323+
embeddedManager.syncMessages();
324+
shadowOf(getMainLooper()).idle();
325+
326+
verify(mockHandler).onEmbeddedMessagingSyncFailed(anyString());
327+
verify(mockHandler, never()).onEmbeddedMessagingSyncSucceeded();
328+
}
329+
268330
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"placements": [
3+
{
4+
"unexpectedField": "missingPlacementIdAndMessages"
5+
}
6+
]
7+
}

0 commit comments

Comments
 (0)