diff --git a/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplay.java b/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplay.java index 6ef42043b8e..413b7ce8dc8 100644 --- a/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplay.java +++ b/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplay.java @@ -19,10 +19,7 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.Application; -import android.content.Intent; -import android.content.pm.ResolveInfo; import android.content.res.Configuration; -import android.net.Uri; import android.text.TextUtils; import android.view.MotionEvent; import android.view.View; @@ -30,7 +27,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import androidx.browser.customtabs.CustomTabsIntent; import com.google.firebase.FirebaseApp; import com.google.firebase.inappmessaging.FirebaseInAppMessaging; import com.google.firebase.inappmessaging.FirebaseInAppMessagingDisplayCallbacks; @@ -96,6 +92,8 @@ public class FirebaseInAppMessagingDisplay extends FirebaseInAppMessagingDisplay private FiamListener fiamListener; private InAppMessage inAppMessage; private FirebaseInAppMessagingDisplayCallbacks callbacks; + private FirebaseInAppMessagingDisplayActionHandler actionHandler = + new FirebaseInAppMessagingDisplayDefaultActionHandler(); @VisibleForTesting @Nullable String currentlyBoundActivityName; @@ -167,6 +165,13 @@ public void clearFiamListener() { this.fiamListener = null; } + /** + * Sets the action handler used when one of the message elements is clicked. + */ + public void setActionHandler(@NonNull FirebaseInAppMessagingDisplayActionHandler actionHandler) { + this.actionHandler = actionHandler; + } + /** * Bind FIAM listener on Activity resume. * @@ -324,7 +329,7 @@ public void onClick(View v) { Logging.logi("Calling callback for click action"); callbacks.messageClicked(action); } - launchUriIntent(activity, Uri.parse(action.getActionUrl())); + actionHandler.handleAction(activity, action); notifyFiamClick(); // Ensure that we remove the displayed FIAM, and ensure that on re-load, the message // isn't re-displayed @@ -540,43 +545,4 @@ private void notifyFiamDismiss() { fiamListener.onFiamDismiss(); } } - - private void launchUriIntent(Activity activity, Uri uri) { - if (ishttpOrHttpsUri(uri) && supportsCustomTabs(activity)) { - // If we can launch a chrome view, try that. - CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder().build(); - Intent intent = customTabsIntent.intent; - intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - customTabsIntent.launchUrl(activity, uri); - } else { - // If we can't launch a chrome view try to launch anything that can handle a URL. - Intent browserIntent = new Intent(Intent.ACTION_VIEW, uri); - ResolveInfo info = activity.getPackageManager().resolveActivity(browserIntent, 0); - browserIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); - browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if (info != null) { - activity.startActivity(browserIntent); - } else { - // If the device can't resolve a url then log, but don't crash. - Logging.loge("Device cannot resolve intent for: " + Intent.ACTION_VIEW); - } - } - } - - private boolean supportsCustomTabs(Activity activity) { - Intent customTabIntent = new Intent("android.support.customtabs.action.CustomTabsService"); - customTabIntent.setPackage("com.android.chrome"); - List resolveInfos = - activity.getPackageManager().queryIntentServices(customTabIntent, 0); - return resolveInfos != null && !resolveInfos.isEmpty(); - } - - private boolean ishttpOrHttpsUri(Uri uri) { - if (uri == null) { - return false; - } - String scheme = uri.getScheme(); - return scheme != null && (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")); - } } diff --git a/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplayActionHandler.java b/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplayActionHandler.java new file mode 100644 index 00000000000..8d6b335a045 --- /dev/null +++ b/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplayActionHandler.java @@ -0,0 +1,12 @@ +package com.google.firebase.inappmessaging.display; + +import android.app.Activity; +import androidx.annotation.NonNull; +import com.google.firebase.inappmessaging.model.Action; + +/** + * Handles message element (image, button) clicks. + */ +public interface FirebaseInAppMessagingDisplayActionHandler { + void handleAction(@NonNull Activity activity, @NonNull Action action); +} diff --git a/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplayDefaultActionHandler.java b/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplayDefaultActionHandler.java new file mode 100644 index 00000000000..2a79be231aa --- /dev/null +++ b/firebase-inappmessaging-display/src/main/java/com/google/firebase/inappmessaging/display/FirebaseInAppMessagingDisplayDefaultActionHandler.java @@ -0,0 +1,58 @@ +package com.google.firebase.inappmessaging.display; + +import android.app.Activity; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import androidx.annotation.NonNull; +import androidx.browser.customtabs.CustomTabsIntent; +import com.google.firebase.inappmessaging.display.internal.Logging; +import com.google.firebase.inappmessaging.model.Action; +import java.util.List; + +/** + * The default handler of message actions. It opens a Custom Tab with the link if possible or tries to find an Activity + * that can handle the action URL + */ +public class FirebaseInAppMessagingDisplayDefaultActionHandler implements FirebaseInAppMessagingDisplayActionHandler { + @Override + public void handleAction(@NonNull Activity activity, @NonNull Action action) { + Uri uri = Uri.parse(action.getActionUrl()); + if (ishttpOrHttpsUri(uri) && supportsCustomTabs(activity)) { + // If we can launch a chrome view, try that. + CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder().build(); + Intent intent = customTabsIntent.intent; + intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + customTabsIntent.launchUrl(activity, uri); + } else { + // If we can't launch a chrome view try to launch anything that can handle a URL. + Intent browserIntent = new Intent(Intent.ACTION_VIEW, uri); + ResolveInfo info = activity.getPackageManager().resolveActivity(browserIntent, 0); + browserIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); + browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (info != null) { + activity.startActivity(browserIntent); + } else { + // If the device can't resolve a url then log, but don't crash. + Logging.loge("Device cannot resolve intent for: " + Intent.ACTION_VIEW); + } + } + } + + private boolean supportsCustomTabs(Activity activity) { + Intent customTabIntent = new Intent("android.support.customtabs.action.CustomTabsService"); + customTabIntent.setPackage("com.android.chrome"); + List resolveInfos = + activity.getPackageManager().queryIntentServices(customTabIntent, 0); + return !resolveInfos.isEmpty(); + } + + private boolean ishttpOrHttpsUri(Uri uri) { + if (uri == null) { + return false; + } + String scheme = uri.getScheme(); + return scheme != null && (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")); + } +}