ExoPlayer version 2.16.x to version 2.18.x
1. Require
Some general requirement is here
Prerequisite
- Add a dependency in the build.gradle file of your app module. The following will add a dependency to the full library:
java
implementation 'com.google.android.exoplayer:exoplayer:2.16.0'
// FIXME: If you don't use feature license encrypt, please comment line below
// implementation 'com.sigma.packer:2.16.x:1.0.3'
2. Integrate MediaDrmCallback
Please see at MediaCallback
3. Create DrmSessionManagerProvider
java
import static com.google.android.exoplayer2.drm.DefaultDrmSessionManager.MODE_PLAYBACK;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.DrmSessionManagerProvider;
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.Util;
import com.google.common.primitives.Ints;
// FIXME: If you use license encrypt feature please uncomment line below
// import com.sigma.packer.SigmaMediaDrm;
import java.util.Map;
public class SmDrmSessionManagerProvider implements DrmSessionManagerProvider {
private final Object lock;
@GuardedBy("lock")
private MediaItem.DrmConfiguration drmConfiguration;
@GuardedBy("lock")
private DrmSessionManager manager;
@Nullable
private DataSource.Factory drmHttpDataSourceFactory;
@Nullable private String userAgent;
public SmDrmSessionManagerProvider() {
lock = new Object();
}
/**
* Sets the {@link DataSource.Factory} which is used to create {@link HttpMediaDrmCallback}
* instances. If {@code null} is passed a {@link DefaultHttpDataSource.Factory} is used.
*
* @param drmDataSourceFactory The data source factory or {@code null} to use {@link
* DefaultHttpDataSource.Factory}.
*/
public void setDrmHttpDataSourceFactory(@Nullable DataSource.Factory drmDataSourceFactory) {
this.drmHttpDataSourceFactory = drmDataSourceFactory;
}
/**
* @deprecated Pass a custom {@link DataSource.Factory} to {@link
* #setDrmHttpDataSourceFactory(DataSource.Factory)} which sets the desired user agent on
* outgoing requests.
*/
@Deprecated
public void setDrmUserAgent(@Nullable String userAgent) {
this.userAgent = userAgent;
}
@Override
public DrmSessionManager get(MediaItem mediaItem) {
checkNotNull(mediaItem.localConfiguration);
@Nullable
MediaItem.DrmConfiguration drmConfiguration = mediaItem.localConfiguration.drmConfiguration;
if (drmConfiguration == null || Util.SDK_INT < 18) {
return DrmSessionManager.DRM_UNSUPPORTED;
}
synchronized (lock) {
if (!Util.areEqual(drmConfiguration, this.drmConfiguration)) {
this.drmConfiguration = drmConfiguration;
this.manager = createManager(drmConfiguration);
}
return checkNotNull(this.manager);
}
}
@RequiresApi(18)
private DrmSessionManager createManager(MediaItem.DrmConfiguration drmConfiguration) {
DataSource.Factory dataSourceFactory =
drmHttpDataSourceFactory != null
? drmHttpDataSourceFactory
: new DefaultHttpDataSource.Factory().setUserAgent(userAgent);
WidevineMediaDrmCallback httpDrmCallback =
new WidevineMediaDrmCallback(
drmConfiguration.licenseUri == null ? null : drmConfiguration.licenseUri.toString(),
drmConfiguration.forceDefaultLicenseUri,
(HttpDataSource.Factory)dataSourceFactory);
for (Map.Entry<String, String> entry : drmConfiguration.licenseRequestHeaders.entrySet()) {
httpDrmCallback.setKeyRequestProperty(entry.getKey(), entry.getValue());
}
DefaultDrmSessionManager drmSessionManager =
new DefaultDrmSessionManager.Builder()
// FIXME: If you use license encrypt feature please uncomment line below
// .setUuidAndExoMediaDrmProvider(drmSchemeUuid, SigmaMediaDrm.DEFAULT_PROVIDER)
.setUuidAndExoMediaDrmProvider(
drmConfiguration.scheme, FrameworkMediaDrm.DEFAULT_PROVIDER)
.setMultiSession(drmConfiguration.multiSession)
.setPlayClearSamplesWithoutKeys(drmConfiguration.playClearContentWithoutKey)
.setUseDrmSessionsForClearContent(
Ints.toArray(drmConfiguration.forcedSessionTrackTypes))
.build(httpDrmCallback);
drmSessionManager.setMode(MODE_PLAYBACK, drmConfiguration.getKeySetId());
return drmSessionManager;
}
}
4. Create PlayerActivity using WidevineMediaDrmCallback
If you have experience with Exoplayer, then please avoid this chapter.
4.1. Create Media Item
java
private static List<MediaItem> createMediaItems(String mediaUrl) {
List<MediaItem> mediaItems = new ArrayList<>();
mediaItems.add(createMediaItem(mediaUrl));
return mediaItems;
}
private static MediaItem createMediaItem(String mediaUrl) {
MediaItem.Builder mediaItem = new MediaItem.Builder();
mediaItem.setUri(Uri.parse(mediaUrl));
mediaItem.setDrmConfiguration(
new MediaItem.DrmConfiguration.Builder(Util.getDrmUuid("widevine"))
.setMultiSession(true)
.setLicenseUri(LICENSE_URL)
.build()
);
return mediaItem.build();
}
4.2. Build Factory
java
private MediaSource.Factory createMediaSourceFactory() {
SmDrmSessionManagerProvider drmSessionManagerProvider =
new SmDrmSessionManagerProvider();
drmSessionManagerProvider.setDrmHttpDataSourceFactory(
buildHttpDataSourceFactory());
return new DefaultMediaSourceFactory(/* context= */ this)
.setDrmSessionManagerProvider(drmSessionManagerProvider);
}
public HttpDataSource.Factory buildHttpDataSourceFactory() {
return new DefaultHttpDataSourceFactory(userAgent);
}
private DataSource.Factory buildDataSourceFactory() {
DefaultDataSourceFactory upstreamFactory =
new DefaultDataSourceFactory(this, buildHttpDataSourceFactory());
return buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache());
}
private RenderersFactory buildRenderersFactory(boolean preferExtensionDecoders) {
int extensionRendererMode =
useExtensionRenderers()
? (preferExtensionRenderer
? DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER
: DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON)
: DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF;
return new DefaultRenderersFactory(/* context= */ this)
.setExtensionRendererMode(extensionRendererMode);
}
3.5. Init Player with MediaSource
java
protected boolean initializePlayer() {
if (player == null) {
mediaItems = createMediaItems(MEDIA_URL);
if (mediaItems.isEmpty()) {
return false;
}
ExoPlayer.Builder playerBuilder =
new ExoPlayer.Builder(/* context= */ this)
.setMediaSourceFactory(createMediaSourceFactory());
playerBuilder.setRenderersFactory(buildRenderersFactory(true));
player = playerBuilder.build();
player.setTrackSelectionParameters(new TrackSelectionParameters.Builder(/* context= */ this).build());
player.setAudioAttributes(AudioAttributes.DEFAULT, /* handleAudioFocus= */ true);
player.setPlayWhenReady(true);
playerView.setPlayer(player);
}
player.setMediaItems(mediaItems, true);
player.prepare();
return true;
}