HotMicMediaPlayer allows you to integrate your own player into your application. In order do to this, you must:
Include the player in your application to be played. (e.g. Bitmovin, JWPlayer, Exo).
Use our protocol to forward commands to your player when the HotMic protocol dictates (e.g. pause the player).
Send to HotMic various player events (e.g. notify HotMic the player is paused).
For using a custom player, the implementation should do the following:
Extend their custom player to support the BaseHMPlayer implementation.
Implement the PlayerCallback getPlayer() function
BaseHMPlayer Interface
This code shows the different values and functions in the BaseHMPlayer interface. If you have any questions about this, please contact our team.
Kotlin
|
/**
* HotMic player interface
*/interface BaseHMPlayer {/** Return the tag that was passed to the player by the sdk */val playerTag: String
/**
* Initialize the player and load the media url * @param url: media url to be loaded
*/funload(url: String?)/**
* Return the player view. Ensure that the player view does not, by
default, show any inbuilt
* controls
*/val playerView: View
/** Returns PDT of the feed */val time: Long
/** Returns the current position of the video (in ms) */val position: Long
/** Returns true if the video is playing */val isPlaying: Boolean
/** Get/sets the audio volume as an integer between 0 and 100 (0 being
mute) */var volume: Int
/** Returns true if the player was muted. Note vol = 0 is not
necessarily muted */val isMuted: Boolean
/**
* Mutes/Unmutes the audio, Unmuting the video should restore the
volume to what the set
* volume earlier was and not the max value
*/funmute(mute: Boolean)/** Play the video */funplay()/** Pauses the video */funpause()/** Returns true if the media that the player is playing is Live */val isLiveContent: Boolean
/** Returns the player progress info, incl. the total video duration,
current position,
* buffered position */fungetProgress(): HMPlayerProgress
/**
* Sets the player to play the video in the given play rate. A normal
play will be 1.0
*/funsetPlayRate(rate: Double)/**
* Returns the current state of the player -
idle/playing/ready/buffering/ended/error
*/val playState: HMPlayerState
/**
* Seeks the video timeline by the given offset. A positive offset will
seek forward
* @param offsetAddedInMS: offset, in milliseconds, to be added to the
timeline */funseekToOffset(offsetAddedInMS: Long)/**
* Seeks the video directly to the given position.
* @param newPosition: position, in millisecond, to jump to */funseekTo(newPosition: Long)/**
* Close the player. Release the player and all params reset
*/funclose()}
ο»Ώ
ο»Ώ
Player Callback Interface
This function is how you define whether you want to use a custom, third party player, or the default one. Implement the getPlayer function in the callback to return a custom player. Returning null will result in the SDK using the inbuilt exo player implementation.
Kotlin
|
/**
* Optional
* If your implementation wants to use a custom player, then ooverride
* this method to construct and return the player * @param context
* @param tag String to identify the player. The implementation has to return this string in
* the BaseHMPlayer.tag variable
* @param listener Callbacks that the player implementation should call on
media state change
* or error
* @return custom implementation which implements BaseHMPlayer. if null,
then default exoplayer
* will be used
*/fungetPlayer(
context: Context,
tag: String,
listener: HMPlayerEventListener
): BaseHMPlayer?{returnnull}
ο»Ώ
ο»Ώ
Other supporting classes
For your reference, these are other classes which may be helpful with your custom player implementation.
Player Event Listener
Kotlin
|
/**
* Listener, which defines the callbacks to be called when the player
implementation encounters
* certain events like state change, error
*/interface HMPlayerEventListener {/**
* On encountering any kind of error, the player implementation should
classify the error
* and then call this method
* @param tag : tag associated with the player, useful when there are
multiple players, Use
* the same tag that was provided to teh player implementation by the
player
* @param error: Type and details of the error encountered by the player
*/funonPlayerError(tag: String, error: HMPlayerError)/**
* Callback triggered when there is a play state change in the player.
The player implementation
* should classify the state to one of the recognized states
* @param tag : tag associated with the player, useful when there are
multiple players, Use
* the same tag that was provided to teh player implementation by the
player
* @param mediaState
*/funonMediaStateChanged(tag: String, mediaState: HMPlayerState)}
ο»Ώ
Player Error Class
Kotlin
|
/**
* Holds details of the error encountered by the player
*/dataclassHMPlayerError(/** Type of error */val type: HMPlayerErrorType,/** Error code returned by the player. If an error message is shown to
this user, then this
* detail will be included in it*/val responseCode: String,/** Any debugging data can be added in this field. This will be passed
to analytics */val analyticReason: String ="",/** Optional - For overwriting the default error message. This would be
displayed to the user. */var displayMessage: String?=null)
ο»Ώ
Player Error Type Enum
Kotlin
|
enumclassHMPlayerErrorType(//Player will try implicit retry at defined intervalsval autoRetry: Boolean,//String resource for the message to be displayed to the user val messageResId: Int){/** Network error. For reference the following exo-player errors will
fall in this category -
* ERROR_CODE_TIMEOUT,
* ERROR_CODE_IO_UNSPECIFIED,
* ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
* ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT,
* ERROR_CODE_IO_BAD_HTTP_STATUS,
/** Error not recognized */ERR_UNKNOWN(false, R.string.err_player_general),* ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE
**/ERR_NETWORK_CONN(true, R.string.err_player_network),/** Media file was not found or no permission to fetch file. For
reference the following
* exo-player errors will fall in this category -
* ERROR_CODE_IO_FILE_NOT_FOUND,
* ERROR_CODE_IO_NO_PERMISSION
* */ERR_MEDIA_NOT_FOUND(true, R.string.err_player_general),/** Media format is not correct or is corrupted. Decoding failure. For
reference the following
* exo-player errors will fall in this category -
* ERROR_CODE_DECODER_INIT_FAILED,
* ERROR_CODE_DECODER_QUERY_FAILED,
* ERROR_CODE_DECODING_FAILED,
* ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES,
* ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
* */ERR_INVALID_CONTENT(false, R.string.err_player_general_no_retry),/** Loading position falling behind the sliding window of available
live content. For reference
* the following exo-player errors will fall in this category -
* ERROR_CODE_BEHIND_LIVE_WINDOW
* */ERR_BEHIND_LIVE_WINDOW(true, R.string.err_player_general),/** Player is in an unexpected state, possibly due to malformed hls.
This happens usually at
* the start and end of the live hls stream. Player will not show this
error to the user, it
* will wait while it keeps retrying. For reference the following exo-
player errors will fall
* in this category -
* ERROR_CODE_PARSING_MANIFEST_MALFORMED,
* ERROR_CODE_PARSING_CONTAINER_MALFORMED,
* ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED,
* ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED
* */ERR_PLAYER_ONHOLD(true, R.string.err_player_general)}
ο»Ώ
Player State Enum
Kotlin
|
enumclass HMPlayerState {/** Player is idle, no url loaded */ MEDIA_IDLE,/** Player is playing, time line is moving */
MEDIA_PLAYING,/** Player is ready to play, but possibly paused */
MEDIA_READY,/** Player is buffering media */
MEDIA_BUFFERING,/** Player has finished playing the data */
MEDIA_ENDED,/** Error encountered while trying to play */
MEDIA_ERROR
}
ο»Ώ
Player Progress Data
Kotlin
|
/**
* For any given point of time, this construct will hold the video progress
details like the duration, current position of the video player
*/dataclassHMPlayerProgress(/** Total duration of the video in milliseconds */val duration: Long =0L,/** Current position of the video in milliseconds */val currentPosition: Long =0L,/** Estimate of the position in the current content up to which data is
buffered, in milliseconds. */val bufferedPosition: Long =0L,/** True if the player is currently seeking to a new position */val isSeeking: Boolean =false,)