Learn how to use the Uplynk Android Player Library.
Download the latest SDK from the CMS by following the "Download Player SDK" link, which can be found in the lower left-hand corner, and then selecting "Android". Alternatively, contact Uplynk support to receive a link to the latest version of this library.
Supported Android versions:
Android Version | Level of Support |
---|---|
2.3 Gingerbread 4.0 Ice Cream Sandwich 4.1 Jelly Bean 4.2 Jelly Bean 4.3 Jelly Bean 4.4 KitKat |
Support for most major brands and chipsets. |
5.x Lollipop 6.x Marshmallow 7.x Nougat 8.x Oreo |
General compatibility via MediaCodec API. |
Compatibility testing and support is limited to latest firmware for a given device.
The Uplynk Android Player API mirrors that of android.media.MediaPlayer [API Level 14] and generally allows for a direct replacement by swapping imports. This section describes Uplynk MediaPlayer-specific:
MediaPlayer.OnAssetBoundaryListener
MediaPlayer.OnCaptionEventListener
MediaPlayer.OnID3MetadataListener
MediaPlayer.OnUplynkMetadataListener
MediaPlayer.OnUplynkSegmentListener
Uplynk Segments Events are fired when a playlist is updated / reloaded and indicate a map of assets that make up the media.
Name | Description |
---|---|
TEXT_SIZE_XSMALL |
50% of native size |
TEXT_SIZE_SMALL |
75% of native size |
TEXT_SIZE_NORMAL |
100% of native size |
TEXT_SIZE_LARGE |
150% of native size |
TEXT_SIZE_XLARGE |
200% of native size |
EDGE_TYPE_NONE |
No special edge type. |
EDGE_TYPE_DROP_SHADOW |
Drop shadow effect for caption text. |
EDGE_TYPE_RAISED |
Raised effect for caption text. |
EDGE_TYPE_DEPRESSED |
Depressed effect for caption text. |
EDGE_TYPE_UNIFORM |
Outline effect for caption text. |
setBackgroundColor(int):void |
Caption text background color in Android color hexadecimal format (0xaarrggbb). Default value: 0xff000000 {*} |
setCaptionPreviewText(int row, int column, String text):void |
Sets the starting row (1 -15), starting column (1-32), and the text to be displayed as a Caption Preview. |
setEdgeType(int):void |
Edge effect from EDGE_TYPE constants. Default=EDGE_TYPE_NONE |
setTextColor(int):void |
Caption text color in Android color hexadecimal format (0xaarrggbb). Default value: 0xffffffff {*} |
setTextSize(int):void |
Caption text size adjustment percentage as integer [50-200]. Default value: TEXT_SIZE_NORMAL or 100% |
setTypeface(Typeface):void |
Caption text font. Default value: MONOSPACE |
setWindowColor(int):void |
Caption background area color in Android color hexadecimal format. Default value: 0x00000000 {*} |
Color values are expressed as android.graphics.Color packed integers.
Name | Description |
---|---|
mode:CaptionMode |
Returns mode in range UNKNOWN,POP_ON,ROLL_UP,PAINT_ON. |
eventType:CaptionEventType |
Returns event type in range TEXT,LINEBREAK,CLEAR. |
rowCount:short |
Returns the number of rows that should be used for painting text when mode==ROLL_UP. |
rows:SparseArray<CaptionRow> |
Returns a list of CaptionRow objects (populated when mode==POP_ON). |
character:CaptionCharacter |
Returns a single CaptionCharacter object. |
Name | Description |
---|---|
character():char |
Character |
color():int |
Color as 0xrrggbb |
isItalic():boolean |
True if character should be italicized. |
isUnderlined():boolean |
True if character should be underlined. |
Name | Description |
---|---|
getRow():int |
Row index |
getColumn():int |
Column index |
getIndent():int |
Column position offset |
getText():String |
Row text as a plain string |
getCharacters():Vector |
List of character objects with style attributes |
Name | Description |
---|---|
getAssetID():String |
Asset ID (GUID) |
getOwner():String |
User ID |
getDescription:String |
Content description as defined in the CMS. |
isAudioOnly():boolean |
Indicates if content only contains audio. |
isAd():boolean |
Indicates if content is flagged as an ad in the CMS. |
hasError():boolean |
If true, there was an error retrieving asset information. |
getTvRating():int |
TV rating as defined in the CMS. |
getMovieRating():int |
Movie rating as defined in the CMS. |
getRatingFlags():int |
Rating flags as defined in the CMS. |
getMaxSlice():int |
Gets the total number of slices. |
getDuration():double |
Length in milliseconds of content. |
getSliceDuration():double |
Length in milliseconds of each slice. |
getThumbnailPrefix():String |
URL thumbnail path prefix |
Name | Description |
---|---|
getKey():String |
ID3 tag name |
getValue():String |
ID3 tag value |
Name | Description |
---|---|
getAssetID():String |
Asset ID (GUID) |
getRay():String |
Ray Alpha Index (A-G) |
getSliceIndex():String |
Slice number in hex. |
getSliceNumber():int |
Slice number in decimal. |
getAssetInfo():UplynkAssetInfo |
UplynkAssetInfo object describing the current slice (can be NULL). |
Defines a piece of a playlist. Use the offset for calculating the correct timecode for loading thumbnails.
Name | Description |
---|---|
getType():char |
Type flag of segment { A=Ad, C=Content }. |
getDuration():double |
Duration of the segment in seconds. |
getOffset():double |
Index offset from the beginning of the specified asset. |
getAssetId():String |
Asset ID |
Name | Description |
---|---|
getType():char |
Type Flag of Track { A=Audio, S=Subtitle } |
getName():String |
Track Name |
getGroup():String |
Track Group Name |
getLang():String |
Track Language |
Method | Description |
---|---|
getAudioTrackOptions():Vector<UplynkTrackInfo> |
[Build 64] Retrieves a list of audio tracks. May return an empty list when there are no alternate audio tracks available. Valid Player States { PREPARED | PLAYING | PAUSED } |
getDisplayRectForMaxDimensions(maxWidth, maxHeight):Rect |
[Build 86] Returns a Rect of the content dimensions with proper aspect ratio given a set of bounds. |
getPlaybackBitrate():int |
[Build 90] Returns the current variant's reported bitrate in bps |
selectAudioTrack(int):boolean |
[Build 64] Sets the target audio track index. zero is always the default audio track. Valid Player States { PREPARED | PLAYING | PAUSED } |
setContext(Context):void |
Allows persisting bandwidth stats by writing to a file in the apps private storage. |
setCaptionChannel(int):void |
Sets the preferred caption channel [1-4]. |
setCaptionStyle(CaptionStyle):void |
Sets the visual properties of the captions. |
setMaxBitrate(int):void |
Limits the variant selection by specified value in Kbps. Example: 500=500Kbps streams or less |
setCaptionsEnabled(boolean):void |
Enables/disables the display of closed captions in configured container. |
setCaptionLayoutContainer(RelativeLayout):void |
Sets the target container that closed captions will be created in. The RelativeLayout is assumed to be directly over the video SurfaceView with matching dimensions. |
setOnAssetBoundaryListener(OnAssetBoundaryListener):void |
Register for Content Boundary Events that are triggered when content changes, such as entering or leaving ad break. Note: this event my be received twice, once with an Asset ID of the new asset and once with a null asset id to signify an ad marker. |
setOnCaptionEventListener(OnCaptionEventListener):void |
Register for Caption Events to receive caption text. |
setOnID3MetadataListener(OnID3MetadataListener):void |
Register for ID3 Metadata Events to receive name/value pairs. |
setOnUplynkMetadataListener(OnUplynkMetadataListener):void |
Register for Metadata Events that are fired for each slice. |
setOnUplynkSegmentListener(OnUplynkSegmentListener):void |
Register for Segment List Events that are fired during playlist updates. |
setVolume(float leftVolume, float rightVolume):void |
Scaler values normalized in range of 0.0 to 1.0. Volume setting is local to player and does not affect device volume. |
Class Methods | Description |
---|---|
getDisplayRectForMaxDimensionsAndVideoDimensions(maxWidth, maxHeight, videoWidth, videoHeight):Rect |
[Build 86] Returns an aspect ratio constrained Rect for a given set of Max display bounds and content dimensions. |
initSurfaceHolder(SurfaceHolder):void |
Allows for configuration of a SurfaceHolder to render correctly with the current device hardware. This must be called on the SurfaceHolder BEFORE passing the SurfaceHolder to a MediaPlayer instance via setDisplay(SurfaceHolder). |
Captions can be accessed either by allowing the MediaPlayer to display the captions or by registering an event listener to receive notifications (or both)
Configure MediaPlayer to display the captions.
Register for caption events.
Activity Setup
import com.uplynk.media.CaptionEvent; import com.uplynk.media.CaptionEvent.CaptionEventType; import com.uplynk.media.CaptionEvent.CaptionMode; import com.uplynk.media.CaptionEvent.CaptionRow; import com.uplynk.media.MediaPlayer; import com.uplynk.media.MediaPlayer.UplynkAssetInfo; import com.uplynk.media.MediaPlayer.UplynkID3; import com.uplynk.media.MediaPlayer.UplynkMetadata; public class MyVideoPlayerActivity extends Activity implements SurfaceHolder.Callback, MediaController.MediaPlayerControl, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnAssetBoundaryListener, MediaPlayer.OnCaptionEventListener, MediaPlayer.OnID3MetadataListener, MediaPlayer.OnUplynkMetadataListener, MediaPlayer.OnUplynkSegmentListener { private MediaPlayer _mp; private MediaController _mc; private SurfaceView _sv; private SurfaceHolder _sh; ... public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... _sv = (SurfaceView)this.findViewById(R.id.surfaceView); _sh = _sv.getHolder(); // configure Surface Holder (required for certain devices) MediaPlayer.initSurfaceHolder(_sh); _sh.addCallback(this); ... } }
Player Creation
private void playContent(final String url) { if(_mp !=null) { _mp.release(); _mp = null; } // Create a new media player _mp = new MediaPlayer(); _mp.setAudioStreamType(AudioManager.STREAM_MUSIC); _mp.setContext(this); // allow persisting bandwidth stats (optional) //_mp.setMaxBitrate(1536); // bandwidth limit in Kps (optional) // Attach Listeners _mp.setOnErrorListener(this); _mp.setOnCompletionListener(this); _mp.setOnSeekCompleteListener(this); _mp.setOnPreparedListener(this); _mp.setOnVideoSizeChangedListener(this); _mp.setOnID3MetadataListener(this); _mp.setOnUplynkMetadataListener(this); _mp.setOnCaptionEventListener(this); _mp.setOnAssetBoundaryListener(this); // Attach Caption container (optional) _mp.setCaptionsEnabled(true); _mp.setCaptionLayoutContainer((RelativeLayout)this.findViewById(R.id.ccContainer)); // Set Caption Styles (optional) CaptionStyle style = new CaptionStyle(); style.setBackgroundColor(0x3300ff00); style.setTextColor(0xffdddddd); style.setTextSize(CaptionStyle.TEXT_SIZE_SMALL); style.setEdgeType(CaptionStyle.EDGE_TYPE_DROP_SHADOW); style.setTypeface(Typeface.SANS_SERIF); _mp.setCaptionStyle(style); // Attach a MediaController (optional) _mc = new MediaController(this); _mc.setAnchorView(_sv); // Set the surface for the video output _mp.setDisplay(_sh); // must already be created _mp.setScreenOnWhilePlaying(true); try { _mp.setDataSource(url); _mp.prepareAsync(); // start asynchronous player preparation } catch (IllegalArgumentException e) { /* handle error */ } catch (IllegalStateException e) { /* handle error */ } catch (IOException e) { /* handle error */ } }
OnPrepared Handler
@Override public void onPrepared(MediaPlayer mp) { if(mp == _mp) { _mc.setMediaPlayer(this); // attach media controller (optional) //_mp.seekTo(20000); // set starting position in milliseconds if > 0 (optional) _mp.start(); // tell player to start playback } }
OnUplynkMetadata Handler
@Override public boolean onUplynkMetadata(MediaPlayer mp, UplynkMetadata metadata) { Log.d(TAG, "MediaPlayer::onUplynkMetadata called (" + metadata.toString() + ")"); return true; }
OnID3Metadata Handler (Build 63)
@Override public boolean onID3Metadata(MediaPlayer mp, UplynkID3 metadata) { Log.d(TAG,String.format("MediaPlayer::onID3Metadata: [%s] %s",metadata.getKey(),metadata.getValue())); return true; }
OnCaptionEvent Handler
@Override public boolean onCaptionEvent(MediaPlayer mp, CaptionEvent event) { Log.d(TAG, "MediaPlayer::onCaptionEvent called"); // if POP_ON, render 'rows' data if( event.mode == CaptionMode.POP_ON) { // loop through all characters of all rows to render SparseArray<CaptionRow> rows = event.rows; for(int i=0;i<rows.size();++i) { CaptionEvent.CaptionRow row = rows.valueAt(i); // Log.i(TAG,String.format("CC [%d] {%d} %s",row.getRow(),(row.getColumn()+row.getIndent()),row.getText())); Vector<CaptionEvent.CaptionCharacter> characters = row.getCharacters(); for(int x=0;x<characters.size();++x) { CaptionEvent.CaptionCharacter cc = characters.get(x); // Log.w(TAG,String.format("CC CHAR [%c] color:%d italic:%b underlined:%b ",cc.character(), cc.color(), cc.isItalic(), cc.isUnderlined())); // handle character } } } // if ROLL_UP, render single character or handle other event type else if( event.mode == CaptionMode.ROLL_UP) { if(event.eventType == CaptionEventType.TEXT) { CaptionEvent.CaptionCharacter cc = event.character; // Log.d(TAG,String.format("CC %c",cc.character())); // render individual character } else if(event.eventType == CaptionEventType.LINEBREAK) { // line break so push content up one line and start new line } else if(event.eventType == CaptionEventType.CLEAR) { // clear all content } } return true; }
OnAssetBoundary Handler
@Override public void onAssetBoundary(MediaPlayer mp, String assetID) { Log.i(TAG,"onAssetBoundaryListener: " + assetID); }
SurfaceCreated Callback (Build 61)
// As of build 61 (2014.03.20), a surfaceDestroyed(...) callback will unbind the // surface from the player to prevent memory leaks // make sure to rebind the surface when it is recreated via it's surfaceCreated(...) callback @Override public void surfaceCreated(SurfaceHolder sh) { Log.d(TAG, "surfaceCreated called"); // need to re-attach surface if(_mp != null && sh == _sh) { _mp.setDisplay(_sh); _mp.setScreenOnWhilePlaying(true); } }
Version | Description |
---|---|
v102b 2017.08.02 |
Fix to prevent possible crash related to getPlaybackBitrate() method Enhanced compatibility with Android 8 (O) preview |
v101 2017.06.07 |
Fix for Alternate Audio Switch Failure on Android 4.3 and lower |
v100 2017.05.03 |
Fix for possible missing stream metadata on Android 4.4 Prevent possible Abort during OMXCodec creation on Android 4.4 Prevent possible crash/hang if calling .stop() or .reset() while player is still initializing Fixes for Roll Up style captions Support for Roll On style captions |
v99 2016.11.30 |
Prevent possible crash if seeking while Video Decoder is reconfiguring |
v98 2016.11.04 |
Fix possible crash when selecting alternate audio tracks |
v97 2016.10.31 |
Fix for OMAP 4 Devices on Android 4.4 |
v96 2016.10.24 |
Fix for possible hang related to calling setDataSource while player is busy Throw IllegalStateException from prepare / prepareAsync instead of crash if bad state or no datasource set |
v95 2016.10.05 |
Fixes related to network error handling Fixes related to quality selection of live streams Fix possible blocking situation when calling .start() that my trigger an ANR Fixes related to reported playhead position after seeking Fixes related to Audio Only streams Fix possible NPE crash in CaptionManager related to Caption Overlay View Fix possible ANR during player stop related to hung system audio engine |
v94 2016.08.11 |
Support for Android 7 (Nougat) Fix incorrect quality switching in some cases on Live Streams Fix possible deadlock situation when calling .start() Reduced overall library bundle size |
v93 2016.07.29 |
Fix possible crash related to some invalid or expired content urls |
v92 2016.07.26 |
Fix for crash related to ads/slate with no audio on some devices |
v91 2016.07.21 |
Fix for possible crash related to some audio track configurations Tested on Android N Preview 5 |
v90 2016.07.15 |
Android N Preview 4 * Initial Support (may not be compatible with Preview 5 or Final release) -API Addition: MediaPlayer.getPlaybackBitrate():int returns the current variant's reported bitrate in bps -Enhancements to general performance including stream start time reduction for Android 4.4+ -Add Support for Dolby Digital output for Android 5.0+ on supported devices |
v89b 2016.04.14 (Hotfix) |
Fix issue related to setting content start position |
v89 2016.03.02 |
Prevent possible crashes related to using HTTPS content URLs Prevent possible stream failure after a short connection loss/reconnect Add Support for x86 Devices running Android 6.0 |
v88b 2016.01.18 |
Fix for possible long starting delay when playing content less than 4 seconds long |
v87 2016.01.11 |
API Addition: MediaPlayer(Map) to include custom HTTP headers on requests * All headers names require "X-" prefix |
v86 2015.12.11 |
Fix hasCaptions flag not being set on Android 5.0 and higher Redraw captions when caption style is changed Increase caption display duration Prevent possible crash during a bad start related to audio system Fix possible crash with quality change during a seek Fixes related to time tracking when alternate audio track is enabled API Addition: utility methods for calculating Aspect Ratio constrained display surface bounds MediaPlayer.getDisplayRectForMaxDimensions(int maxWidth, int maxHeight): Rect MediaPlayer::getDisplayRectForMaxDimensionsAndVideoDimensions(int maxWidth, int maxHeight, int videoWidth, int videoHeight): Rect |
v85d 2015.10.26 |
Discontinuity handling fix for Android 4.4 and lower |
v85c 2015.10.07 |
Memory Leak and Possible Deadlock fixes |
v85b |
Fix crash related to ID3 Tags with a Description Field |
v85 2015.10.05 |
Support for Android 6 (Marshmallow) MediaCodec implementation for use on Lollipop and higher Video: Skip Non Key frames when restoring video surface to prevent failure on MediaTek devices and corruption on other devices Enable Hardware Rendering on Lollipop with Broadcom chipset for FireTV Stick with Lollipop Discontinuity Tracking enhancements |
v84c 2015.07.22 |
Prevent video hesitation during ad break transitions (HW Rendering) Fixes for some devices with Qualcomm chipset decoder that incorrectly adjust frame timestamps Signal an Error Event and stop in the advent of a timing failure of video stream Prevent possible hang when changing directly from one display surface to another |
v83 2015.06.29 |
Fix possible crash when setting start position to within the first segment (~ 4 seconds) Fix possible hang if stop() called while buffering Fix possible quality degradation or failure with Hardware rendering after a resolution change on some devices |
v82 2016.06.12 |
Fix possible loss of video when surface is removed and then reassigned to the player (Lollipop) Prevent invalid decoder state if player is started before a surface is assigned (Lollipop) Prevent decoder hang if buffer allocation fails during initialization Fix for possible failure when moving from one display surface directly to a different surface (Lollipop) Fix video flickering on Verizon Ellipsis 7 Tablet Fix issue that could trigger a high quality stream on a slow connection Allow quicker failure when device appears to be offline, instead of making multiple retries |
v81 2016.06.12 |
Revised Input Buffer Allocation for Qualcomm chipsets to fix Snapdragon 400 chipset support |
v80 2015.03.16 |
Fix for possible crash if content could not be loaded (invalid source / no internet connection) Fix for crash related to TXXX ID3 tag parsing that include a description field + a value field Fix to prevent possible Metadata Stream out of sync issue |
v79 2015.03.05 |
Playback and Seek Stability Fixes for Android 5.0 Fix for incorrect onCompletion event signal while seeking Support for Android 5.1 |
v78 2015.02.02 |
Fix for crash related to releasing the player while asset info fetch in progress Fix possible hang if player was seeked and then reused with a different source Fix possible hang when content could not be loaded (invalid source / no internet connection) Fix crash on Android 2.3 related to audio engine not being released on previous playback Fix ID3 Parsing Error related to PRIV tags |
v77 2015.01.23 |
Fix invalid state if seekTo() called while paused Fix invalid state if player is stopped while paused and then given a new source |
v76 2015.01.21 |
Fix ID3 Parsing Error for long tag values Fix hang when calling stop() while paused |
v75 2015.01.15 |
Add Exynos Chipset Support on Android 5.0 / Lollipop (Nexus 10) |
v74 2015.01.12 |
Support for Android 5 / Lollipop Support for Hardware Rendering on Lollipop on some chipsets * requires manually adjusting Surface Size to maintain proper aspect ratio |
v73 2014.11.21 |
Fix for Closed Captions sometimes not being rendered after a seek to an earlier timecode |
v72 2014.11.19 |
API Addition: MediaPlayer.setSurface(Surface) can be used in place of setDisplay(SurfaceHolder) for using a TextureView for 4.x Fixes to prevent crash when calling stop() or release() while player is still preparing |
v71 2014.11.18 |
Fix for Closed Caption timing issue |
v70 2014.10.16 |
Allow recovery of stream quality level after a forced downgrade due to high cpu load. Quality will recover after setting a new source or automatically after a short period of time on some devices. |
v69 2014.10.10 |
Revised Decoder Handling for Broadcom AVC Decoder (Amazon FireTV Stick) |
v68 2014.10.08 |
Added support for Broadcom AVC Decoder (Amazon FireTV Stick) |
v67 2014.10.01 |
Fix for possible crash during stream shutdown Added x86 support for Android 4.4.x (Galaxy Tab 3 10.1 w/ latest firmware) |
v66 2014.09.24 |
Fix for Segment Downloader signaling onCompletion() instead of onError() after a download failure |
v65 2014.09.23 |
Include armeabi-v7a architecture variant (can be excluded if armeabi is included) Logging: All library tags are now prefixed with ?upLynk? or ?UL-? Fix for possible crash related to setting initial playback position Fix for possible crash related to quality selection on poor connections Report error and shutdown if there is an audio or video decoder error instead of playing without the bad stream |
v64 2014.08.21 |
New Feature: Alternate Audio Track Support (VOD) API Addition: MediaPlayer.getAudioTrackOptions():Vector<UplynkTrackInfo> MediaPlayer.selectAudioTrack(int index) MediaPlayer.OnUplynkSegmentListener Interface MediaPlayer.setOnUplynkSegmentListener(OnUplynkSegmentListener listener) Fix playback failure on Audio Only streams Fix seek failure if the playhead was so near the content end that one but not all of the playback threads had exited Fix for some Android 2.3 Devices with Secure Decoders not able to dynamically change quality levels Fix NPE related to the caption container being destroyed while in use |