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)
- Twilio Live Player Android SDK 1.0.1 [Maven Central], [docs]
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)
- Twilio Live Player Android SDK 1.0.0 [Maven Central], [docs]
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 aPlayerView
and set theplayer.playerView
property.
val player = Player.connect(...)
player.playerView = playerView
- Added
PlayerStats
class andplayer.stats
property to view a live stream's stats. - Added a
PlayerStats
property to thePlaybackQuality.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
afteronFailed(...)
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 from1.0.0-preview5
through1.0.0-preview7
will result in anAccessTokenInvalid
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 uniquecode
property. Additionally, the class now includes a nullableexplanation
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 JSONplayer
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. ThePlayer.connect(..)
API returns aPlayer
in theIDLE
state. - Removed
playerSid
property fromPlayer
,TelemetryData.Connection
,TelemetryData.Playback
,TelemetryData.PlaybackQuality
,TelemetryData.PlaybackState
andTelemetryData.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 istrue
by default. The Player SDK considers aplayer.liveLatency
value greater than 3 seconds as an occurrence of high latency. When this property is enabled, the Player SDK will periodically inspectplayer.liveLatency
and perform the following when high latency is observed:
- 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.
- 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 thePlayer
reaches theIDLE
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
, andPlayerSdk.version
have been moved to thePlayer
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 thePlayerListener
callback interface. This callback will be invoked when thePlayer
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
andavailableQualities
. Thequality
property represents the quality of the stream and theavailableQualities
property represents a list of supported qualities from a stream. TheavailableQualities
andquality
properties will contain an empty list and empty values respectively, until the player reaches thePlayerState.READY
state. Thequality
property can only be set to a value contained in theavailableQualities
list, otherwise the player throws anIllegalArgumentException
. 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"
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.