Skip to content

Commit b42b53b

Browse files
In-app Browser Experience (#1267)
* upgrade gradle * Implement browser experience * Update Branch-SDK-TestBed/src/main/java/io/branch/branchandroidtestbed/MainActivity.java Co-authored-by: matter-code-review[bot] <150888575+matter-code-review[bot]@users.noreply.github.com> * Update Branch-SDK/src/main/java/io/branch/referral/Branch.java Co-authored-by: matter-code-review[bot] <150888575+matter-code-review[bot]@users.noreply.github.com> * ai committed an extra brace * Update Branch-SDK/src/main/java/io/branch/referral/Branch.java Co-authored-by: matter-code-review[bot] <150888575+matter-code-review[bot]@users.noreply.github.com> --------- Co-authored-by: matter-code-review[bot] <150888575+matter-code-review[bot]@users.noreply.github.com>
1 parent ae5d35c commit b42b53b

File tree

14 files changed

+271
-55
lines changed

14 files changed

+271
-55
lines changed

Branch-SDK-TestBed/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ dependencies {
1515
implementation("store.galaxy.samsung.installreferrer:samsung_galaxystore_install_referrer:4.0.0")
1616
implementation("com.miui.referrer:homereferrer:1.0.0.7")
1717

18+
implementation("androidx.browser:browser:1.8.0")
19+
1820
androidTestImplementation("androidx.test.ext:junit:1.1.5")
1921
androidTestImplementation("androidx.test:runner:1.5.2")
2022
androidTestImplementation("androidx.test:rules:1.5.0")

Branch-SDK-TestBed/src/main/java/io/branch/branchandroidtestbed/CustomBranchApp.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package io.branch.branchandroidtestbed;
22

3+
import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK;
4+
35
import android.app.Application;
46
import android.util.Log;
57

8+
import androidx.browser.customtabs.CustomTabsIntent;
9+
610
import java.io.File;
711
import java.io.FileOutputStream;
812
import java.io.OutputStreamWriter;
@@ -22,8 +26,11 @@ public void onCreate() {
2226
// saveLogToFile(message);
2327
// };
2428
Branch.enableLogging(BranchLogger.BranchLogLevel.VERBOSE);
25-
2629
Branch.getAutoInstance(this);
30+
CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
31+
.setColorScheme(COLOR_SCHEME_DARK)
32+
.build();
33+
Branch.getInstance().setCustomTabsIntent(customTabsIntent);
2734
}
2835

2936
private void saveLogToFile(String logMessage) {

Branch-SDK-TestBed/src/main/java/io/branch/branchandroidtestbed/MainActivity.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import com.android.billingclient.api.Purchase;
3131
import com.android.billingclient.api.QueryProductDetailsParams;
3232

33+
import org.json.JSONArray;
34+
import org.json.JSONException;
3335
import org.json.JSONObject;
3436

3537
import java.io.IOException;
@@ -54,7 +56,6 @@
5456
import io.branch.referral.util.LinkProperties;
5557
import io.branch.referral.util.ProductCategory;
5658
import io.branch.referral.util.ShareSheetStyle;
57-
import io.branch.referral.validators.IntegrationValidator;
5859

5960
public class MainActivity extends Activity {
6061
private EditText txtShortUrl;
@@ -659,6 +660,21 @@ public void onClick(View v) {
659660
Branch.notifyNativeToInit();
660661
}
661662
});
663+
664+
findViewById(R.id.openInAppBrowser).setOnClickListener(new OnClickListener() {
665+
@Override
666+
public void onClick(View v) {
667+
try {
668+
JSONObject invokeFeatures = new JSONObject();
669+
invokeFeatures.put("enhanced_web_link_ux", "IN_APP_WEBVIEW");
670+
invokeFeatures.put("web_link_redirect_url", "https://branch.io");
671+
672+
Branch.getInstance().openBrowserExperience(invokeFeatures);
673+
} catch (JSONException e) {
674+
throw new RuntimeException(e);
675+
}
676+
}
677+
});
662678
}
663679

664680
private void createNotificationChannel() {

Branch-SDK-TestBed/src/main/res/layout/main_activity.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@
133133
android:text="Misc."
134134
/>
135135

136+
<Button
137+
android:id="@+id/openInAppBrowser"
138+
style="@style/testbed_button_style"
139+
android:drawableStart="@drawable/baseline_document_scanner_24"
140+
android:text="Browser Test" />
141+
136142
<Button
137143
android:id="@+id/viewLogsButton"
138144
style="@style/testbed_button_style"

Branch-SDK/build.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ dependencies {
4242
// Google Play Billing library
4343
compileOnly("com.android.billingclient:billing:6.0.1")
4444

45+
// In app browser experience
46+
compileOnly("androidx.browser:browser:1.8.0")
47+
48+
4549
androidTestImplementation("androidx.test.ext:junit:1.1.5")
4650
androidTestImplementation("androidx.test:runner:1.5.2")
4751
androidTestImplementation("androidx.test:rules:1.5.0")
@@ -74,7 +78,6 @@ fun isReleaseBuild(): Boolean {
7478

7579
android {
7680
compileSdk = ANDROID_BUILD_SDK_VERSION_COMPILE.toInt()
77-
buildToolsVersion = ANDROID_BUILD_TOOLS_VERSION
7881
defaultConfig {
7982
minSdk = ANDROID_BUILD_SDK_VERSION_MINIMUM.toInt()
8083
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Branch-SDK/src/main/java/io/branch/referral/Branch.java

Lines changed: 133 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import static io.branch.referral.BranchError.ERR_IMPROPER_REINITIALIZATION;
44
import static io.branch.referral.BranchPreinstall.getPreinstallSystemData;
55
import 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;
610
import static io.branch.referral.PrefHelper.isValidBranchKey;
711
import static io.branch.referral.util.DependencyUtilsKt.billingGooglePlayClass;
812
import static io.branch.referral.util.DependencyUtilsKt.classExists;
@@ -25,6 +29,7 @@
2529
import androidx.annotation.NonNull;
2630
import androidx.annotation.Nullable;
2731
import androidx.annotation.RequiresApi;
32+
import androidx.browser.customtabs.CustomTabsIntent;
2833
import androidx.core.app.ActivityCompat;
2934

3035
import com.android.billingclient.api.Purchase;
@@ -54,6 +59,7 @@
5459
import io.branch.referral.network.BranchRemoteInterfaceUrlConnection;
5560
import io.branch.referral.util.BRANCH_STANDARD_EVENT;
5661
import io.branch.referral.util.BranchEvent;
62+
import io.branch.referral.util.DependencyUtilsKt;
5763
import 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

Comments
 (0)