Skip to main content

Player Integration in Android WebView

Overview

In this document, we briefly go through the steps to get started with integrating the Bambuser Live Video Shopping player into your native Android mobile app.


Requirements

  • Your app supports WebViews
    (or is web-based)
  • A webpage embedding Bambuser Live Video Shopping player, which can be loaded inside the WebView

    • Hosted and managed by you
    • Includes JavaScript code for connecting the player with your app

Below we, step-by-step, show how to set up, embed and integrate the Bambuser Live Video Shopping player in your native Android App.

Getting started

Here you find a simple example project that can help you understand the implementation and get started with the technical integration quickly.

iOS project

Android

  • Kotlin
  • Webview
  • Interface class
  • Helper methods
HTML embed page

Embed HTML page

  • To be embedded inside the webview
  • Player configuration and event listener
  • Sample show embedded

How it works

img

Because the Bambuser Live Video Shopping player is a web app, it works perfectly within a webview. Thanks to the ability of the common platforms to communicate between WebView and the native code, it is possible to utilize the Bambuser Player JavaScript API to configure and customize the behavior of the player inside the WebView.

Embed player on HTML page

Steps:

  • Setup a webpage to embed inside the webview
    • Hosted and managed on your side
  • Embed the player on that webpage (Learn more)

Setup a webview

Steps:

  • Create a new activity
  • Add webview to the layout
  • Set the landing page URL
  • Enable JavaScript
  • Attach the interface methods to the webview (Implemented on Handle WebView Events )

Example Code:

layout > activity_webview.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WebviewActivity">

<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>
WebviewActivity.kt
package com.example.bambuserwebview

import androidx.appcompat.app.AppCompatActivity
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebView

/**
* An example full-screen activity that hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
class WebViewActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

if (BuildConfig.DEBUG) {
//For the cases you wish to debug with Google Chrome
WebView.setWebContentsDebuggingEnabled(true)
}

setContentView(R.layout.activity_webview)

// Set up the user interaction to manually show or hide the system UI.
webViewSetup()
}

@SuppressLint("SetJavaScriptEnabled")
private fun webViewSetup() {
val webView = findViewById<View>(R.id.webview) as WebView

webView.apply {
// Here are a list of URLs to a sample webview embed HTML page on different player states
// Uncomment one at a time to test different scenarios
// 1. Recorded show
loadUrl("https://bambuser.github.io/bambuser-lvs-webview-examples/index.html")

// 2. Live Show (fake live to test chat)
// loadUrl("https://bambuser.github.io/bambuser-lvs-webview-examples/index.html?mockLiveBambuser=true")

// 3. Countdown screen / Scheduled show
// loadUrl("https://bambuser.github.io/bambuser-lvs-webview-examples/index.html?showId=2iduPdz2hn6UKd0eQmJq")

settings.javaScriptEnabled = true
}

// Attaching the WebViewInterface class to the webView JavaScript context
// This will be used later in "Establish a JavaScript interface between native app and webview" step
webView.addJavascriptInterface(WebViewInterface(this@WebViewActivity, this@WebViewActivity), "Android")

}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bambuserwebview">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:label="@string/app_name"
android:theme="@style/Theme.BambuserWebView">
<activity android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".WebViewActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="portrait"
android:label="@string/title_activity_webview">
</activity>
</application>

</manifest>
note

If you are having an issue with the keyboard covering the chat input, you need to disable the fullscreen setting for the webview activity.

Next, we will see how to communicate between the webview and the native functionalities.

Establish a JavaScript interface between native app and webview

There is a need to set up a data flow from the native app to the webview and vice versa.

Steps:

  • Implement a WebView Interface class
  • Add your methods (Keep the @JavascriptInterface anotation for each method)
  • Make sure you added the interface to the webview using the addJavascriptInterface method when initiating the webview
WebViewInterface.kt
package com.example.bambuserwebview

import android.app.Activity
import android.content.Context
import android.webkit.JavascriptInterface

/** Instantiate the interface and set the context */
class WebViewInterface(private val context: Context, private val activity: Activity) {

// Methods defined here can be invoked within the Embed HTML page inside the webview

//Example of a native handler
@JavascriptInterface
fun handleClose() {
activity.finish();
}

// Example of providing data from the app to the webview (e.g. to configure the player translations)
@JavascriptInterface
fun getCurrentLocale(): String {
return "en-US";
}
}

Handle WebView Events

On the Embed HTML page, you can use the player API to handle different player events. Below we gathered the most common scenarios that are handled within the context of app integration.

Handle Add To Calendar

Event name: player.EVENT.SHOW_ADD_TO_CALENDAR

trigger
  • When a shopper clicks on Add to Calendar button inside the player
  1. Hide player's default calendar view
  2. HTML Embed
    // Inside onBambuserLiveShoppingReady

    player.configure({
    ui: {
    hideAddToCalendar: true,
    },
    });

  3. Handle player.EVENT.SHOW_ADD_TO_CALENDAR event to display native Add To Calendar view
    // Inside onBambuserLiveShoppingReady

    player.on(player.EVENT.SHOW_ADD_TO_CALENDAR, (event) => {
    console.log("SHOW_ADD_TO_CALENDAR", event);

    Android.addToCalendar(JSON.stringify(event));
    });

Handle Share

Event name: player.EVENT.SHOW_SHARE

trigger
  • When a shopper clicks on Share button inside the player
  1. Hide player's default share view
  2. HTML Embed
    // Inside onBambuserLiveShoppingReady

    player.configure({
    ui: {
    hideShareView: true,
    },
    });

  3. Handle player.EVENT.SHOW_SHARE event to display the native Share view
    // Inside onBambuserLiveShoppingReady

    player.on(player.EVENT.SHOW_SHARE, (event, callback) => {
    console.log("SHOW_SHARE", event); event,

    Android.share(JSON.stringify(event));
    });

Handle Product View

Event name: player.EVENT.SHOW_PRODUCT_VIEW

trigger
  • When a shopper clicks on a product (whether from the product list or highlighted product).
  1. Override default product click behavior
  2. HTML Embed
    // Inside onBambuserLiveShoppingReady

    player.configure({
    buttons: {
    product: player.BUTTON.NONE,
    },
    });

  3. Handle player.EVENT.SHOW_PRODUCT_VIEW event to display your native PDP
    // Inside onBambuserLiveShoppingReady

    player.on(player.EVENT.SHOW_PRODUCT_VIEW, (event) => {
    console.log("SHOW_PRODUCT_VIEW", event);

    Android.overlayProductView(event.sku);
    });

Handle Closing the Player

Event name: player.EVENT.CLOSE

trigger
  • When a shopper closes the player.
  1. Make sure to configure the dismiss button as below
  2. HTML Embed
    // Inside onBambuserLiveShoppingReady

    player.configure({
    buttons: {
    dismiss: player.BUTTON.CLOSE,
    },
    });

  3. Handle player.EVENT.CLOSE to navigate shopper back to your native app
    // Inside onBambuserLiveShoppingReady

    player.on(player.EVENT.CLOSE, function () {
    Android.handleClose();
    });