Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
boolean handled = false;
if (pendingAction != null) {
handled = executeAction(context, pendingAction);
pendingAction = null;
// Only clear pending action if it was handled.
// This allows the action to be processed later when SDK is fully initialized
// (e.g., when customActionHandler becomes available after initialize() is called).
if (handled) {
pendingAction = null;
}
}
return handled;
}
Expand All @@ -38,6 +43,13 @@
IterableLogger.e(TAG, "handlePushAction: extras == null, can't handle push action");
return;
}

// Store the application context if not already set, so custom actions can be
// processed even when the SDK hasn't been fully initialized (e.g., openApp=false)
if (IterableApi.sharedInstance._applicationContext == null && context != null) {
IterableApi.sharedInstance._applicationContext = context.getApplicationContext();
}

IterableNotificationData notificationData = new IterableNotificationData(intent.getExtras());
String actionIdentifier = intent.getStringExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER);
IterableAction action = null;
Expand Down Expand Up @@ -87,7 +99,7 @@
Intent launcherIntent = IterableNotificationHelper.getMainActivityIntent(context);
launcherIntent.putExtras(intent.getExtras());
launcherIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (launcherIntent.resolveActivity(context.getPackageManager()) != null) {

Check warning

Code scanning / CodeQL

Dereferenced variable may be null Warning

Variable
context
may be null at this access as suggested by
this
null guard.
context.startActivity(launcherIntent);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,59 @@ public void testLegacyDeepLinkPayload() throws Exception {
assertEquals("https://example.com", capturedAction.getValue().getData());
}

@Test
public void testBackgroundCustomActionWithNonInitializedSDK() throws Exception {
// Reset to simulate SDK not being initialized
IterableTestUtils.resetIterableApi();

// Verify context is initially null
assertNull(IterableApi.sharedInstance._applicationContext);

IterablePushActionReceiver iterablePushActionReceiver = new IterablePushActionReceiver();
Intent intent = new Intent(IterableConstants.ACTION_PUSH_ACTION);
intent.putExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, "remindMeButton");
intent.putExtra(IterableConstants.ITERABLE_DATA_KEY, IterableTestUtils.getResourceString("push_payload_background_custom_action.json"));

// Receive push action when SDK is not initialized
iterablePushActionReceiver.onReceive(ApplicationProvider.getApplicationContext(), intent);

// Verify that context was stored even without SDK initialization
assertNotNull(IterableApi.sharedInstance._applicationContext);

// Verify that the main app activity was NOT launched (openApp=false)
Application application = ApplicationProvider.getApplicationContext();
Intent activityIntent = shadowOf(application).peekNextStartedActivity();
assertNull(activityIntent);
}

@Test
public void testBackgroundCustomActionProcessedAfterSDKInit() throws Exception {
// Reset to simulate SDK not being initialized
IterableTestUtils.resetIterableApi();

IterablePushActionReceiver iterablePushActionReceiver = new IterablePushActionReceiver();
Intent intent = new Intent(IterableConstants.ACTION_PUSH_ACTION);
intent.putExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, "remindMeButton");
intent.putExtra(IterableConstants.ITERABLE_DATA_KEY, IterableTestUtils.getResourceString("push_payload_background_custom_action.json"));

// Receive push action when SDK is not initialized (action won't be handled)
iterablePushActionReceiver.onReceive(ApplicationProvider.getApplicationContext(), intent);

// Now initialize SDK with a custom action handler
stubAnyRequestReturningStatusCode(server, 200, "{}");
final boolean[] handlerCalled = {false};
IterableTestUtils.createIterableApiNew(builder ->
builder.setCustomActionHandler((action, actionContext) -> {
handlerCalled[0] = true;
assertEquals("snoozeReminder", action.getType());
return true;
})
);

// Verify that the custom action handler was called during initialization
// (processPendingAction is called in initialize())
assertEquals(true, handlerCalled[0]);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"campaignId": 5678,
"templateId": 8765,
"messageId": "background123456",
"isGhostPush": false,
"actionButtons": [
{
"identifier": "remindMeButton",
"title": "Remind me in 15 minutes",
"openApp": false,
"action": {
"type": "snoozeReminder",
"data": "{\"delay\":15}"
}
}
],
"defaultAction": {
"type": null
}
}
Loading