Configuration and Functions
To find the detailed configuration and functions please refer to Bambuser Player API Reference
BambuserSDK Initialization
Initialize the SDK in your Application class. You can create separate instances for different regions:
class HostApplication : Application() {
lateinit var globalBambuserSDK: BambuserSDK
lateinit var euBambuserSDK: BambuserSDK
override fun onCreate() {
super.onCreate()
globalBambuserSDK = BambuserSDK(
applicationContext = this,
organizationServer = OrganizationServer.US,
)
euBambuserSDK = BambuserSDK(
applicationContext = this,
organizationServer = OrganizationServer.EU,
)
}
}
Choose OrganizationServer.US or OrganizationServer.EU to match your organization's region.
Video Player Creation
Use the SDK instance to create a live player view:
application.globalBambuserSDK.GetLiveView(
modifier = Modifier.fillMaxSize(),
videoConfiguration = BambuserVideoConfiguration(
events = listOf("*"),
configuration = mapOf(
"buttons" to mapOf("dismiss" to "none"),
"currency" to "USD",
"locale" to "en-US",
"autoplay" to true,
),
videoType = BambuserVideoAsset.Live(showId)
),
videoPlayerDelegate = videoPlayerDelegate
)
GetLiveView accepts the following parameters:
| Parameter | Required | Description |
|---|---|---|
modifier | No | Compose modifier (default Modifier.fillMaxSize()) |
playerId | No | Unique player identifier (auto-generated if omitted) |
videoConfiguration | Yes | Configuration including video type, events, and config |
videoPlayerDelegate | Yes | Delegate to receive events and errors |
piPState | No | PiP state object for picture-in-picture support |
BambuserVideoConfiguration
BambuserVideoConfiguration takes four parameters:
| Parameter | Required | Description |
|---|---|---|
videoType | Yes | BambuserVideoAsset.Live(id) for live shows |
events | Yes | List of event types to receive — use listOf("*") for all |
configuration | Yes | Map of player configuration key/value pairs |
videoScaleMode | No | How the video is scaled inside the player view. Defaults to BambuserVideoScaleMode.FIT |
Button Configurations
Each button type has different modes of operation:
none→ will hide the button.event→ emits an event to be captured by your event handler.auto→ uses the SDK's default behavior.
Dismiss Button
| Property Name | Value | Description |
|---|---|---|
dismiss | none | Hides the button, no events emits |
dismiss | event | Emits an event that can be handled by your custom event handler. |
dismiss | minimize | Not applicable in the Mobile SDK. |
Product Button Configs
| Property Name | Value | Description |
|---|---|---|
product | none | Emits an event – implement your own product view logic. |
product | event | Emits an event that can be handled by your custom handler. |
product | auto | Default behavior – opens the product detail modal. |
Checkout Button Configs
| Property Name | Value | Description |
|---|---|---|
checkout | none | Emits an event – implement your own checkout flow. |
checkout | auto | Default behavior – opens the product detail modal. |
ActionCard Button Configs
| Property Name | Value | Description |
|---|---|---|
actionCard | none | Emits an event – handle navigation in your app. |
actionCard | auto | Default behavior – opens configured link in a webview. ⚠️ Recommended: Use none and handle redirection from your app. |
UI Configurations
⚠️ All UI flags must be nested under a
"ui"key — not at the top level ofconfiguration.
configuration = mapOf(
"ui" to mapOf(
"hideEmojiOverlay" to true,
"hideActionBar" to false,
"hideShareButton" to false,
"hideShareFromTimestampButton" to false,
"hideVolumeButton" to false,
"hideClosedCaptionsButton" to false,
"hidePlaybackRateButton" to false,
"hidePromotedShows" to false,
)
)
| Property Name | Type | Description |
|---|---|---|
hideActionBar | boolean | Hides the full action bar. No button will be displayed. |
hideCartView | boolean | Hides the cart view in the modal, showing only product listing. |
hideChatOverlay | boolean | Hides the chat overlay. |
hideEmojiOverlay | boolean | Hides the emoji overlay on the player. |
hideProductList | boolean | Hides the product list. |
hideShareButton | boolean | Hides the share button. |
hideShareFromTimestampButton | boolean | Hides the share button with timestamp. |
hideShareView | boolean | Hides the share view. |
hideVolumeButton | boolean | Hides the volume control button. |
hideClosedCaptionsButton | boolean | Hides the closed captions / subtitles button. |
hidePlaybackRateButton | boolean | Hides the playback speed button. |
hidePromotedShows | boolean | Hides the promoted shows carousel inside the player. |
Tracking Configurations
| Property Name | Type | Description |
|---|---|---|
enableTrackingPoint | boolean | Sends all tracking information. You will receive notifications in the onNewEventReceived delegate method. |
Player Behavior Configurations
| Property Name | Type | Default | Description |
|---|---|---|---|
autoplay | boolean | true | Automatically starts playback when the player is ready. When false, use PlayerActions.play() from the onVideoStatusChanged callback to start playback manually. |
configuration = mapOf(
"autoplay" to false // Use playerActions.play() in onVideoStatusChanged to start manually
)
Picture-in-Picture
To enable PiP for your activity:
-
Add to your
AndroidManifest.xml—<application>block:android:resizeableActivity="true" -
Add to your
AndroidManifest.xml—<activity>block:android:supportsPictureInPicture="true"android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" -
Use the
PiPDelegateActivityhelper to manage PiP state:
class LiveActivity : ComponentActivity(), PiPDelegate by PiPDelegateActivity() {
override fun enterPiP() {
val aspectRatio = Rational(
playbackDimensions.value.width,
playbackDimensions.value.height
)
enterPictureInPictureMode(
PictureInPictureParams.Builder().setAspectRatio(aspectRatio).build()
)
}
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration
) {
pipState.value = pipState.value.copy(isPipMode = isInPictureInPictureMode)
}
override fun onStop() {
super.onStop()
pipState.value = pipState.value.copy(shouldClosePip = true)
}
}
Pass piPState = pipState.value to GetLiveView to enable PiP.
⚠️ Do not use
viewAction.invoke(),notifyView(), orswitchScreenMode()while in PiP mode.
Video Scale Mode
Requires SDK version 3.6.0 or later.
videoScaleMode controls how the video is scaled inside the player view. It is a parameter on BambuserVideoConfiguration, not a key inside the configuration map.
The video's aspect ratio is always preserved. The mode only decides what happens when the player view and the video have different aspect ratios.
The parameter is optional. Leave it out and the player uses BambuserVideoScaleMode.FIT, so existing integrations keep their current behavior.
| Value | Default | Description |
|---|---|---|
BambuserVideoScaleMode.FIT | ✅ | The whole video fits inside the player view, leaving empty space on the axis where the ratios differ. |
BambuserVideoScaleMode.FILL | The video covers the player view and the overflowing axis is cropped. |
import com.bambuser.social_commerce_sdk.data.BambuserVideoScaleMode
BambuserVideoConfiguration(
events = listOf("*"),
configuration = mapOf("autoplay" to true),
videoType = BambuserVideoAsset.Live(showId),
videoScaleMode = BambuserVideoScaleMode.FILL,
)
No phone screen matches the 9:16 aspect ratio most live shows are recorded in, so a full-screen player using FIT always leaves empty space above and below the video. Use FILL when the video should cover the player view instead.
Full Screen
FILL covers whatever you pass to GetLiveView, so the player view itself has to be the full screen for the video to reach the edges. Remove any system bar padding you apply to it:
Scaffold(modifier = Modifier.fillMaxSize()) { _ ->
// With FILL, do not pass the Scaffold's innerPadding to the player view.
Box(modifier = Modifier.fillMaxSize()) {
application.globalBambuserSDK.GetLiveView(
modifier = Modifier.fillMaxSize(),
videoConfiguration = videoConfiguration,
videoPlayerDelegate = videoPlayerDelegate,
)
}
}
If you keep the padding, FILL still crops the video to the player view, but the player view stops at the system bars and the video does not reach the screen edges.
Only remove the padding when you use FILL. The web overlay fills the player view in both modes, so an unpadded player view in FIT puts the player's own controls under the system bars while the video stays letterboxed inside the view, which gains you nothing. If you offer both modes at runtime, switch the padding with the mode.
The activity has to draw edge to edge for this to have any effect. enableEdgeToEdge() does that, and it is the default when targeting SDK 35 or later.
Hide the system bars
For the best full-screen experience, hide the status bar and the navigation bar. The player lays its own controls out edge to edge, so with the bars visible the show title renders behind the clock and the seek bar sits under the navigation bar.
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
WindowInsetsControllerCompat(window, window.decorView).apply {
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
hide(WindowInsetsCompat.Type.systemBars())
}
Type.systemBars() covers both bars. Use Type.statusBars() or Type.navigationBars() to hide only one. BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE lets the user swipe from either edge to bring the bars back temporarily, after which they hide again.
On devices using gesture navigation this also hides the home indicator, so the video reaches all four edges with no system chrome over it.
If you keep the bars visible, give any controls you draw over the player their own insets, for example Modifier.statusBarsPadding(). That does not help the player's own controls, which the SDK cannot inset: WebView reports env(safe-area-inset-*) as 0, so the web player has no way to know where the bars are.
Full Configuration Example
application.globalBambuserSDK.GetLiveView(
modifier = Modifier.fillMaxSize(),
videoConfiguration = BambuserVideoConfiguration(
events = listOf("*"),
configuration = mapOf(
"buttons" to mapOf(
"dismiss" to "none", // Hides dismiss button, emits event
"product" to "none", // Emits event on product tap
),
"ui" to mapOf(
"hideEmojiOverlay" to false,
"hidePlaybackRateButton" to false,
"hidePromotedShows" to false,
),
"autoplay" to true,
"currency" to "USD", // Required for product hydration
"locale" to "en-US", // Required for product hydration
),
videoType = BambuserVideoAsset.Live(showId),
videoScaleMode = BambuserVideoScaleMode.FIT, // FIT | FILL — how the video is scaled
),
videoPlayerDelegate = videoPlayerDelegate,
piPState = pipState.value,
)