-
Notifications
You must be signed in to change notification settings - Fork 38
[SDK-417] Fail gracefully when managers accessed before init #1073
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
Merged
franco-zalamena-iterable
merged 2 commits into
master
from
feature/SDK-417-graceful-preinit
Jul 14, 2026
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
iterableapi/src/main/java/com/iterable/iterableapi/EmptyEmbeddedManager.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package com.iterable.iterableapi | ||
|
|
||
| /** | ||
| * No-op [IterableEmbeddedManager] returned by [IterableApi.getEmbeddedManager] when the SDK has not | ||
| * been initialized. Every method is a benign no-op so callers never crash for a pre-initialization | ||
| * usage error. Use [IterableApi.getEmbeddedManagerOrNull] to detect this state explicitly. | ||
| */ | ||
| internal class EmptyEmbeddedManager : IterableEmbeddedManager() { | ||
|
|
||
| private val emptySessionManager = EmbeddedSessionManager() | ||
|
|
||
| private fun logNotInitialized(method: String) { | ||
| IterableLogger.e(LOG_TAG, "$method called before IterableApi was initialized; no-op. " + | ||
| "Call IterableApi.initialize() in Application#onCreate.") | ||
| } | ||
|
|
||
| override fun addUpdateListener(updateHandler: IterableEmbeddedUpdateHandler) { | ||
| logNotInitialized("addUpdateListener()") | ||
| } | ||
|
|
||
| override fun removeUpdateListener(updateHandler: IterableEmbeddedUpdateHandler) { | ||
| logNotInitialized("removeUpdateListener()") | ||
| } | ||
|
|
||
| override fun getUpdateHandlers(): List<IterableEmbeddedUpdateHandler> { | ||
| logNotInitialized("getUpdateHandlers()") | ||
| return emptyList() | ||
| } | ||
|
|
||
| override fun getEmbeddedSessionManager(): EmbeddedSessionManager { | ||
| logNotInitialized("getEmbeddedSessionManager()") | ||
| return emptySessionManager | ||
| } | ||
|
|
||
| override fun getMessages(placementId: Long): List<IterableEmbeddedMessage>? { | ||
| logNotInitialized("getMessages()") | ||
| return null | ||
| } | ||
|
|
||
| override fun reset() { | ||
| logNotInitialized("reset()") | ||
| } | ||
|
|
||
| override fun getPlacementIds(): List<Long> { | ||
| logNotInitialized("getPlacementIds()") | ||
| return emptyList() | ||
| } | ||
|
|
||
| override fun syncMessages(placementIds: Array<Long>) { | ||
| logNotInitialized("syncMessages()") | ||
| } | ||
|
|
||
| override fun handleEmbeddedClick(message: IterableEmbeddedMessage, buttonIdentifier: String?, clickedUrl: String?) { | ||
| logNotInitialized("handleEmbeddedClick()") | ||
| } | ||
|
|
||
| override fun onSwitchToForeground() { | ||
| } | ||
|
|
||
| override fun onSwitchToBackground() { | ||
| } | ||
|
|
||
| private companion object { | ||
| private const val LOG_TAG = "EmptyEmbeddedManager" | ||
| } | ||
| } | ||
157 changes: 157 additions & 0 deletions
157
iterableapi/src/main/java/com/iterable/iterableapi/EmptyInAppManager.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| package com.iterable.iterableapi; | ||
|
|
||
| import android.net.Uri; | ||
|
|
||
| import androidx.annotation.NonNull; | ||
| import androidx.annotation.Nullable; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * No-op {@link IterableInAppManager} returned by {@link IterableApi#getInAppManager()} when the SDK | ||
| * has not been initialized. Every method is a benign no-op so callers never crash for a | ||
| * pre-initialization usage error. Use {@link IterableApi#getInAppManagerOrNull()} to detect this | ||
| * state explicitly. | ||
| */ | ||
| class EmptyInAppManager extends IterableInAppManager { | ||
| private static final String TAG = "EmptyInAppManager"; | ||
|
|
||
| EmptyInAppManager() { | ||
| super(); | ||
| } | ||
|
|
||
| private void logNotInitialized(String method) { | ||
| IterableLogger.e(TAG, method + " called before IterableApi was initialized; no-op. " + | ||
| "Call IterableApi.initialize() in Application#onCreate."); | ||
| } | ||
|
|
||
| @NonNull | ||
| @Override | ||
| public synchronized List<IterableInAppMessage> getMessages() { | ||
| logNotInitialized("getMessages()"); | ||
| return Collections.emptyList(); | ||
| } | ||
|
|
||
| @Override | ||
| synchronized IterableInAppMessage getMessageById(String messageId) { | ||
| logNotInitialized("getMessageById()"); | ||
| return null; | ||
| } | ||
|
|
||
| @NonNull | ||
| @Override | ||
| public synchronized List<IterableInAppMessage> getInboxMessages() { | ||
| logNotInitialized("getInboxMessages()"); | ||
| return Collections.emptyList(); | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized int getUnreadInboxMessagesCount() { | ||
| logNotInitialized("getUnreadInboxMessagesCount()"); | ||
| return 0; | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void setRead(@NonNull IterableInAppMessage message, boolean read) { | ||
| logNotInitialized("setRead()"); | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void setRead(@NonNull IterableInAppMessage message, boolean read, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { | ||
| logNotInitialized("setRead()"); | ||
| if (failureHandler != null) { | ||
| failureHandler.onFailure("Iterable SDK is not initialized", null); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void setAutoDisplayPaused(boolean paused) { | ||
| logNotInitialized("setAutoDisplayPaused()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void resumeInAppDisplay() { | ||
| logNotInitialized("resumeInAppDisplay()"); | ||
| } | ||
|
|
||
| @Override | ||
| void syncInApp() { | ||
| logNotInitialized("syncInApp()"); | ||
| } | ||
|
|
||
| @Override | ||
| void reset() { | ||
| logNotInitialized("reset()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void showMessage(@NonNull IterableInAppMessage message) { | ||
| logNotInitialized("showMessage()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void showMessage(@NonNull IterableInAppMessage message, @NonNull IterableInAppLocation location) { | ||
| logNotInitialized("showMessage()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void showMessage(final @NonNull IterableInAppMessage message, boolean consume, final @Nullable IterableHelper.IterableUrlCallback clickCallback) { | ||
| logNotInitialized("showMessage()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void showMessage(final @NonNull IterableInAppMessage message, boolean consume, final @Nullable IterableHelper.IterableUrlCallback clickCallback, @NonNull IterableInAppLocation inAppLocation) { | ||
| logNotInitialized("showMessage()"); | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void removeMessage(@NonNull IterableInAppMessage message) { | ||
| logNotInitialized("removeMessage()"); | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void removeMessage(@NonNull IterableInAppMessage message, @NonNull IterableInAppDeleteActionType source, @NonNull IterableInAppLocation clickLocation) { | ||
| logNotInitialized("removeMessage()"); | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void removeMessage(@NonNull IterableInAppMessage message, @Nullable IterableInAppDeleteActionType source, @Nullable IterableInAppLocation clickLocation, @Nullable IterableHelper.SuccessHandler successHandler, @Nullable IterableHelper.FailureHandler failureHandler) { | ||
| logNotInitialized("removeMessage()"); | ||
| if (failureHandler != null) { | ||
| failureHandler.onFailure("Iterable SDK is not initialized", null); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| synchronized void removeMessage(String messageId) { | ||
| logNotInitialized("removeMessage()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void handleInAppClick(@NonNull IterableInAppMessage message, @Nullable Uri url) { | ||
| logNotInitialized("handleInAppClick()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void onSwitchToForeground() { | ||
| } | ||
|
|
||
| @Override | ||
| public void onSwitchToBackground() { | ||
| } | ||
|
|
||
| @Override | ||
| public void addListener(@NonNull Listener listener) { | ||
| logNotInitialized("addListener()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void removeListener(@NonNull Listener listener) { | ||
| logNotInitialized("removeListener()"); | ||
| } | ||
|
|
||
| @Override | ||
| public void notifyOnChange() { | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.