diff --git a/iterableapi/src/main/AndroidManifest.xml b/iterableapi/src/main/AndroidManifest.xml index 5c55dbe8f..2684877a7 100644 --- a/iterableapi/src/main/AndroidManifest.xml +++ b/iterableapi/src/main/AndroidManifest.xml @@ -29,6 +29,7 @@ android:name=".IterableTrampolineActivity" android:exported="false" android:launchMode="singleTask" + android:taskAffinity="" android:excludeFromRecents="true" android:theme="@style/TrampolineActivity.Transparent"/> diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableAction.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableAction.java index 9bcad4aed..2044b516b 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableAction.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableAction.java @@ -14,6 +14,7 @@ public class IterableAction { /** Open the URL or deep link */ public static final String ACTION_TYPE_OPEN_URL = "openUrl"; + public static final String ACTION_TYPE_OPEN_APP = "openApp"; private final @NonNull JSONObject config; @@ -68,6 +69,8 @@ static IterableAction actionCustomAction(@NonNull String customActionName) { * If {@link #ACTION_TYPE_OPEN_URL}, the SDK will call {@link IterableUrlHandler} and then try to * open the URL if the delegate returned `false` or was not set. * + * If {@link #ACTION_TYPE_OPEN_APP}, the SDK will open the app's main activity. + * * For other types, {@link IterableCustomActionHandler} will be called. * @return Action type */ diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableActionRunner.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableActionRunner.java index 4476709d0..f01437c07 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableActionRunner.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableActionRunner.java @@ -41,6 +41,8 @@ boolean executeAction(@NonNull Context context, @Nullable IterableAction action, if (action.isOfType(IterableAction.ACTION_TYPE_OPEN_URL)) { return openUri(context, Uri.parse(action.getData()), actionContext); + } else if (action.isOfType(IterableAction.ACTION_TYPE_OPEN_APP)) { + return false; } else { return callCustomActionIfSpecified(action, actionContext); } diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableCustomActionHandler.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableCustomActionHandler.java index e17c52bba..20cd5234f 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableCustomActionHandler.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableCustomActionHandler.java @@ -11,7 +11,7 @@ public interface IterableCustomActionHandler { * Callback called for custom actions from push notifications * @param action {@link IterableAction} object containing action payload * @param actionContext The action context - * @return Boolean value. Reserved for future use. + * @return true if your app handled the action, false otherwise */ boolean handleIterableCustomAction(@NonNull IterableAction action, @NonNull IterableActionContext actionContext); diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java index b6b9a99f6..f875addff 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppFragmentHTMLNotification.java @@ -16,6 +16,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.util.AndroidRuntimeException; import android.util.DisplayMetrics; import android.view.Display; import android.view.Gravity; @@ -200,9 +201,12 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c applyWindowGravity(getDialog().getWindow(), "onCreateView"); } - webView = new IterableWebView(getContext()); + webView = createWebViewSafely(getContext()); + if (webView == null) { + dismissAllowingStateLoss(); + return null; + } webView.setId(R.id.webView); - webView.createWithHtml(this, htmlString); if (orientationListener == null) { @@ -324,7 +328,9 @@ public void onSaveInstanceState(@NonNull Bundle outState) { */ @Override public void onStop() { - orientationListener.disable(); + if (orientationListener != null) { + orientationListener.disable(); + } super.onStop(); } @@ -747,6 +753,15 @@ InAppLayout getInAppLayout(Rect padding) { return InAppLayout.CENTER; } } + + private IterableWebView createWebViewSafely(Context context) { + try { + return new IterableWebView(context); + } catch (AndroidRuntimeException e) { + IterableLogger.e(TAG, "Failed to create WebView", e); + return null; + } + } } enum InAppLayout { diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationBuilder.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationBuilder.java index 346fce45d..97ad1d0eb 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationBuilder.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationBuilder.java @@ -135,7 +135,7 @@ private PendingIntent getPendingIntent(Context context, IterableNotificationData if (button.openApp) { IterableLogger.d(TAG, "Go through TrampolineActivity"); buttonIntent.setClass(context, IterableTrampolineActivity.class); - buttonIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + buttonIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); pendingButtonIntent = PendingIntent.getActivity(context, buttonIntent.hashCode(), buttonIntent, pendingIntentFlag); } else { diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java index 2625b32bf..f005010c2 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java @@ -194,7 +194,7 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex trampolineActivityIntent.setClass(context, IterableTrampolineActivity.class); trampolineActivityIntent.putExtras(extras); trampolineActivityIntent.putExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, IterableConstants.ITERABLE_ACTION_DEFAULT); - trampolineActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + trampolineActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Action buttons if (notificationData.getActionButtons() != null) {