Migration Guide - v2 to v3 (Android SDK)

Benefit from the architectural and performance improvements, along with new features that become available with our new major version 3 of the Android SDK. Learn how to migrate from your current v2 SDK Project to v3 with ease!


The following points will explain all breaking changes, renamed functions and configuration objects, as well as minimum requirements that need to be fulfilled to migrate and benefit from all the major performance and usability improvements that become available with v3.

V3 of the Android Player SDK marks a new direction where the player itself and the sources it plays back become more decoupled. This allows for sources to have their own lifecycle, emit their own events and offer functionality even when the source is currently not being played back. For more details on how the top-level components fit together in V3, refer to the Player, Source and PlaylistApi documentation.

With this new direction comes the ability to load multiple sources into the player via a PlaylistConfig. The player will play back one source after another until it reaches the end of the playlist. Sources in the playlist can already preload content before they are being played back, leading to gapless playback across sources without the overhead of unloading and loading a new source like in V2.

As events are a big part of interacting with the SDK, we have also completely reworked how to interact with them. The Player, Source and PlayerView all implement the new EventEmitter, which offers a more intuitive and flexible way of handling event subscriptions with less boilerplate.

This release also includes improvements like reworked documentation, a better developer experience by including the source-code of the public API and by improving the Maven publishing process, and more.

Minimum Requirements

Supported Android Platforms

  • no requirement changes compared to v2

Google Cast

  • CAF compatible v3 receiver applications required Learn More

Bitmovin Player UI

  • v3.25.x or higher (default and custom versions)


  • The initial 3.0.0 version does not support loading live-streams inside a playlist. As we can't detect the type until we actually start loading the source there won't be an error when loading a live-stream. Doing so will result in unexpected behavior.
  • The event migration towards SourceEvents isn't finished yet. More events will be migrated to be emitted on a per-source basis over the next releases. See also the API doc for an updated list of the already migrated events.
  • Suspended offline downloads of individual tracks that were started utilizing v2 cannot be resumed with v3 when using a version below 3.8.1. Downloads of specific tracks that were started utilizing v2 without using the CompatibilityHelper.PARCELABLE_ACTION_DATA flag can not be resumed in v3 due to internal changes in the serialization workflow. Trying to resume such a download will result in an IllegalStateException. This limitation was removed in version 3.8.1.

Package and Dependency Changes

New Maven Artifact ID

The artifactId of the SDK changed from playercore to player. The full dependency is now declared as follows:

// v2
dependencies {  
  implementation "com.bitmovin.player:playercore:2.65.0"  
// v3
dependencies {  
  implementation "com.bitmovin.player:player:3.0.0"  

Transitive Dependencies

The Maven setup has been reworked to avoid unnecessary dependency leakage. This might force the explicit inclusion of dependencies that are used in the project, but were previously included transitively via the Bitmovin player.

Google Cast Package names

Please see the section Casting for more details.

New package and class names

We have sanitized the package structure used throughout the SDK. This will cause many of the existing imports to break. The easiest way to fix broken imports is to remove the existing imports and re-import the classes while paying attention to possible name changes.


There are three general changes in naming conventions that were cleaned up throughout the SDK:

  1. All configurations were renamed from *Configuration to *Config. E.g. PlaybackConfiguration is now called PlaybackConfig.
  2. All enum entries were renamed from SCREAMING_SNAKE_CASE to PascalCase. E.g. AdSourceType.UNKNOWN was renamed to AdSourceType.Unknown.
  3. All UPPERCASE abbreviations in class names were changed to PascalCase. E.g. UserInterfaceAPI was renamed to UserInterfaceApi.

This table lists all simple name changes from v2 to v3.

EventHandler.addEventListenerEventEmitter.on (Details)
EventHandler.removeEventListenerEventEmitter.off (Details)


This table lists API which was removed in v3 with its replacements (if any).

All deprecated functionality from v2the various replacements
GoogleCastReceiverVersionremoved without replacement (Details)
PlayerView constructor that takes a PlayerConfigPlayerView(Context, Player?)
PlayerFragmentremoved without replacement
Player.setupremoved without replacement (Details)
ConfigurationUpdatedEventremoved as a configuration can't be updated anymore
PlayerConfiguration.sourceConfigurationreplaced with new loading workflows (Details)
Configuration interface from all *Configsremoved without replacement
DRMSystems enumWiedevineConfig and ClearKeyConfig
flags parameter from OfflineContentManager.getOfflineContentManager() and BitmovinDownloadService()not necessary anymore
fromJson function from PlayerConfiguration and SourceConfigurationremoved without replacement
JsonConverterremoved without replacement

Player setup


Many configs were refactored to data classes, making it possible to use named parameters instead of creating an empty config and setting values after creation:


val playerConfig = PlayerConfig()
playerConfig.adaptationConfig = AdaptationConfig()
playerConfig.advertisingConfig = AdvertisingConfig()


val playerConfig = PlayerConfig(adaptationConfig = AdaptationConfig, advertisingConfig = AdvertisingConfig)

Instance Setup

While in v2 BitmovinPlayer was a concrete class that could simply be created using the constructor, in v3 Player is an interface and PlayerBuilder has to be used for instance creation.


val player = BitmovinPlayer(context, playerConfiguration)


val player = new PlayerBuilder(context).setPlayerConfig(playerConfig).build()

In addition, we removed the Player.setup call as well as the ConfigurationUpdatedEvent, which means that the configuration can't be changed anymore once a player was created.

Loading a Source


The SourceItem was renamed to SourceConfig and the old SourceConfiguration was removed completely. SourceConfig from now on refers to the old SourceItem.

As our old SourceConfiguration was based on the SourceConfig from the Web Player SDK there was the possibility to set up multiple configurations for each streaming technology (HLS, Dash ...). We are moving away from this concept starting with v3, therefore we deprecated all the legacy types which were used to set up those different sources, which will be removed in an upcoming minor version:

  • MediaSource
    • AdaptiveSource
      • HLSSource
      • DASHSource
      • SmoothSource
    • ProgressiveSource

The new designated way to create a SourceConfig is to use the url and the type directly in the SourceConfig constructor:


val sourceConfig = SourceItem(HLSSource(url))


val sourceConfig = SourceConfig(url, SourceType.Hls)

Alternatively, a SourceConfig can be created by automatically detecting its type from an url:


val sourceConfig = SourceItem("sample.mpd")


val sourceConfig = SourceConfig.fromUrl("sample.mpd")


The Source is, next to the Player, the new main component in the SDK. See the documentation for more detailed insights.

To create an instance of a Source, a SourceConfig is needed. The SourceConfig can then be passed to a SourceBuilder to build a Source instance.

val source = new SourceBuilder(sourceConfig).build()

To load a Source into the Player, a new load function accepting a Source was added:

val source = new SourceBuilder(SourceConfig.fromUrl("some.mpd")).build()

If you don't need to handle Sources explicitly, you can still load a SourceConfig directly:

val sourceConfig = SourceConfig.fromUrl("some.mpd")

Event handling

We completely reworked how to manage event subscriptions to make it more intuitive and flexible in v3. You can now subscribe to events directly with a lambda or an EventListener<Event> implementation.

Event listener changes

In v2, addEventListener and removeEventListener was called with an event specific EventListener (e.g. the OnSourceLoadListener).
In v3, this functionality is now available as on and off. Additionally, the event specific listeners were replaced by two approaches that offer idiomatic usage from both Kotlin and Java:

Usage from Kotlin

// Quick fire-and-forget subscription
player.on<PlayerEvent.Ready> { println("Player is ready") }

// Adding a subscriber for an event and removing it later
val onPlayerActive: (PlayerEvent.Active) -> Unit = { println("Player is active") }


Usage from Java

// Quick fire-and-forget subscription
player.on(PlayerEvent.Ready.class, event -> System.out.println("Player is ready"));

// Adding an event listener for an event and removing it later
EventListener<PlayerEvent.Active> onPlayerActive = event -> System.out.println("Player is active");

player.on(PlayerEvent.Active.class, onPlayerActive);
player.off(PlayerEvent.Active.class, onPlayerActive);

More details and examples can be found in the EventEmitter documentation.

Source-specific events

Each Source can have its own event listeners to notify about changes in the source. To enable that, we split the existing BitmovinPlayerEvent into PlayerEvent and SourceEvent and introduced a separate sealed class hierarchy for both of them.


class BitmovinPlayerEvent { ... }
class ReadyEvent : BitmovinPlayerEvent { ... }
class SourceLoadedEvent: BitmovinPlayerEvent { ... }


sealed class Event { ... }

sealed class PlayerEvent : Event {
    class Ready() : PlayerEvent()

sealed class SourceEvent : Event {
    class Loaded() : SourceEvent()

We introduce the new Event class as the root type for all events. Each SourceEvent (e.g. SourceEvent.Loaded) extends SourceEvent and each PlayerEvent (e.g. PlayerEvent.Play) extends PlayerEvent.

Every SourceEvent emitted from the currently active Source will also be emitted through the Player.
This means that SourceEvents of a specific source can be received either on the specific Source instance directly or on the Player, if the source is active. In order to receive events for sources that are not active, event listeners must be added to each source directly.

When migrating a v2 workflow, there is naturally only one source which is always active, leading to all source-specific events being emitted trough the player. In general, this eliminates the requirement for listening for source specific events on a Source in single source use cases.

Listening for source-specific events

In order to listen for SourceEvents from a specific source, the same syntax as listening for PlayerEvents from the player is applied:

source.on<SourceEvent.Loaded> { ... }

Events related to source loading

The SourceEvent.Loaded and the SourceEvent.Unloaded equivalent events in v2 were often used to track the lifecycle of a player. With v3, these events are emitted per source, and also for non-active sources. In order to ensure that existing workflows still produce the expected results, new events for playback session tracking were introduced.

SourceLoadedEvent is emitted when the player is about to load a source indicating a source life-cycle has startedPlayerEvent.Active is emitted when the player received one or more sources and has started a playback session
SourceUnloadedEvent is emitted after the player finished unloading a source indicating that the source life-cycle has finishedPlayerEvent.Inactive is emitted when all sources were removed from the player and the playback session has finished

Error / Warning codes

WARNING: The integer values of the warning and error codes changed in v3.

Further, error and warning codes were restructured. In previous versions they were represented by plain integers on the respective ErrorCodes and WarningCodes classes.
They are now divided in Player, Source and Offline specific codes that are represented by enumerations. See the error and warning code documentation for further details.

The codes are surfaced by ErrorEvents or WarningEvents that can be a PlayerEvent, a SourceEvent as well as an OfflineErrorEvent.


Support for Cast Receivers with version 2 (former GoogleCastReceiverVersion.V2) was dropped. Going forward, only CAF-compatible receivers (former GoogleCastReceiverVersion.V3) are supported.

Casting package names

Special attention needs to be paid to package paths referenced in AndroidManifest files as they are easily missed. Be sure to replace the following packages in case you are using cast functionality.


UI / View

The new v3 Android SDK isn’t compatible with Bitmovin Player Web UI v2.x. To use the v3 SDK with a customized Bitmovin Player Web UI you will need to update your Player Web UI version to v3.x. The recommended version is 3.25.0 and above.

We continue to support Bitmovin Player Web UI v2.x for use with our v2 Android SDK only. More details on the Bitmovin Player Web UI can be found here.


We have updated our Android Samples GH Repository as well to get you started with our new major version 3 for Android. Check them out!