Skip to content

ExternalMediaAdapter Interface

The External Media Player (EMP) Adapter allows you to declare and use external media application sources in your application. In order to interface with the EMP Adapter, you must use one of the following:

  • A media connection client to interface the EMP Adapter to the external app.
  • An embedded media app. For information about external embedded media app solutions, contact your SA or Partner Manager.

Note: If the media app service requires additional customer experience details, incorporate the requirement in your implementation. For example, if the provider requires your application to show the provider's logo in a particular way, modify the implementation to meet the requirement.

When advised by your SA or Partner Manager, configure the External Media Player Adapter to the device's capabilities. See aace::alexa::config::AlexaConfiguration::createExternalMediaPlayerConfig for details on configuring the supported agent, or provide the equivalent JSON values in a configuration file.

{
  "aace.alexa": {
    "externalMediaPlayer": {
      "agent": "<agent>"
    }
  }
}

You must register and implement each ExternalMediaAdapter (along with its associated external client or library). After the engine establishes a connection to the Alexa service, you can run discovery to validate each external media application. You can report discovered external media players by calling reportDiscoveredPlayers() at any point during runtime. When the Alexa service recognizes the player, you will get a call to the Authorize message including the player's authorization status. Both the reportDiscoveredPlayers() method and the Authorize message can contain one or more players in their JSON payloads. Validating the application enables Alexa to exercise playback control over the registered source type.

The Login and Logout messages inform AVS of login state changes, if applicable. If your application has the ability to handle cloud-based login and logout, you should also publish the LoginComplete and LogoutComplete messages where appropriate.

When the user makes an Alexa voice request (for example, "Play Spotify"), the Play message is sent. This message contains various fields, including the player id of the player to which the playback information should be routed.

Whether through voice or GUI event, the PlayControl message is sent with the relevant PlayControlType. Similar to Play the control should be routed to the appropriate player.

The PlayControlType is determined by player's supportedOperations, which are specified by your implementation in the reply message of GetState.

The ExternalMediaAdapter interface provides messages PlayerEvent and PlayerError for your implementation to report events regarding the state of the playback session managed by your external player. Even though your player manages its own playback, including reacting to on-device transport control button presses from the user and reacting appropriately to other non-Alexa audio events on the system, the PlayerEvent and PlayerError calls provide important information to the Engine:

  1. The Engine may use calls to these methods to synchronize the state of your player’s playback session with Alexa.

  2. The Engine may react to these calls according to the event name specified to update its internal view of your player’s state. Particular event names indicate if the player is focused on the system (meaning it has an active playback session) or if it is un-focused (meaning it is not in use and is brought into use only by further on-device interaction by the user or a user voice request to Alexa). The Engine uses this information to sync its internal focus management.

The tables below describe each supported event name and what it means to the Engine. Usage of these events depends on the particular type of player controlled by the ExternalMediaAdapter instance, so contact your Solutions Architect (SA) or Partner Manager for guidance regarding supported embedded and external app solutions.

PlayerEvent name Description
"PlaybackSessionStarted" A new playback session has started, either from a GUI interaction or as a result of a user voice request to Alexa. The Engine considers the player active and in focus (although it may or may not yet be playing).
"PlaybackStarted" During an active session, the player has started to play or resumed from a paused state. The Engine considers the player active and in focus.
"TrackChanged" During an active session, one track has ended and another has started. The Engine uses this primarily for state reporting.
"PlaybackNext" During an active session, the player skipped from one track to the next track, either as a result of a GUI interaction or a user voice request to Alexa. The Engine uses this primarily for state reporting.
"PlaybackPrevious" During an active session, the player skipped from one track to the previous track, either as a result of a GUI interaction or a user voice request to Alexa. The Engine uses this primarily for state reporting.
"PlayModeChanged" During an active session, some user setting for the track or playback session changed, such as the favorite setting or the shuffle mode. The Engine uses this primarily for state reporting.
"PlaybackStopped" During an active session, the player has paused or stopped, either as a result of a GUI interaction or a user voice request to Alexa. The Engine considers the player active and in focus, just not currently playing. User voice requests to resume still control the player.
"PlaybackSessionEnded" An active playback session has ended. The player should no longer be playing or playable until a new session is started by GUI interaction or user voice request to Alexa. The Engine considers the player inactive and no longer in focus.
PlayerError name Description
"INTERNAL_ERROR" Any fatal player error has occurred
"UNKNOWN_ERROR" An unknown error occurred
"UNPLAYABLE_BY_AUTHORIZATION" The media couldn't be played due to an unauthorized account
"UNPLAYABLE_BY_STREAM_CONCURRENCY" The media couldn't be played due to the number of accounts currently streaming
"UNPLAYABLE_BY_ACCOUNT" The media couldn't be played due to the account type
"UNPLAYABLE_BY_REGION" The media couldn't be played due to the current region
"UNPLAYABLE_BY_PARENTAL_CONTROL" The media couldn't be played due to parental settings
"UNPLAYABLE_BY_SUBSCRIPTION" The media couldn't be played due to the subscription type
"OPERATION_REJECTED_UNINTERRUPTIBLE" The operation could not be performed due to non interruptible media
"OPERATION_REJECTED_END_OF_QUEUE" The operation could not be performed due to the end of media being reached
"OPERATION_UNSUPPORTED" The operation was not supported
"OPERATION_REJECTED_SKIP_LIMIT" The operation failed because a skip limit was reached
"PLAYER_UNKNOWN" An unknown player was detected
"PLAYER_NOT_FOUND" The player was not discovered
"PLAYER_CONNECTION_REJECTED" The connection to the player failed
"PLAYER_CONNECTION_TIMEOUT" The connection to the player timed out

The Seek and AdjustSeek messages are invokable via Alexa if the currently in-focus external player supports them. Seek specifies an absolute offset, whereas AdjustSeek specifies a relative offset.

The VolumeChanged and MutedStateChanged messages are invoked to change the volume and mute state of the currently-focused external player. VolumeChanged specifies the new volume. MutedStateChanged specifies the new MutedState.

The GetState message is called to synchronize the external player's state with the cloud. This method is used to maintain correct state during startup, and after every Alexa request.

You construct the ExternalMediaAdapterState object using the data taken from the media app connection client or embedded player app (associated via localPlayerId) and return the state information.

The following table describes the fields comprising a ExternalMediaAdapterState, which includes two sub-components: PlaybackState, and SessionState.

State Type Required Notes
PlaybackState
state String Yes "IDLE"/"STOPPED"/"PLAYING"
supportedOperations SupportedPlaybackOperation[] Yes see SupportedOperation
trackOffset long No optional
shuffleEnabled boolean Yes report shuffle status
repeatEnabled boolean Yes report repeat status
favorites Favorites No see Favorites
type String Yes must be set as "ExternalMediaPlayerMusicItem"
playbackSource String No If available else use local player name
playbackSourceId String No empty
trackName String No If available else use local player name
trackId String No empty
trackNumber String No optional
artistName String No optional
artistId String No empty
albumName String No optional
albumId String No empty
tinyURL String No optional
smallURL String No optional
mediumURL String No optional
largeURL String No optional
coverId String No empty
mediaProvider String No optional
mediaType MediaType Yes see MediaType
duration long No optional
SessionsState
endpointId String No empty
loggedIn boolean No empty
userName String No empty
isGuest boolean No empty
launched boolean Yes true if the source is enabled, false otherwise
active boolean Yes true if the application is in an active state
accessToken String No empty
tokenRefreshInterval long No empty
playerCookie String No A player may declare arbitrary information for itself
spiVersion String Yes must be set as "1.0"

supportedOperations should be a list of the operations that the external media adapter supports. Below is a list of all possible supportedOperations.

SupportedPlaybackOperation.PLAY,
SupportedPlaybackOperation.PAUSE,
SupportedPlaybackOperation.STOP,
SupportedPlaybackOperation.PREVIOUS,
SupportedPlaybackOperation.NEXT,
SupportedPlaybackOperation.ENABLE_SHUFFLE,
SupportedPlaybackOperation.DISABLE_SHUFFLE,
SupportedPlaybackOperation.ENABLE_REPEAT_ONE,
SupportedPlaybackOperation.ENABLE_REPEAT,
SupportedPlaybackOperation.DISABLE_REPEAT,
SupportedPlaybackOperation.SEEK,
SupportedPlaybackOperation.ADJUST_SEEK,
SupportedPlaybackOperation.FAVORITE,
SupportedPlaybackOperation.UNFAVORITE,
SupportedPlaybackOperation.FAST_FORWARD,
SupportedPlaybackOperation.REWIND,
SupportedPlaybackOperation.START_OVER

Note: Currently PLAY/PAUSE/STOP will always be supported for a source. Passing null will allow ALL supported operations for the source.