33import static io .branch .referral .BranchError .ERR_IMPROPER_REINITIALIZATION ;
44import static io .branch .referral .BranchPreinstall .getPreinstallSystemData ;
55import static io .branch .referral .BranchUtil .isTestModeEnabled ;
6+ import static io .branch .referral .Defines .Jsonkey .EXTERNAL_BROWSER ;
7+ import static io .branch .referral .Defines .Jsonkey .IN_APP_WEBVIEW ;
8+ import static io .branch .referral .PrefHelper .KEY_ENHANCED_WEB_LINK_UX_USED ;
9+ import static io .branch .referral .PrefHelper .KEY_URL_LOAD_MS ;
610import static io .branch .referral .PrefHelper .isValidBranchKey ;
711import static io .branch .referral .util .DependencyUtilsKt .billingGooglePlayClass ;
812import static io .branch .referral .util .DependencyUtilsKt .classExists ;
2529import androidx .annotation .NonNull ;
2630import androidx .annotation .Nullable ;
2731import androidx .annotation .RequiresApi ;
32+ import androidx .browser .customtabs .CustomTabsIntent ;
2833import androidx .core .app .ActivityCompat ;
2934
3035import com .android .billingclient .api .Purchase ;
5459import io .branch .referral .network .BranchRemoteInterfaceUrlConnection ;
5560import io .branch .referral .util .BRANCH_STANDARD_EVENT ;
5661import io .branch .referral .util .BranchEvent ;
62+ import io .branch .referral .util .DependencyUtilsKt ;
5763import io .branch .referral .util .LinkProperties ;
5864
5965/**
@@ -87,87 +93,87 @@ public class Branch {
8793 * The redirect URL provided when the link is handled by a desktop client.
8894 */
8995 public static final String REDIRECT_DESKTOP_URL = "$desktop_url" ;
90-
96+
9197 /**
9298 * The redirect URL provided when the link is handled by an Android device.
9399 */
94100 public static final String REDIRECT_ANDROID_URL = "$android_url" ;
95-
101+
96102 /**
97103 * The redirect URL provided when the link is handled by an iOS device.
98104 */
99105 public static final String REDIRECT_IOS_URL = "$ios_url" ;
100-
106+
101107 /**
102108 * The redirect URL provided when the link is handled by a large form-factor iOS device such as
103109 * an iPad.
104110 */
105111 public static final String REDIRECT_IPAD_URL = "$ipad_url" ;
106-
112+
107113 /**
108114 * The redirect URL provided when the link is handled by an Amazon Fire device.
109115 */
110116 public static final String REDIRECT_FIRE_URL = "$fire_url" ;
111-
117+
112118 /**
113119 * The redirect URL provided when the link is handled by a Blackberry device.
114120 */
115121 public static final String REDIRECT_BLACKBERRY_URL = "$blackberry_url" ;
116-
122+
117123 /**
118124 * The redirect URL provided when the link is handled by a Windows Phone device.
119125 */
120126 public static final String REDIRECT_WINDOWS_PHONE_URL = "$windows_phone_url" ;
121-
127+
122128 /**
123129 * Open Graph: The title of your object as it should appear within the graph, e.g., "The Rock".
124130 *
125131 * @see <a href="http://ogp.me/#metadata">Open Graph - Basic Metadata</a>
126132 */
127133 public static final String OG_TITLE = "$og_title" ;
128-
134+
129135 /**
130136 * The description of the object to appear in social media feeds that use
131137 * Facebook's Open Graph specification.
132138 *
133139 * @see <a href="http://ogp.me/#metadata">Open Graph - Basic Metadata</a>
134140 */
135141 public static final String OG_DESC = "$og_description" ;
136-
142+
137143 /**
138144 * An image URL which should represent your object to appear in social media feeds that use
139145 * Facebook's Open Graph specification.
140146 *
141147 * @see <a href="http://ogp.me/#metadata">Open Graph - Basic Metadata</a>
142148 */
143149 public static final String OG_IMAGE_URL = "$og_image_url" ;
144-
150+
145151 /**
146152 * A URL to a video file that complements this object.
147153 *
148154 * @see <a href="http://ogp.me/#metadata">Open Graph - Basic Metadata</a>
149155 */
150156 public static final String OG_VIDEO = "$og_video" ;
151-
157+
152158 /**
153159 * The canonical URL of your object that will be used as its permanent ID in the graph.
154160 *
155161 * @see <a href="http://ogp.me/#metadata">Open Graph - Basic Metadata</a>
156162 */
157163 public static final String OG_URL = "$og_url" ;
158-
164+
159165 /**
160166 * Unique identifier for the app in use.
161167 */
162168 public static final String OG_APP_ID = "$og_app_id" ;
163-
169+
164170 /**
165171 * {@link String} value denoting the deep link path to override Branch's default one. By
166172 * default, Branch will use yourapp://open?link_click_id=12345. If you specify this key/value,
167173 * Branch will use yourapp://'$deeplink_path'?link_click_id=12345
168174 */
169175 public static final String DEEPLINK_PATH = "$deeplink_path" ;
170-
176+
171177 /**
172178 * {@link String} value indicating whether the link should always initiate a deep link action.
173179 * By default, unless overridden on the dashboard, Branch will only open the app if they are
@@ -181,7 +187,7 @@ public class Branch {
181187 * unlimited number of times.
182188 */
183189 public static final int LINK_TYPE_UNLIMITED_USE = 0 ;
184-
190+
185191 /**
186192 * An {@link Integer} value indicating the link type. In this case, the link can be used only
187193 * once. After initial use, subsequent attempts will not validate.
@@ -200,17 +206,17 @@ public class Branch {
200206
201207 /* Json object containing key-value pairs for debugging deep linking */
202208 private JSONObject deeplinkDebugParams_ ;
203-
209+
204210 private static boolean disableDeviceIDFetch_ ;
205211
206212 static boolean bypassWaitingForIntent_ = false ;
207-
213+
208214 private static boolean bypassCurrentActivityIntentState_ = false ;
209215
210216 static boolean disableAutoSessionInitialization ;
211217
212218 static boolean referringLinkAttributionForPreinstalledAppsEnabled = false ;
213-
219+
214220 /**
215221 * <p>A {@link Branch} object that is instantiated on init and holds the singleton instance of
216222 * the class during application runtime.</p>
@@ -231,7 +237,7 @@ public class Branch {
231237
232238 /* Set to true when {@link Activity} life cycle callbacks are registered. */
233239 private static boolean isActivityLifeCycleCallbackRegistered_ = false ;
234-
240+ private CustomTabsIntent customTabsIntentOverride ;
235241
236242 /* Enumeration for defining session initialisation state. */
237243 enum SESSION_STATE {
@@ -2654,4 +2660,112 @@ public void setConsumerProtectionAttributionLevel(Defines.BranchAttributionLevel
26542660 }
26552661 }
26562662
2663+ /**
2664+ * Internal method to display an in app web browser.
2665+ * Launches default browser that supports CustomTabs.
2666+ */
2667+ public void openBrowserExperience (JSONObject jsonObject ) {
2668+ BranchLogger .v ("openBrowserExperience JSONObject: " + String .valueOf (jsonObject ));
2669+ try {
2670+ if (jsonObject == null ) {
2671+ BranchLogger .e ("openBrowserExperience: jsonObject is null" );
2672+ return ;
2673+ }
2674+
2675+ String experienceType = null ;
2676+ String weblinkUrl = null ;
2677+
2678+ if (jsonObject .has (Defines .Jsonkey .Enhanced_Web_Link_UX .getKey ())){
2679+ experienceType = jsonObject .optString (Defines .Jsonkey .Enhanced_Web_Link_UX .getKey (), null );
2680+ }
2681+
2682+ if (jsonObject .has (Defines .Jsonkey .Web_Link_Redirect_URL .getKey ())){
2683+ weblinkUrl = jsonObject .optString (Defines .Jsonkey .Web_Link_Redirect_URL .getKey (), null );
2684+ }
2685+
2686+ if (weblinkUrl == null || weblinkUrl .isEmpty ()){
2687+ BranchLogger .e ("openBrowserExperience: weblinkUrl is null or empty" );
2688+ return ;
2689+ }
2690+
2691+ boolean customTabsImported = classExists (DependencyUtilsKt .androidBrowserClass );
2692+
2693+ if (IN_APP_WEBVIEW .getKey ().equals (experienceType ) && customTabsImported ) {
2694+ // If developer passed their own, use that
2695+ if (customTabsIntentOverride != null ){
2696+ BranchLogger .v ("Using developer specified CustomTabs" );
2697+ launchCustomTabBrowser (customTabsIntentOverride , weblinkUrl , getCurrentActivity ());
2698+ }
2699+ else {
2700+ BranchLogger .v ("Using default CustomTabs" );
2701+ launchCustomTabBrowser (weblinkUrl , getCurrentActivity ());
2702+ }
2703+ }
2704+ // This would be executed if either experienceType.equals("EXTERNAL_BROWSER")
2705+ // Or if the androidx.browser:browser is not imported
2706+ else {
2707+ BranchLogger .v ("customTabsImported " + customTabsImported );
2708+ BranchLogger .v ("Opening in external browser." );
2709+ launchExternalBrowser (weblinkUrl );
2710+ }
2711+ }
2712+ catch (Exception ex ){
2713+ BranchLogger .e ("openBrowserExperience caught exception: " + ex );
2714+ }
2715+ }
2716+
2717+ private void launchCustomTabBrowser (String url , Activity activity ) {
2718+ androidx .browser .customtabs .CustomTabsIntent customTabsIntent =
2719+ new androidx .browser .customtabs .CustomTabsIntent .Builder ()
2720+ .build ();
2721+ launchCustomTabBrowser (customTabsIntent , url , activity );
2722+ }
2723+
2724+ /**
2725+ * Set a CustomTabsIntent to open web urls through an in-app browser experience.
2726+ * This allows customization of the in-app browser appearance and behavior.
2727+ *
2728+ * <p>
2729+ * Example usage:
2730+ * <pre>
2731+ * CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
2732+ * .setColorScheme(COLOR_SCHEME_DARK)
2733+ * .setShowTitle(true)
2734+ * .build();
2735+ * Branch.getInstance().setCustomTabsIntent(customTabsIntent);
2736+ * </pre>
2737+ * </p>
2738+ *
2739+ * @param customTabsIntent A configured CustomTabsIntent instance that will be used
2740+ * when opening web links in-app. If null, the default CustomTabsIntent
2741+ * will be used.
2742+ */
2743+ public void setCustomTabsIntent (CustomTabsIntent customTabsIntent ){
2744+ this .customTabsIntentOverride = customTabsIntent ;
2745+ }
2746+
2747+ private void launchCustomTabBrowser (CustomTabsIntent customTabsIntent , String url , Activity activity ) {
2748+ try {
2749+ prefHelper_ .setWebLinkUxTypeUsed (IN_APP_WEBVIEW .getKey ());
2750+ prefHelper_ .setWebLinkLoadTime (System .currentTimeMillis ());
2751+ customTabsIntent .launchUrl (activity , Uri .parse (url ));
2752+ }
2753+ catch (Exception ex ){
2754+ BranchLogger .e ("launchCustomTabBrowser caught exception: " + ex );
2755+ }
2756+ }
2757+
2758+ private void launchExternalBrowser (String url ) {
2759+ try {
2760+ prefHelper_ .setWebLinkUxTypeUsed (EXTERNAL_BROWSER .getKey ());
2761+ prefHelper_ .setWebLinkLoadTime (System .currentTimeMillis ());
2762+
2763+ Intent intent = new Intent (Intent .ACTION_VIEW , Uri .parse (url ));
2764+ intent .addFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
2765+ context_ .startActivity (intent );
2766+ }
2767+ catch (Exception ex ){
2768+ BranchLogger .e ("launchExternalBrowser caught exception: " + ex );
2769+ }
2770+ }
26572771}
0 commit comments