Skip to content

[MOB-9340] Fix for removing recalled campaigns from device memory #893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ android {
multiDexEnabled true
}

buildFeatures {
buildConfig true
}

Comment on lines +24 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets remove all the build and embedded related changes from this PR

buildTypes {
release {
minifyEnabled true
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.9.0'
ext.kotlin_version = '1.9.22'
ext.mavenPublishEnabled = true
repositories {
google()
jcenter()
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
Expand All @@ -26,7 +26,7 @@ buildscript {
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

Expand Down
14 changes: 10 additions & 4 deletions iterableapi-ui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ android {
targetCompatibility JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = "17"
}

publishing {
multipleVariants {
allVariants()
Expand Down Expand Up @@ -76,8 +80,10 @@ task javadoc(type: Javadoc) {
}

// A hack to import the classpath and BuildConfig into the javadoc task
afterEvaluate {
javadoc.classpath += files(android.libraryVariants.collect { variant -> variant.javaCompile.classpath.files })
javadoc.classpath += files(android.libraryVariants.collect { variant -> "build/generated/source/r/${variant.flavorName}/${variant.buildType.name}" })
javadoc.classpath += files(android.libraryVariants.collect { variant -> "build/generated/source/buildConfig/${variant.flavorName}/${variant.buildType.name}" })
android.libraryVariants.configureEach { variant ->
javadoc.doFirst {
javadoc.classpath += files(variant.javaCompileProvider.get().classpath.files)
javadoc.classpath += files("build/generated/source/r/${variant.flavorName}/${variant.buildType.name}")
javadoc.classpath += files("build/generated/source/buildConfig/${variant.flavorName}/${variant.buildType.name}")
}
}
15 changes: 10 additions & 5 deletions iterableapi/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ android {
compileSdk 34

namespace 'com.iterable.iterableapi'
testNamespace 'iterable.com.iterableapi'

buildFeatures {
buildConfig = true
Expand All @@ -17,6 +16,10 @@ android {
targetCompatibility JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = "17"
}

defaultConfig {
minSdkVersion 21
targetSdkVersion 34
Expand Down Expand Up @@ -114,8 +117,10 @@ task checkstyle(type: Checkstyle) {
}

// A hack to import the classpath and BuildConfig into the javadoc task
afterEvaluate {
javadoc.classpath += files(android.libraryVariants.collect { variant -> variant.javaCompile.classpath.files })
javadoc.classpath += files(android.libraryVariants.collect { variant -> "build/generated/source/r/${variant.flavorName}/${variant.buildType.name}" })
javadoc.classpath += files(android.libraryVariants.collect { variant -> "build/generated/source/buildConfig/${variant.flavorName}/${variant.buildType.name}" })
android.libraryVariants.configureEach { variant ->
javadoc.doFirst {
javadoc.classpath += files(variant.javaCompileProvider.get().classpath.files)
javadoc.classpath += files("build/generated/source/r/${variant.flavorName}/${variant.buildType.name}")
javadoc.classpath += files("build/generated/source/buildConfig/${variant.flavorName}/${variant.buildType.name}")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import java.util.List;

class IterableActionRunner {
public class IterableActionRunner {

@VisibleForTesting
static IterableActionRunnerImpl instance = new IterableActionRunnerImpl();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public class IterableEmbeddedManager : IterableActivityMonitor.AppStateCallback
}
}

fun handleEmbeddedClick(message: IterableEmbeddedMessage, buttonIdentifier: String?, clickedUrl: String?) {
public fun handleEmbeddedClick(message: IterableEmbeddedMessage, buttonIdentifier: String?, clickedUrl: String?) {
if ((clickedUrl != null) && clickedUrl.toString().isNotEmpty()) {
if (clickedUrl.startsWith(IterableConstants.URL_SCHEME_ACTION)) {
// This is an action:// URL, pass that to the custom action handler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ data class IterableEmbeddedPlacement(
}
}

data class IterableEmbeddedMessage (
public data class IterableEmbeddedMessage (
val metadata: EmbeddedMessageMetadata,
val elements: EmbeddedMessageElements? = null,
val payload: JSONObject? = null
Expand Down Expand Up @@ -82,7 +82,7 @@ data class IterableEmbeddedMessage (
}
}

class EmbeddedMessageMetadata(
public class EmbeddedMessageMetadata(
var messageId: String,
val placementId: Long,
val campaignId: Int? = null,
Expand Down Expand Up @@ -117,7 +117,7 @@ class EmbeddedMessageMetadata(
}
}

class EmbeddedMessageElements (
public class EmbeddedMessageElements (
val title: String? = null,
val body: String? = null,
val mediaURL: String? = null,
Expand Down Expand Up @@ -213,7 +213,7 @@ class EmbeddedMessageElements (
}
}

class EmbeddedMessageElementsButton (
public class EmbeddedMessageElementsButton (
val id: String,
val title: String? = null,
val action: EmbeddedMessageElementsButtonAction? = null
Expand Down Expand Up @@ -258,7 +258,7 @@ class EmbeddedMessageElementsButton (
}
}

class EmbeddedMessageElementsDefaultAction (
public class EmbeddedMessageElementsDefaultAction (
val type: String,
val data: String
) {
Expand Down Expand Up @@ -287,7 +287,7 @@ class EmbeddedMessageElementsDefaultAction (
}
}

class EmbeddedMessageElementsButtonAction (
public class EmbeddedMessageElementsButtonAction (
val type: String,
val data: String
) {
Expand Down Expand Up @@ -315,7 +315,7 @@ class EmbeddedMessageElementsButtonAction (
}
}
}
class EmbeddedMessageElementsText (
public class EmbeddedMessageElementsText (
val id: String,
val text: String? = null,
val label: String? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public static boolean handleMessageReceived(@NonNull Context context, @NonNull R
String messageId = extras.getString("messageId");
if (messageId != null) {
IterableApi.getInstance().getInAppManager().removeMessage(messageId);
IterableApi.getInstance().getInAppManager().syncInApp();
}
break;
case "UpdateEmbedded":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ public void handleInAppClick(@NonNull IterableInAppMessage message, @Nullable Ur
synchronized void removeMessage(String messageId) {
IterableInAppMessage message = storage.getMessage(messageId);
if (message != null) {
// Mark message as consumed before removing it to prevent it from being displayed
message.setConsumed(true);
storage.removeMessage(message);
}
notifyOnChange();
Expand Down Expand Up @@ -365,7 +367,10 @@ private void syncWithRemoteQueue(List<IterableInAppMessage> remoteQueue) {

for (IterableInAppMessage localMessage : storage.getMessages()) {
if (!remoteQueueMap.containsKey(localMessage.getMessageId())) {
// Mark message as consumed before removing it to prevent it from being displayed
localMessage.setConsumed(true);
storage.removeMessage(localMessage);
api.inAppConsume(localMessage, null, null, null, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets get a confirmation from product to see if recalled message should be consumed. As it could affect the analytics.
Also referencing localMessage after its removal could cause problems.


changed = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;

public class IterableInAppManagerSyncTest extends BaseTest {

Expand Down Expand Up @@ -81,4 +85,37 @@ public void testSyncOnLogin() throws Exception {
verify(inAppManagerMock).syncInApp();
}

}
@Test
public void testRecalledMessagesAreConsumed() throws Exception {
// Create a test message in local storage
IterableInAppMessage testMessage = InAppTestUtils.getTestInboxInAppWithId("test-message-1");
doReturn(testMessage).when(storageMock).getMessage("test-message-1");

// Create a storage with only this message
doReturn(Arrays.asList(testMessage)).when(storageMock).getMessages();

// Setup the API to return empty message list (simulating recall)
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
IterableHelper.IterableActionHandler handler = invocation.getArgument(1);
// Return an empty message list
handler.execute("{\"" + IterableConstants.ITERABLE_IN_APP_MESSAGE + "\": []}");
return null;
}
}).when(iterableApiMock).getInAppMessages(any(Integer.class), any(IterableHelper.IterableActionHandler.class));

// Verify message is not consumed initially
assertFalse(testMessage.isConsumed());

// Sync with remote queue
inAppManager.syncInApp();

// Verify that the message was marked as consumed
assertTrue(testMessage.isConsumed());

// Verify that inAppConsume was called
verify(iterableApiMock).inAppConsume(testMessage, null, null, null, null);
}

}
Loading