diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 602b24953..6600a3eb8 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -42,6 +42,7 @@ import com.clevertap.android.sdk.inapp.store.preference.FileStore; import com.clevertap.android.sdk.inapp.store.preference.InAppAssetsStore; import com.clevertap.android.sdk.inapp.store.preference.StoreRegistry; +import com.clevertap.android.sdk.interfaces.CustomInAppDisplayProvider; import com.clevertap.android.sdk.network.NetworkManager; import com.clevertap.android.sdk.task.CTExecutorFactory; import com.clevertap.android.sdk.task.MainLooperHandler; @@ -794,6 +795,10 @@ private void showInApp( currentlyDisplayingInApp = inAppNotification; + if (tryCustomShowInApp(inAppNotification)) { + return; // handled by a CustomInAppDisplayProvider + } + CTInAppBaseFragment inAppFragment = null; CTInAppType type = inAppNotification.getInAppType(); switch (type) { @@ -872,6 +877,53 @@ private void showInApp( } } + // Tries to show the notification via a CustomInAppDisplayProvider implemented by the current Activity. + // Returns true if shown, false otherwise. + private boolean tryCustomShowInApp(CTInAppNotification notification) { + Activity activity = CoreMetaData.getCurrentActivity(); + if (activity == null || !(activity instanceof CustomInAppDisplayProvider) ) { + return false; // not a CustomInAppDisplayProvider + } + try { + CustomInAppDisplayProvider displayProvider = (CustomInAppDisplayProvider) activity; + if (!displayProvider.canDisplay(notification, config, activity)) { + return false; // not supported/wanted + } + displayProvider.display(notification, config, activity, new CustomInAppDisplayProvider.Callbacks() { + @Override + public Bundle onActionTriggered(@NonNull CTInAppNotification notification, + @NonNull CTInAppAction action, + @NonNull String callToAction, + Bundle additionalData, + Context activityContext) { + return inAppNotificationActionTriggered(notification, action, callToAction, additionalData, + activityContext); + } + + @Override + public void onButtonClicked(@NonNull CTInAppNotification notification, CTInAppNotificationButton button, + Context activityContext) { + inAppNotificationDidClick(notification, button, activityContext); + } + + @Override + public void onDismissed(@NonNull CTInAppNotification notification, Bundle formData) { + inAppNotificationDidDismiss(notification, formData); + } + + @Override + public void onShown(@NonNull CTInAppNotification notification, Bundle formData) { + inAppNotificationDidShow(notification, formData); + } + }); + } catch (Exception e) { + Logger.d(config.getAccountId(), "Error in custom in-app display provider: " + e.getMessage(), e); + return false; // fall back to standard display + } + + return true; // handled + } + @WorkerThread public void onQueueEvent(final String eventName, Map eventProperties, Location userLocation) { final Map appFieldsWithEventProperties = JsonUtil.mapFromJson( diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/interfaces/CustomInAppDisplayProvider.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/interfaces/CustomInAppDisplayProvider.java new file mode 100644 index 000000000..0f995e429 --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/interfaces/CustomInAppDisplayProvider.java @@ -0,0 +1,63 @@ +package com.clevertap.android.sdk.interfaces; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import androidx.annotation.NonNull; +import com.clevertap.android.sdk.CleverTapInstanceConfig; +import com.clevertap.android.sdk.inapp.CTInAppAction; +import com.clevertap.android.sdk.inapp.CTInAppNotification; +import com.clevertap.android.sdk.inapp.CTInAppNotificationButton; + +// +// CustomInAppDisplayProvider +// -------------------------- +// Activities that implement this interface can take responsibility for +// displaying individual CTInAppNotifications. +// +// InAppController looks for this interface on the current activity whenever it +// needs to show an in-app notification. If present, it calls canDisplay(); if +// that returns true it then calls display(). +// +// display() MUST report its outcome via the Callbacks object so the SDK keeps +// queue state and analytics accurate. +// +public interface CustomInAppDisplayProvider { + + // Returns true if this provider can handle the notification in this host. + boolean canDisplay( + @NonNull CTInAppNotification notification, + @NonNull CleverTapInstanceConfig config, + @NonNull Activity host); + + // Renders the notification (only after canDisplay() == true). + // Implementation MUST report its outcome via Callbacks. + void display( + @NonNull CTInAppNotification notification, + @NonNull CleverTapInstanceConfig config, + @NonNull Activity host, + @NonNull Callbacks callbacks); + + // Bridge back into InAppController for metrics & queue management. + interface Callbacks { + Bundle onActionTriggered( + @NonNull CTInAppNotification notification, + @NonNull CTInAppAction action, + @NonNull String callToAction, + Bundle additionalData, + Context activityContext); + + void onButtonClicked( + @NonNull CTInAppNotification notification, + CTInAppNotificationButton button, + Context activityContext); + + void onDismissed( + @NonNull CTInAppNotification notification, + Bundle formData); + + void onShown( + @NonNull CTInAppNotification notification, + Bundle formData); + } +}