PopupBridge allows WebViews to open popup windows in a browser and send data back to the WebView
PopupBridge is an Android library that allows WebViews to open popup windows in a browser and send data back to the parent page in the WebView.
:mega: A new major version of the SDK is available in beta. See the v4 migration guide for details.
PopupBridge is also available for iOS.
See the Frequently Asked Questions to learn more about PopupBridge. See Using PayPal in a WebView to use PopupBridge with PayPal.
Add the dependency in your build.gradle
:
dependencies {
implementation 'com.braintreepayments.api:popup-bridge:4.1.0'
}
To preview the latest work in progress builds, add the following SNAPSHOT dependency in your build.gradle
:
dependencies {
implementation 'com.braintreepayments.api:popup-bridge:4.1.1-SNAPSHOT'
}
You will also need to add the Sonatype snapshots repo to your top-level build.gradle
to import SNAPSHOT builds:
allprojects {
repositories {
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
}
AndroidManifest.xml
, add an intent-filter
to your deep link destination Activity and register a custom URL scheme:<activity android:name="com.company.app.MyPopupBridgeActivity"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="my-custom-url-scheme" />
</intent-filter>
</activity>
Note: android:exported
is required if your app compile SDK version is API 31 (Android 12) or later.
Note: The scheme you define must use all lowercase letters.
Instantiate a PopupBridgeClient
in your app:
package com.company.myapp;
import com.braintreepayments.api.PopupBridgeClient;
class MyWebViewActivity extends Activity {
private WebView webView;
private PopupBridgeClient popupBridgeClient;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
popupBridgeClient = new PopupBridgeClient(this, webView, "my-custom-url-scheme");
// register error listener
popupBridgeClient.setErrorListener(error -> showDialog(error.getMessage()));
webView.loadUrl("https://www.example.com/my_web_app");
}
@Override
protected void onNewIntent(Intent newIntent) {
// required if your deep link destination activity launch mode is `singleTop`, `singleTask`, or `singleInstance`
super.onNewIntent(newIntent);
setIntent(newIntent);
}
}
Use PopupBridge from the web page by writing some JavaScript:
var url = 'http://localhost:4567/'; // the url you wish to open in a popup
if (window.popupBridge) {
// Open the popup in a browser, and give it the deep link back to the app
popupBridge.open(url + '?popupBridgeReturnUrlPrefix=' + popupBridge.getReturnUrlPrefix());
// Optional: define a callback to process results of interaction with the popup
popupBridge.onComplete = function (err, payload) {
if (err) {
console.error('PopupBridge onComplete Error:', err);
} else if (!err && !payload) {
console.log('User closed popup.');
} else {
alert('Your favorite color is ' + payload.queryItems.color);
console.log(payload.path) // defaults to ""
console.log(payload.hash) // defaults to ""
}
};
} else {
var popup = window.open(url);
window.addEventListener('message', function (event) {
var color = JSON.parse(event.data).color;
if (color) {
popup.close();
alert('Your favorite color is ' + color);
}
});
}
Redirect back to the app inside of the popup:
<h1>What is your favorite color?</h1>
<a href="#" data-color="red">Red</a>
<a href="#" data-color="green">Green</a>
<a href="#" data-color="blue">Blue</a>
<script src="jquery.js"></script>
<script>
$('a').on('click', function (event) {
var color = $(this).data('color');
if (location.search.indexOf('popupBridgeReturnUrlPrefix') !== -1) {
var prefix = location.search.split('popupBridgeReturnUrlPrefix=')[1];
// Open the deep link back to the app, and send some data
location.href = prefix + '?color=' + color;
} else {
window.opener.postMessage(JSON.stringify({ color: color }), '*');
}
});
</script>
By default, WebViews cannot open popups -- window.open
will not work.
You can use setSupportMultipleWindows()
and roll your own WebChromeClient and manage the windows yourself, but this does not allow popups to communicate back to the parent WebView.
window.popupBridge
) for the web page to interact with the Android app codewindow.popupBridge
; if so, it uses popupBridge.open
to open the popup URL
popupBridge.open
creates an Intent to open the popup URL, which Android forwards to the user's selected browserpopupBridge.onComplete
as a callbackThe deep link is registered as a custom URL scheme in AndroidManifest.xml
One way to avoid hard-coding the deep link is by adding it as a query parameter to the popup URL:
popupBridge.open(url + '?popupBridgeReturnUrlPrefix=' + popupBridge.getReturnUrlPrefix());
popupBridge.onComplete
popupBridge.onComplete
gets called with the error and payload as null
We are a team of engineers who work on the Developer Experience team at Braintree.
Short answer: to accept PayPal as a payment option when mobile apps are using a WebView to power the checkout process.
PayPal used to support authentication via a modal iframe, but authentication now occurs in a popup window to increase user confidence that their account information is protected from malicious actors (the address bar shows paypal.com
with the HTTPS lock icon). However, this causes issues with Braintree merchants who use a web page to power payments within their apps: they cannot accept PayPal because WebViews cannot open popups and return the PayPal payment authorization data to the parent checkout page.
PopupBridge solves this problem by allowing braintree-web
or PayPal's Checkout.js to open the PayPal popup from a secure mini-browser.
WebView-based checkout flows can accept PayPal with PopupBridge and the Braintree JS SDK or PayPal's Checkout.js. For the authentication flow, PayPal requires a popup window—which can be simulated with PopupBridge.
PayPalDataCollector
in your build.gradle
dependencies, e.g. compile 'com.paypal.android.sdk:data-collector:2.+'
Braintree, [email protected]
PopupBridge is available under the MIT license. See the LICENSE file for more info.