Menu

Expand
Rate this page:

Android Player SDK Changelog

We are no longer allowing new customers to onboard to Twilio Live. Effective November 30, 2023, Twilio Live will End of Life. We have created this Migration Guide to help you identify an alternative solution for your use case.

1.0.1 (January 27, 2022)

Bug Fixes

  • Fixed stuttering when playing a stream from a source media playlist.
  • Fixed a bug where a loaded stream could play without the play method being called, during a network reconnect.
  • Improved player stability by reducing occurrences of rare crashes.

Size Report

ABI APK Size Impact
x86 1.5MB
x86_64 1.5MB
armeabi-v7a 1.3MB
arm64-v8a 1.4MB
universal 4MB

1.0.0 (October 19th, 2021)

The Twilio Live Player Android SDK is now generally available!

Migrating from 1.0.0-preview11

To update your applications from a preview release, please rename usages of com.twilio.player to com.twilio.live.player.

Size Report

ABI APK Size Impact
x86 1.5MB
x86_64 1.5MB
armeabi-v7a 1.2MB
arm64-v8a 1.4MB
universal 4MB

1.0.0-preview11 (September 1, 2021)

Bug Fixes

  • Fixed a crash transitioning the Player from the READY to the IDLE state.

1.0.0-preview10 (August 20, 2021)

Enhancements

  • Introduced a PlayerView that enables an application to render a live stream to an app's view hierarchy. To render a stream in your app, instantiate a PlayerView and set the player.playerView property.
val player = Player.connect(...)

player.playerView = playerView
  • Added PlayerStats class and player.stats property to view a live stream's stats.
  • Added a PlayerStats property to the PlaybackQuality.Summary telemetry event.

1.0.0-preview9 (August 12, 2021)

Maintenance

  • Updated the project's Android Gradle Plugin to 7.0.0 and Gradle version to 7.0.2.

Bug Fixes

  • Fixed a null pointer exception that would occur when attempting to access player.qualities after onFailed(...) was invoked.
  • Fixed an issue where increasing the playback rate to reduce latency resulted in an onFailed being emitted.

Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.

1.0.0-preview8 (August 4, 2021)

Breaking API Changes

  • Player.connect(...) has been updated to accept a Twilio Access Token with a PlaybackGrant whose type is a JSON object instead of a stringified JSON. Providing a playback grant as stringified JSON as recommended from 1.0.0-preview5 through 1.0.0-preview7 will result in an AccessTokenInvalid error.

Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.

1.0.0-preview7 (July 28, 2021)

Enhancements

  • The SDK will now retry connecting to a stream when a recoverable error is detected upon the invocation of Player.connect(...)

Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.

1.0.0-preview6 (July 22, 2021)

API Updates

  • PlayerException has been updated to include a unique code property. Additionally, the class now includes a nullable explanation property that provides more details about the error that occurred.
  • PlayerException now includes constant definitions for all the unique error code values. The table below describes each error code.
Code Constant Name Description
20101 ACCESS_TOKEN_INVALID_EXCEPTION Twilio was unable to validate your Access Token
56000 PLAYBACK_MEDIA_ERROR_EXCEPTION An error occurred playing back media content
56001 PLAYBACK_AUTHORIZATION_ERROR_EXCEPTION A network resource is not authorized
56002 PLAYBACK_INVALID_DATA_EXCEPTION Data or input is invalid
56003 PLAYBACK_INVALID_PARAMETER_EXCEPTION A method parameter is invalid
56004 PLAYBACK_INVALID_STATE_EXCEPTION The Player or an internal object is in an invalid state
56005 PLAYBACK_NETWORK_ERROR_EXCEPTION A network error occurred
56006 PLAYBACK_NETWORK_IOERROR_EXCEPTION A network I/O error occurred
56007 PLAYBACK_STREAM_NOT_AVAILABLE_EXCEPTION The stream is not available
56008 PLAYBACK_TOO_MANY_STREAMING_REQUESTS_EXCEPTION The current-viewers limit was reached
56009 PLAYBACK_NOT_SUPPORTED_EXCEPTION A method or feature is not supported
56010 PLAYBACK_NO_SOURCE_EXCEPTION There is no source for the Player to play
56011 PLAYBACK_TIMEOUT_EXCEPTION The Player timed out performing an operation

Maintenance

  • Updated the project to use Android Gradle Plugin 4.2.2.

Bug Fixes

  • Updated the behavior of Player.connect(...) to only supported a stringified JSON player grant.
  • Removed unused internal thread used for previous authentication mechanism.
  • Stop quality reporting when onFailed is emitted.

Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.

1.0.0-preview5 (July 9, 2021)

Breaking API Changes

  • Player.connect(...) has been updated to accept a Twilio Access Token with a PlaybackGrant. Please note that the 1.0.0-preview5 Player SDKs are not backwards compatible with the previously generated AccessTokens.

  • Removed CONNECTING player state. The Player.connect(..) API returns a Player in the IDLE state.

  • Removed playerSid property from Player, TelemetryData.Connection, TelemetryData.Playback, TelemetryData.PlaybackQuality, TelemetryData.PlaybackState and TelemetryData.TimedMetadataTelemetry classes.

Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.

1.0.0-preview4 (July 1, 2021)

API Updates

  • Added a static property Player.isHighLatencyReductionEnabled that is true by default. The Player SDK considers a player.liveLatency value greater than 3 seconds as an occurrence of high latency. When this property is enabled, the Player SDK will periodically inspect player.liveLatency and perform the following when high latency is observed:
  1. If the live latency is between 3 and 5 seconds, the Player will increase the playback rate to a value that should not be perceptible to a user. The increased playback rate will allow the Player to catch up to the live source, and will be reverted once the live latency drops below 3 seconds. Application of this strategy may result in audio pitch distortion.
  2. If the live latency is greater than or equal to 5 seconds, the Player will seek ahead to near the end of the Player's buffered content. The user will notice skips in the media content when this strategy is applied.
New telemetry events
Telemetry Data Reporting Details
TelemetryData.PlaybackQuality.HighLatencyReductionApplied Reported when the SDK applies a high latency reduction strategy.
TelemetryData.PlaybackQuality.HighLatencyReductionReverted Reported when the SDK reverts all high latency reduction strategies.

Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.

1.0.0-preview3 (June 15, 2021)

Enhancements

Telemetry

The Telemetry API enables applications to subscribe to event and metric data collected by the Player SDK. Telemetry data emitted by the Player SDK can be used to track stream quality, triage issues, and better understand your application's Player SDK usage.

Typed Data Events

The Player SDK represents telemetry data as strongly typed classes. Reference the table below for a summary of the currently reported events.

Type Reporting Details
TelemetryData.Connection.Connecting Reported when Player.connect(...) is called
TelemetryData.Connection.Connected Reported when the Player is connected to Twilio Media Service
TelemetryData.Connection.NetworkUnavailable Reported when onNetworkUnavailable is invoked
TelemetryData.Connection.Disconnected Reported when Player.disconnect() is called
TelemetryData.Connection.Error Reported when onFailed is invoked in the CONNECTING state
TelemetryData.Playback.Played Reported when player.play() is called
TelemetryData.Playback.Paused Reported when player.pause() is called
TelemetryData.Playback.VolumeSet Reported when player.volume is set
TelemetryData.Playback.Muted Reported when player.isMuted is set to true
TelemetryData.Playback.Unmuted Reported when player.isMuted is set to false
TelemetryData.Playback.Error Reported when onFailed is invoked in the following states: IDLE, READY, PLAYING, BUFFERING
TelemetryData.Playback.Rebuffering Reported when onRebuffering is invoked
TelemetryData.PlaybackQuality.Summary Reported every three seconds while the player is BUFFERING or PLAYING
TelemetryData.PlaybackQuality.QualitySet Reported when player.quality is set
TelemetryData.PlaybackQuality.QualityChanged Reported when onQualityChanged is invoked
TelemetryData.PlaybackQuality.VideoSizeChanged Reported when onVideoSizeChanged is invoked
TelemetryData.PlaybackState.Changed Each state is reported when onStateChanged is invoked
TelemetryData.TimedMetadataTelemetry.Received Reported when onTimedMetadata is invoked
Usage

The following snippets demonstrate a few examples of how to use the Telemetry API.

Telemetry Logger

The following snippet demonstrates the simplest Telemetry example: Logging all Telemetry events emitted by the Player SDK

val telemetryLogger: TelemetrySubscriber = {
    Log.d("PlayerSdkTelemetry", it.toString())
}

// Subscribe the logger to events
Player.telemetry.subscribe(telemetryLogger)

// .. When your app no longer wants telemetry events, unsubscribe
Player.telemetry.unsubscribe(telemetryLogger)

Track High Latency

The following snippet demonstrates an example of checking experience quality by tracking any instances of high latency.

Player.telemetry.subscribe({
    if (it is TelemetryData.PlaybackQuality.Summary && it.playerLiveLatency > 3000) {
        yourAppsAnalytics.track("high-latency-detected")
    }
})

Track Connection Errors

The following snippet demonstrates an example of using TelemetryPredicate's to filter on specific Telemetry events.

Player.telemetry.subscribe({ yourAppAnalytics.track("connection-error-detected") }) {
    it is TelemetryData.Connection.Error
}

API Updates

  • Added Player.streamerSid property which represents a PlayerStreamer SID. This property is an empty string until the Player reaches the IDLE state.

Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.

1.0.0-preview2 (June 3, 2021)

API Updates

  • Removed the PlayerSdk class. PlayerSdk.connect(...), PlayerSdk.logLevel, and PlayerSdk.version have been moved to the Player class. Reference the following snippet to update your application.

1.0.0-preview1

PlayerSdk.logLevel = LogLevel.DEBUG

PlayerSdk.version

val player = PlayerSdk.connect(...)

1.0.0-preview2

Player.logLevel = LogLevel.DEBUG

Player.version

val player = Player.connect(...)
  • Added onNetworkUnavailable to the PlayerListener callback interface. This callback will be invoked when the Player loses network connectivity.

Enhancements

  • Playback is now automatically paused when the network connection is lost, and it is resumed when the connection is restored.
  • Improved the accuracy of Player.liveLatency.
  • Improved the Adaptive Bitrate Streaming algorithm to improve stream quality more quickly when network connections improve.
  • Added two properties to the Player class: quality and availableQualities. The quality property represents the quality of the stream and the availableQualities property represents a list of supported qualities from a stream. The availableQualities and quality properties will contain an empty list and empty values respectively, until the player reaches the PlayerState.READY state. The quality property can only be set to a value contained in the availableQualities list, otherwise the player throws an IllegalArgumentException. Please note that by default, the SDK automatically changes the quality based on device and network conditions. Once the quality is set by an app, the SDK will stop automatically adjusting the quality.
val player = Player.connect(context, "access token", object : PlayerListener {
    override fun onStateChanged(player: Player, playerState: PlayerState) {
        when (playerState) {
            PlayerState.READY -> {
                player.quality = player.availableQualities.first()
            }
        }
    }
})

Bug Fixes

  • Improved Player stability
  • Fixed an issue where the SDK crashed if the app targeted Android 11 (API level 30) and the user was running Android 11 on a cellular network.
  • Fixed an issue where the SDK could crash if the client app uses an old (pre-4.0) version of OkHttp.

Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.

1.0.0-preview1 (May 6, 2021)

The Twilio Player Android SDK lets you play a stream in your native Android application.

Usage

The following snippets provide demonstrations on how to use the Player Android SDK in an app. For more details about streaming content, visit the Twilio Live documentation.

Connecting a Player and Handling Events

Once your app acquires a Twilio access token, you can connect to a stream.


val player = PlayerSdk.connect(context, "access token", object : PlayerListener {
    /**
     * The player instance is returned in the PlayerState.CONNECTING state after calling connect.
     */
    override fun onStateChanged(player: Player, playerState: PlayerState) {
        when (playerState) {
            PlayerState.IDLE -> {
                /**
                 * The player has successfully authenticated and is loading the stream. This
                 * state is also reached as a result of calling player.pause().
                 */
            }
            PlayerState.READY -> {
                /**
                 * The player is ready to playback the stream.
                 */
            }
            PlayerState.PLAYING -> {
                /**
                 * The player is now playing a stream. This state occurs as a result of calling
                 * player.play().
                 */
            }
            PlayerState.BUFFERING -> {
                /**
                 * The player is buffering content.
                 */
            }
            PlayerState.ENDED -> {
                /**
                 * The stream has ended.
                 */
            }
        }
    }

    override fun onFailed(player: Player, playerException: PlayerException) {
        /**
         * An error occurred connecting the player or loading a stream.
         */
    }
})

Managing Playback

The following snippets demonstrate how to manage playback in your app.


/**
 * Once the Player reaches the PlayerState.READY state after initially calling
 * PlayerSdk.connect(...), an application can invoke play(). The player will then transition to
 * the PlayerState.PLAYING state once playback successfully begins.
 *
 * play() can also be called during the PlayerState.IDLE state only after transitioning as a result
 * of calling pause().
 */
player.play()

/**
 * To pause playback, invoke pause(). The player will transition to PlayerState.IDLE
 * until playback is resumed with a subsequent call to play().
 */
player.pause()

/**
 * Playback audio can be muted by updating the isMuted property.
 */
player.isMuted = true

/**
 * The playback volume can also be adjusted. Updating the isMuted property has no effect
 * on the volume property. Once a stream is un-muted, playback will ensue with the last set
 * player volume.
 */
player.volume = 0.25f

Using TimedMetadata

When your application inserts TimedMetadata into a stream, the player will emit the onTimedMetadata callback if the player is in the PlayerState.PLAYING state. TimedMetadata will not be received if the player is paused and any data inserted while a player is paused will not be received once the player is resumed.


val playerListener = object : PlayerListener {
    override fun onTimedMetadata(player: Player, metadata: TimedMetadata) {
        /**
         * Handle the data
         */
    }
}

Disconnecting a Player

In order to free resources, the player should be disconnected when your application no longer requires the instance.


/**
* Disconnect the player and transition the player to the PlayerState.ENDED state. The player object
* is no longer usable.
*/
player.disconnect()

Threading Contract

The Player Android SDK does not provide thread safety. Developers should use a Player instance from a single thread. Typically, this will be the UI thread. All callbacks will be emitted on the same thread that called PlayerSdk.connect(...). The SDK does log warnings if a threading violation is detected.


val player = PlayerSdk.connect(...)

/**
 * This will result in a warning log!
 */
Thread {
    player.isMuted = true
}.start()


Known Issues

  • This release only enables developers to build audio-only experiences. Rendering a stream to a video view will be implemented in a subsequent release.
  • The Player Android SDK has a runtime dependency on OkHttp version 4.2.2. Using OkHttp version 3.x may result undefined behavior due to backwards compatibility issues. If your application demonstrates any runtime issues with OkHttp, update your application to use a compatible version of OkHttp. The example below demonstrates how to update an application's usage of Retrofit to include a compatible version of OkHttp.


implementation("com.squareup.retrofit2:retrofit:2.9.0") {
    exclude(group: "com.squareup.okhttp3", module: "okhttp")
}
implementation "com.squareup.okhttp3:okhttp:4.2.2"
Rate this page:

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Stack Overflow Collective or browsing the Twilio tag on Stack Overflow.

Loading Code Sample...
        
        
        

        Thank you for your feedback!

        Please select the reason(s) for your feedback. The additional information you provide helps us improve our documentation:

        Sending your feedback...
        🎉 Thank you for your feedback!
        Something went wrong. Please try again.

        Thanks for your feedback!

        thanks-feedback-gif