Migrating to ExoPlayer 2 Framework

In this topic, you will learn how to use the ExoPlayer 2 framework with the Brightcove Native Player SDK for Android..

Overview

Google's ExoPlayer is an open source, application-level media player for Android. Brightcove leverages the ExoPlayer to take advantage of the benefits it provides. For more information about the benefits of upgrading to the ExoPlayer, see the Brightcove Native SDK with ExoPlayer 2 blog post.

Learn how to migrate for the following project types:

Refer to the ExoPlayer sample applications for additional guidance on integrating the ExoPlayer 2 framework into your project.

New project

Follow these steps to add ExoPlayer 2 to a new Android project:

  1. In your build.gradle file, add the following dependency:
    dependencies {
      implementation "com.brightcove.player:exoplayer2:${anpVersion}"
    }
  2. Setting the transitive option to true tells gradle to automatically include other dependencies such as the offline-playback plugin. If you are using a gradle version less than 5, the transitive dependencies are off by default. So, you will need to add the following statement:
    dependencies {
      implementation "com.brightcove.player:exoplayer2:${anpVersion}" {transitive = true}
    }
  3. If you are using an environment variable for the SDK version, then open the gradle.properties file, and set the current version value for the Native SDK for Android. It should look similar to this:
    anpVersion=6.5.0

Existing ExoPlayer 1 project

Follow these steps to update an existing ExoPlayer 1 project to use the ExoPlayer 2 framework:

  1. In your constants.gradle file, update the Android Build Tools version:
    buildToolsVersion "28.0.2"
    
  2. In your build.gradle file, update Android support libraries:
    implementation 'com.android.support:appcompat-v7:${APPCOMPAT_V7_VERSION}'
    implementation 'com.android.support:support-v4:${SUPPORT_V4_VERSION}'
    implementation 'com.android.support:recyclerview-v7:${SUPPORT_V4_VERSION}'
    implementation 'com.android.support:support-vector-drawable:${SUPPORT_V4_VERSION}'
    

    The current values for the constants can be found in the constants.gradle file.

  3. In your build.gradle file, add the Google Maven Repository:
    maven {
      url 'https://maven.google.com'
    }
    
  4. If your project uses advertising with Google IMA, update Google Play Services Ads:
    implementation 'com.google.android.gms:play-services-ads:'+PLAY_SERVICES_VERSION
    
  5. In your build.gradle file, where you previously imported the Brightcove ExoPlayer library as a dependency like this:
    dependencies {
      implementation "com.brightcove.player:exoplayer:${anpVersion}"
    }
    

    Change the name of the dependency:

    dependencies {
      implementation "com.brightcove.player:exoplayer2:${anpVersion}"
    }
    

    The current value for the Brightcove SDK version (anpVersion) can be found in the gradle.properties file.

  6. Setting the transitive option to true tells gradle to automatically include other dependencies such as the offline-playback plugin. If you are using a gradle version less than 5, the transitive dependencies are off by default. So, you will need to add the following:
    dependencies {
    	implementation "com.brightcove.player:exoplayer2:${anpVersion}" {transitive = true}
    }
  7. If you are using an environment variable for the SDK version, then open the gradle.properties file, and set the current version value for the Native SDK for Android. It should look similar to this:
    anpVersion=6.5.0

    There should be no additional coding required to integrate ExoPlayer 2 into your project.

Existing MediaPlayer project

Follow these steps to update an existing MediaPlayer project to use the ExoPlayer 2 framework:

  1. In your build.gradle file, add the following dependency:
    dependencies {
      implementation "com.brightcove.player:exoplayer2:${anpVersion}"
    }
  2. Setting the transitive option to true tells gradle to automatically include other dependencies such as the offline-playback plugin. If you are using a gradle version less than 5, the transitive dependencies are off by default. So, you will need to add the following:
    dependencies {
      implementation "com.brightcove.player:exoplayer2:${anpVersion}" {transitive = true}
    }
  3. If you are using an environment variable for the SDK version, then open the gradle.properties file, and set the current version value for the Native SDK for Android. It should look similar to this:
    anpVersion=6.5.0
  4. In your app, use the BrightcoveExoPlayerVideoView instead of the BrightcoveVideoView, which uses the Android Media Player.

Breaking changes

The following changes to the Brightcove Native SDK for Android are breaking changes with the ExoPlayer 2. Use of the ExoPlayer 1 has been deprecated with the Brightcove Native SDK.

ExoPlayerVideoDisplayComponent internal listeners

The ExoPlayerVideoDisplayComponent class allows you to set listeners to get the status of the ExoPlayer components. Below is a list of some of the listeners:

Set the listener Receive status info about
setDebugListener InfoListener
setCaptionListener CaptionListener
setMetadataListener MetadataListener
setInternalErrorListener InternalErrorListener

Below are recommendations for using the ExoPlayer 2.

InfoListener

For the InfoListener interface, the following changes were made:

  • The onAvailableRangeChanged method was removed
  • The onLoadStarted method has an additional length parameter

Example: ExoPlayerVideoDisplayComponent using ExoPlayer 2

public interface InfoListener {
void onVideoFormatEnabled(Format format, int trigger, long mediaTimeMs);
void onAudioFormatEnabled(Format format, int trigger, long mediaTimeMs);
void onDroppedFrames(int count, long elapsed);
void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate);
void onLoadStarted(int sourceId, int type, int trigger, Format format,
				long mediaStartTimeMs, long mediaEndTimeMs);
void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format,
				long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs);
void onDecoderInitialized(String decoderName, long initializedTimestampMs,
				long initializationDurationMs);
}

CaptionListener

The CaptionListener interface is unchanged.

Example: ExoPlayerVideoDisplayComponent using ExoPlayer v2

public interface CaptionListener {
void onCues(List<Cue> cues);
}

MetadataListener

The MetadataListener interface was introduced with ExoPlayer v2. The previous use of the Id3MetadataListener is now deprecated.

Example: ExoPlayerVideoDisplayComponent using ExoPlayer v2

public interface MetadataListener {
void onMetadata(Metadata metadata);
}

With the new MetadataListener you will receive a Metadadata object in the onMetadata callback. With the deprecated Id3MetadataListener, you received a list of Id3Frame objects. With the new listener, you can still get a list of Id3Frame objects as shown below:

exoPlayerVideoDisplayComponent.setMetadataListener(new ExoPlayerVideoDisplayComponent.MetadataListener() {
@Override
public void onMetadata(Metadata metadata) {
 for(int i = 0; i < metadata.length(); i++) {
		 Metadata.Entry entry = metadata.get(i);
		 if (entry instanceof Id3Frame) {
				 Id3Frame id3Frame = (Id3Frame) entry;
		 }
 }
}
});

InternalErrorListener

The InternalErrorListener interface has many changes. Please check the code below for comparison:

ExoPlayerVideoDisplayComponent using ExoPlayer v2

public interface InternalErrorListener {
void onPlayerError(Exception e);
void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs);
void onLoadError(int sourceId, IOException e);
void onDrmSessionManagerError(Exception e);
}

ExoPlayerVideoDisplayComponent using ExoPlayer v1 (deprecated)

public interface InternalErrorListener {
void onRendererInitializationError(Exception e);
void onAudioTrackInitializationError(AudioTrack.InitializationException e);
void onAudioTrackWriteError(AudioTrack.WriteException e);
void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs);
void onDecoderInitializationError(MediaCodecTrackRenderer.DecoderInitializationException e);
void onCryptoError(MediaCodec.CryptoException e);
void onLoadError(int sourceId, IOException e);
void onDrmSessionManagerError(Exception e);
}

When using ExoPlayer 2, the type of exception you get in onPlayerError(Exception e) is com.google.android.exoplayer2.ExoPlaybackException, but this may change in the future.

By using com.google.android.exoplayer2.ExoPlaybackException, you can get the following exception types:

  • ExoPlaybackException.TYPE_SOURCE
  • ExoPlaybackException.TYPE_RENDERER
  • ExoPlaybackException.TYPE_UNEXPECTED

You can also retrieve the cause of the error by getting the Throwable object with ExoPlaybackException.getSourceException().

Offline playback support

If your project is using the MediaDownloadable.setConfigurationBundle(Bundle) method to specify the download preferences such as video bitrate, then please update your code as follows:

Old format (deprecated)

com.google.android.exoplayer.MediaFormat

New format

com.brightcove.player.model.MediaFormat

Legacy Media API classes

The deprecated legacy Media API classes, in the com.brightcove.player.media package, were removed from the Brightcove Native SDK for Android.

If you were using the Media classes, you need to migrate and start using the com.brightcove.player.edge.Catalog class.

The following classes were moved from com.brightcove.player.media to com.brightcove.player.model:

  • DeliveryType.java
  • CaptionType.java
  • ErrorFields.java
  • VideoFields.java

Additional Resources

For more information about using the ExoPlayer 2 framework, see the following documents: