# Video Player Configuration(Android)

This guide covers player configuration options for all Firework video widgets. These options are set through `PlayerOption` in `ViewOptions` and control the video player's behavior, appearance, and features.

For a complete reference of all player options with detailed documentation, see [PlayerOption Configuration](/firework-for-developers/android-sdk/integration-guide/configuration/player-options.md).

## Player Display

### Player Mode

Controls how video content is scaled and displayed within the player.

**Values:**

* `PlayerMode.FIT_MODE` - Video fits within bounds maintaining 9:16 aspect ratio, may have letterboxing
* `PlayerMode.FULL_BLEED_MODE` - Video fills the entire screen, may be cropped (default)

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        playerMode(PlayerMode.FIT_MODE)
    }
}

val videoFeedView = findViewById<FwVideoFeedView>(R.id.videoFeedView)
videoFeedView.init(viewOptions)
```

### Scrolling Orientation

Controls the swipe direction for navigating between videos in the player.

**Values:**

* `ScrollingOrientation.HORIZONTAL` - Swipe left/right (default)
* `ScrollingOrientation.VERTICAL` - Swipe up/down

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        scrollingOrientation(ScrollingOrientation.VERTICAL)
    }
}
```

## UI Element Visibility

### Firework Logo

Control whether the Firework logo is displayed in the player. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        showFireworkLogo(false)
    }
}
```

### Custom Channel Logo

Configure custom logo display in the player using `LogoConfig`.

**Options:**

* `LogoConfig.NoLogo` - No logo shown
* `LogoConfig.Logo.AggregatorLogo(channelId, isClickable)` - Custom drawable logo from channel
* `LogoConfig.Logo.CreatorLogo(channelId, isClickable)` - Custom drawable logo from creator

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        logoConfig(
            LogoConfig.Logo.AggregatorLogo(
                channelId = "your_encoded_channel_id",
                isClickable = true
            )
        )
    }
}
```

Set `isClickable = false` if you don't want the share menu to appear when clicking the logo.

### Share Button

Show or hide the share button. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        showShareButton(true)
    }
}
```

### Mute Button

Show or hide the mute/unmute button. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        showMuteButton(true)
    }
}
```

### Play/Pause Button in Videos

Show or hide the play/pause button for regular videos. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        showPlayPauseButtonInVideo(true)
    }
}
```

### Play/Pause Button in Replays

Show or hide the play/pause button for livestream replays. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        showPlayPauseButtonInReplay(true)
    }
}
```

### More Button

Show or hide the more options button. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        showMoreButton(true)
    }
}
```

## Playback Behavior

### Autoplay

Enable autoplay for the first visible video in FwVideoFeedView. Default is `false`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        autoplay(true)
    }
}
```

### Auto-Play Next Video

Automatically play the next video when the current video ends. When `true`, the player advances to the next video. When `false`, the current video loops. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        autoPlayOnComplete(true)
    }
}
```

## Sharing

### Share Base URL

Configure a base URL for generating share links.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        shareBaseUrl("https://your-app.com/videos")
    }
}
```

### Custom Share URL Callback

Customize share URLs before sharing using a suspend callback.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        shareUrlCustomCallBack { url, videoInfo ->
            // Add custom parameters
            "$url?utm_source=app&video_id=${videoInfo.videoId}"
        }
    }
}
```

## CTA Configuration

### SDK Handle CTA Button Click

Control whether the SDK automatically handles CTA button clicks. Default is `true`.

When set to `false`, you must handle CTA clicks in your app using the `OnCtaButtonClickListener`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        sdkHandleCtaButtonClick(false)
    }
}

// Set your CTA click listener
FireworkSdk.shopping.setOnCtaButtonClickListener { url, videoInfo ->
    // Handle CTA click
}
```

### CTA Button Visibility Delay

Control when the CTA button becomes visible during video playback.

**Delay Units:**

* `CtaDelayUnit.SECONDS` - Delay in seconds (0.0f - 10.0f, default: 3 seconds)
* `CtaDelayUnit.PERCENTAGE` - Delay as percentage of video duration (0.0f - 1.0f, default: 0.2f or 20%)

```kotlin
val viewOptions = viewOptions {
    ctaOptions {
        ctaDelay(CtaDelay(2.0f, CtaDelayUnit.SECONDS))
    }
}
```

**Example with percentage:**

```kotlin
val viewOptions = viewOptions {
    ctaOptions {
        ctaDelay(CtaDelay(0.5f, CtaDelayUnit.PERCENTAGE)) // Show at 50% of video
    }
}
```

### CTA Button Highlight Delay

Control when the CTA button becomes highlighted after it appears.

```kotlin
val viewOptions = viewOptions {
    ctaOptions {
        ctaHighlightDelay(CtaDelay(2.0f, CtaDelayUnit.SECONDS))
    }
}
```

### Custom CTA Button Styling

Override `FwCtaButtonViewStyle` in your app's theme to customize CTA button appearance:

```xml
<resources>
    <style name="FwCtaButtonViewStyle">
        <item name="android:backgroundTint">@color/customBackgroundColor</item>
        <item name="android:textColor">@color/customTextColor</item>
        <item name="android:fontFamily">@font/customFont</item>
    </style>
</resources>
```

For rounded corners and shape customization:

```xml
<resources>
    <style name="FwCtaButtonViewStyle">
        <item name="shapeAppearanceOverlay">@style/MyCustomCtaButtonShapeStyle</item>
    </style>
    
    <style name="MyCustomCtaButtonShapeStyle">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSizeTopLeft">6dp</item>
        <item name="cornerSizeBottomLeft">6dp</item>
        <item name="cornerSizeBottomRight">6dp</item>
        <item name="cornerSizeTopRight">6dp</item>
    </style>
</resources>
```

## Picture-in-Picture (PIP)

### Enable PIP Mode

Enable Picture-in-Picture mode. Default is `false`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        enablePipMode(true)
    }
}
```

### Enter PIP Programmatically

```kotlin
FireworkSdk.enterPip { success ->
    // true if entering PIP was successful
}
```

### Close PIP

```kotlin
FireworkSdk.closePip()
```

### PIP Cleanup on Activity Destroy

In Android 11+, removing the app's task from the task manager doesn't kill the player in PIP mode. Close PIP in your Activity's `onDestroy`:

```kotlin
override fun onDestroy() {
    FireworkSdk.closePip()
    super.onDestroy()
}
```

## Subtitles and Captions

### Show Subtitles

Show or hide video subtitles. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        showSubtitle(true)
    }
}
```

### Show Captions

Show or hide video captions. Default is `true`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        showCaption(true)
    }
}
```

### Subtitle Text Color

Customize the text color for subtitles. Default is white (`0xFFFFFFFF`).

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        subtitleTextColor(0xFFFFFFFF.toInt())
    }
}
```

### Subtitle Background Color

Customize the background color for subtitles. Default is semi-transparent black (`0x66121212`).

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        subtitleBackgroundColor(0x66121212.toInt())
    }
}
```

### Reverse Audio Controls Order

Rearrange the order of mute/unmute button and closed captions button. Default is `false`.

When `true`, the closed captions button appears to the right of the mute/unmute button. When `false`, the closed captions button appears to the left of the mute/unmute button.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        reverseAudioControls(false)
    }
}
```

## Livestream Features

### Livestream Countdown

Display a countdown timer before livestream starts (over trailer video). Users can set reminders for the livestream.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        livestreamCountDownOption(
            LivestreamCountDownOption.Builder()
                .isHidden(false)
                .theme(Theme.DARK)
                .build()
        )
    }
}
```

## Immersive Mode

Enable immersive fullscreen mode that hides system UI (navigation bars, status bar). Default is `false`.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        enableImmersiveMode(true)
    }
}
```

## Advanced UI Configuration

### Player UI Options

Configure advanced player UI elements including custom icons and detailed options.

```kotlin
val customIcon = WidgetImage(
    drawableRes = R.drawable.ic_custom,
    tintColor = Color.WHITE
)

val viewOptions = viewOptions {
    playerOptions {
        playerUiOption(
            PlayerUiOption.Builder()
                .videoDetailsOption(
                    VideoDetailsOption.Builder()
                        .showCaption(true)
                        .buttonIcon(customIcon)
                        .build()
                )
                .closeButtonOption(
                    CloseButtonOption.Builder()
                        .icon(customIcon)
                        .shouldShowWhenPiPEnabled(false)
                        .build()
                )
                .pipButtonOption(
                    PipButtonOption.Builder()
                        .icon(customIcon)
                        .build()
                )
                .muteButtonOption(
                    MuteButtonOption.Builder()
                        .muteIcon(customIcon)
                        .unmuteIcon(customIcon)
                        .build()
                )
                .playbackButtonOption(
                    PlaybackButtonOption.Builder()
                        .playIcon(customIcon)
                        .pauseIcon(customIcon)
                        .build()
                )
                .build()
        )
    }
}
```

**Customizable Icons:**

* **Player detail button (More Button)** - Three dots on top left showing details/share
* **Mute button** - Icon for muted state
* **Unmute button** - Icon for unmuted state
* **Close button** - Icon on top right to close player
* **Play button** - Icon for paused state (center of player)
* **Pause button** - Icon for playing state (when WCAG Talkback is on)
* **PIP button** - Icon for Picture-in-Picture mode

### Action Buttons

Add custom action buttons to the player.

```kotlin
val viewOptions = viewOptions {
    playerOptions {
        actionButtonOption(
            ActionButtonOption.Builder()
                .addActionButton(
                    ActionButton(
                        icon = R.drawable.ic_custom_action,
                        action = { videoInfo ->
                            // Handle custom action
                            Log.d("Player", "Custom action for video: ${videoInfo.videoId}")
                        }
                    )
                )
                .build()
        )
    }
}
```

## Complete Configuration Example

```kotlin
class VideoPlayerActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_video_player)
        
        val customIcon = WidgetImage(
            drawableRes = R.drawable.ic_custom_close,
            tintColor = Color.WHITE
        )
        
        val viewOptions = viewOptions {
            baseOptions {
                feedResource(FeedResource.Discovery)
            }
            playerOptions {
                // Display
                playerMode(PlayerMode.FULL_BLEED_MODE)
                scrollingOrientation(ScrollingOrientation.VERTICAL)
                
                // UI Elements
                showFireworkLogo(false)
                showShareButton(true)
                showMuteButton(true)
                showPlayPauseButtonInVideo(true)
                showMoreButton(true)
                
                // Playback
                autoplay(true)
                autoPlayOnComplete(true)
                
                // Sharing
                shareBaseUrl("https://your-app.com/videos")
                shareUrlCustomCallBack { url, videoInfo ->
                    "$url?utm_source=app&video_id=${videoInfo.videoId}"
                }
                
                // CTA
                sdkHandleCtaButtonClick(true)
                
                // PIP
                enablePipMode(true)
                
                // Subtitles
                showSubtitle(true)
                showCaption(true)
                subtitleTextColor(0xFFFFFFFF.toInt())
                subtitleBackgroundColor(0x66121212.toInt())
                reverseAudioControls(false)
                
                // Livestream
                livestreamCountDownOption(
                    LivestreamCountDownOption.Builder()
                        .isHidden(false)
                        .theme(Theme.DARK)
                        .build()
                )
                
                // Immersive Mode
                enableImmersiveMode(true)
                
                // Custom UI
                playerUiOption(
                    PlayerUiOption.Builder()
                        .closeButtonOption(
                            CloseButtonOption.Builder()
                                .icon(customIcon)
                                .build()
                        )
                        .build()
                )
            }
            ctaOptions {
                ctaDelay(CtaDelay(3.0f, CtaDelayUnit.SECONDS))
                ctaHighlightDelay(CtaDelay(2.0f, CtaDelayUnit.SECONDS))
            }
        }
        
        val videoFeedView = findViewById<FwVideoFeedView>(R.id.videoFeedView)
        videoFeedView.init(viewOptions)
    }
    
    override fun onDestroy() {
        FireworkSdk.closePip()
        super.onDestroy()
    }
}
```

## See Also

* [PlayerOption Reference](/firework-for-developers/android-sdk/integration-guide/configuration/player-options.md) - Complete player options documentation
* [ViewOptions Overview](/firework-for-developers/android-sdk/integration-guide/configuration.md) - All configuration options
* [Shopping Integration](/firework-for-developers/android-sdk/integration-guide/shoppable-videos.md) - CTA handling and shopping features
* [Livestream Integration](/firework-for-developers/android-sdk/integration-guide/livestream.md) - Livestream features and callbacks
* [Widgets Overview](/firework-for-developers/android-sdk/integration-guide/widgets.md) - All available widgets


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.firework.com/firework-for-developers/android-sdk/integration-guide/video-player.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
