User Interaction Controller
Purpose
The User Interaction Controller manages the interface between the user’s input and the media playback engine within the player UI. It addresses the need for responsive, intuitive control over video playback, seeking, subtitle toggling, and ad interaction. By maintaining observable playback state data, it enables dynamic UI updates that reflect current playback status and media metadata.
This controller solves the problem of bridging complex playback states—including transitions between ads and content—and user actions, ensuring that UI elements such as play/pause buttons, seek bars, subtitles toggles, and ad metadata stay synchronized with the underlying media player.
Functionality
Playback State Management: Tracks and exposes the current playback state (
playerPlaybackState), play readiness (isVideoPlayWhenReady), and whether the current media is an ad (isCurrentAd).Media Metadata Exposure: Provides observable fields for video title, poster image, subtitle availability, ad metadata, and remaining playback time, allowing UI components to bind and update automatically.
User Controls Handling: Implements playback control interfaces to respond to user actions such as:
Play/pause toggling (
togglePlayPause)Fast forward and rewind by fixed intervals (
fastForward,fastRewind)Seek operations by absolute position or relative offsets (
seekTo,seekBy)Subtitle enable/disable toggling (
triggerSubtitlesToggle)Ad click interaction (
clickCurrentAd)
SeekBar Interaction: Listens to SeekBar touch events to update playback position, while managing flags to avoid UI conflicts during user interaction (
isDraggingSeekBar).Playback Progress Updates: Periodically updates the current playback and buffered positions, along with formatted time strings, and notifies registered callbacks for synchronization.
Player Event Listening: Implements
ExoPlayer.EventListenerto react to playback state changes, timeline updates, loading states, and errors, reflecting these changes in observables.Control State Management: Supports different UI control states (normal, custom seek, options), enabling contextual UI behavior such as long-press seeking or subtitle options.
Callback Integration: Communicates with external playback action callbacks (
PlaybackActionCallback) to notify about user-triggered events like play toggling, seeking, subtitles toggle, and ad clicks, enabling integration with FSM or other business logic layers.
Key Workflow Example
When the user drags the seek bar:
onStartTrackingTouchsetsisDraggingSeekBarto true to pause automatic UI updates.As progress changes,
onProgressChangedupdates the displayed time values in real-time.On releasing the seek bar (
onStopTrackingTouch), the controller seeks the player to the new position and clears the dragging flag.Playback progress updates resume only when the user is not interacting.
Relationship to Parent Topic and Other Subtopics
This controller is a core part of the **Media Playback and UI Controls** parent topic, specializing in bridging user input with the adaptive streaming playback managed by ExoPlayer. Unlike the **Player UI Controller** which focuses primarily on managing UI component visibility and resume states, or the **Custom Player View** which integrates video rendering and subtitles, the User Interaction Controller encapsulates the logic for interpreting and acting on user commands, while maintaining observable state for UI binding.
It complements the **Playback Activity Base** by providing a reusable, lifecycle-aware interface for controlling playback that activities can instantiate and bind to UI components such as `UIControllerView`. It also interacts indirectly with the FSM layer via callbacks to synchronize user actions with playback state transitions, ensuring smooth coordination between user input, UI feedback, and underlying media state.
Introducing New Behavior Not Covered Elsewhere
The fine-grained management of seek bar dragging states and multiple control modes (normal, custom seek, options) is unique to this controller.
It provides real-time formatted time strings for display (
videoRemainInString,videoPositionInString), enhancing user experience.It bridges ad-specific UI data (e.g.,
adClickUrl,numberOfAdsLeft) with the playback controls, enabling contextual UI responses during ad playback.The controller handles subtitle visibility toggling by directly modifying the subtitle view, which is not covered by the general UI controller or player view.
Code Snippet Highlight
The controller’s operation on user seeking demonstrates its integration of UI events with playback control:
@Override
public void onStopTrackingTouch(final SeekBar seekBar) {
if (mPlayer != null) {
seekTo(Utils.progressToMilli(mPlayer.getDuration(), seekBar));
}
isDraggingSeekBar.set(false);
}
@Override
public void seekTo(final long millisecond) {
if (mPlaybackActionCallback != null && mPlaybackActionCallback.isActive()) {
long currentProgress = mPlayer != null ? mPlayer.getCurrentPosition() : 0;
mPlaybackActionCallback.onSeek(mMediaModel, currentProgress, millisecond);
}
seekToPosition(millisecond);
}
private void seekToPosition(long positionMs) {
if (mPlayer != null) {
mPlayer.seekTo(mPlayer.getCurrentWindowIndex(), positionMs);
}
}
This snippet shows how user input triggers a seek operation both in the ExoPlayer instance and notifies external callbacks for further processing or analytics.
Diagram
flowchart TD
User[User Input]
UI[UI Components (e.g. SeekBar, Buttons)]
Controller[User Interaction Controller]
Player[ExoPlayer Instance]
Callbacks[PlaybackActionCallback]
SubtitleView[Subtitle View]
User --> UI
UI --> Controller
Controller --> Player
Controller --> Callbacks
Controller --> SubtitleView
Player --> Controller
Callbacks --> Controller
**Diagram Explanation:** User input through UI components (like buttons or seek bars) is routed to the User Interaction Controller, which translates these actions into playback commands on the ExoPlayer instance and updates UI observables. It also notifies registered playback callbacks for state synchronization. The controller directly manipulates subtitle visibility through the subtitle view and listens for player events to update UI accordingly.
This design ensures a seamless, reactive user experience tightly coupled with the underlying playback engine and higher-level state management.