simplify PlayerActivity towards using the media item only
PiperOrigin-RevId: 305300409
This commit is contained in:
parent
c84ac809e4
commit
4e2a0f6032
@ -62,6 +62,7 @@ import com.google.android.exoplayer2.ui.PlayerView;
|
|||||||
import com.google.android.exoplayer2.ui.spherical.SphericalGLSurfaceView;
|
import com.google.android.exoplayer2.ui.spherical.SphericalGLSurfaceView;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
||||||
import com.google.android.exoplayer2.util.EventLogger;
|
import com.google.android.exoplayer2.util.EventLogger;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
@ -71,9 +72,7 @@ import java.net.CookieManager;
|
|||||||
import java.net.CookiePolicy;
|
import java.net.CookiePolicy;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/** An activity that plays media using {@link SimpleExoPlayer}. */
|
/** An activity that plays media using {@link SimpleExoPlayer}. */
|
||||||
public class PlayerActivity extends AppCompatActivity
|
public class PlayerActivity extends AppCompatActivity
|
||||||
@ -410,28 +409,29 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
? ((Sample.PlaylistSample) intentAsSample).children
|
? ((Sample.PlaylistSample) intentAsSample).children
|
||||||
: new UriSample[] {(UriSample) intentAsSample};
|
: new UriSample[] {(UriSample) intentAsSample};
|
||||||
|
|
||||||
boolean seenAdsTagUri = false;
|
|
||||||
List<MediaSource> mediaSources = new ArrayList<>();
|
List<MediaSource> mediaSources = new ArrayList<>();
|
||||||
|
Uri adTagUri = null;
|
||||||
for (UriSample sample : samples) {
|
for (UriSample sample : samples) {
|
||||||
seenAdsTagUri |= sample.adTagUri != null;
|
MediaItem mediaItem = sample.toMediaItem();
|
||||||
if (!Util.checkCleartextTrafficPermitted(sample.uri)) {
|
Assertions.checkNotNull(mediaItem.playbackProperties);
|
||||||
|
if (!Util.checkCleartextTrafficPermitted(mediaItem)) {
|
||||||
showToast(R.string.error_cleartext_not_permitted);
|
showToast(R.string.error_cleartext_not_permitted);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
if (Util.maybeRequestReadExternalStoragePermission(/* activity= */ this, sample.uri)
|
if (Util.maybeRequestReadExternalStoragePermission(/* activity= */ this, mediaItem)) {
|
||||||
|| (sample.subtitleInfo != null
|
|
||||||
&& Util.maybeRequestReadExternalStoragePermission(
|
|
||||||
/* activity= */ this, sample.subtitleInfo.uri))) {
|
|
||||||
// The player will be reinitialized if the permission is granted.
|
// The player will be reinitialized if the permission is granted.
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
MediaSource mediaSource = createLeafMediaSource(sample);
|
MediaSource mediaSource = createLeafMediaSource(mediaItem);
|
||||||
if (mediaSource != null) {
|
if (mediaSource != null) {
|
||||||
|
adTagUri = sample.adTagUri;
|
||||||
mediaSources.add(mediaSource);
|
mediaSources.add(mediaSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (seenAdsTagUri && mediaSources.size() == 1) {
|
|
||||||
Uri adTagUri = samples[0].adTagUri;
|
if (adTagUri == null) {
|
||||||
|
releaseAdsLoader();
|
||||||
|
} else if (mediaSources.size() == 1) {
|
||||||
if (!adTagUri.equals(loadedAdTagUri)) {
|
if (!adTagUri.equals(loadedAdTagUri)) {
|
||||||
releaseAdsLoader();
|
releaseAdsLoader();
|
||||||
loadedAdTagUri = adTagUri;
|
loadedAdTagUri = adTagUri;
|
||||||
@ -442,72 +442,42 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
} else {
|
} else {
|
||||||
showToast(R.string.ima_not_loaded);
|
showToast(R.string.ima_not_loaded);
|
||||||
}
|
}
|
||||||
} else if (seenAdsTagUri && mediaSources.size() > 1) {
|
} else if (mediaSources.size() > 1) {
|
||||||
showToast(R.string.unsupported_ads_in_concatenation);
|
showToast(R.string.unsupported_ads_in_concatenation);
|
||||||
releaseAdsLoader();
|
releaseAdsLoader();
|
||||||
} else {
|
|
||||||
releaseAdsLoader();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mediaSources;
|
return mediaSources;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private MediaSource createLeafMediaSource(UriSample parameters) {
|
private MediaSource createLeafMediaSource(MediaItem mediaItem) {
|
||||||
MediaItem.Builder builder = new MediaItem.Builder().setSourceUri(parameters.uri);
|
Assertions.checkNotNull(mediaItem.playbackProperties);
|
||||||
builder.setMimeType(Sample.inferAdaptiveStreamMimeType(parameters.uri, parameters.extension));
|
|
||||||
HttpDataSource.Factory drmDataSourceFactory = null;
|
HttpDataSource.Factory drmDataSourceFactory = null;
|
||||||
if (parameters.drmInfo != null) {
|
if (mediaItem.playbackProperties.drmConfiguration != null) {
|
||||||
if (Util.SDK_INT < 18) {
|
if (Util.SDK_INT < 18) {
|
||||||
showToast(R.string.error_drm_unsupported_before_api_18);
|
showToast(R.string.error_drm_unsupported_before_api_18);
|
||||||
finish();
|
finish();
|
||||||
return null;
|
return null;
|
||||||
} else if (!MediaDrm.isCryptoSchemeSupported(parameters.drmInfo.drmScheme)) {
|
} else if (!MediaDrm.isCryptoSchemeSupported(
|
||||||
|
mediaItem.playbackProperties.drmConfiguration.uuid)) {
|
||||||
showToast(R.string.error_drm_unsupported_scheme);
|
showToast(R.string.error_drm_unsupported_scheme);
|
||||||
finish();
|
finish();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
builder
|
|
||||||
.setDrmLicenseUri(parameters.drmInfo.drmLicenseUrl)
|
|
||||||
.setDrmLicenseRequestHeaders(
|
|
||||||
createLicenseHeaders(parameters.drmInfo.drmKeyRequestProperties))
|
|
||||||
.setDrmUuid(parameters.drmInfo.drmScheme)
|
|
||||||
.setDrmMultiSession(parameters.drmInfo.drmMultiSession)
|
|
||||||
.setDrmSessionForClearTypes(Util.toList(parameters.drmInfo.drmSessionForClearTypes));
|
|
||||||
drmDataSourceFactory = ((DemoApplication) getApplication()).buildHttpDataSourceFactory();
|
drmDataSourceFactory = ((DemoApplication) getApplication()).buildHttpDataSourceFactory();
|
||||||
}
|
}
|
||||||
if (parameters.subtitleInfo != null) {
|
|
||||||
builder.setSubtitles(
|
|
||||||
Collections.singletonList(
|
|
||||||
new MediaItem.Subtitle(
|
|
||||||
parameters.subtitleInfo.uri,
|
|
||||||
parameters.subtitleInfo.mimeType,
|
|
||||||
parameters.subtitleInfo.language,
|
|
||||||
C.SELECTION_FLAG_DEFAULT)));
|
|
||||||
}
|
|
||||||
|
|
||||||
DownloadRequest downloadRequest =
|
DownloadRequest downloadRequest =
|
||||||
((DemoApplication) getApplication())
|
((DemoApplication) getApplication())
|
||||||
.getDownloadTracker()
|
.getDownloadTracker()
|
||||||
.getDownloadRequest(parameters.uri);
|
.getDownloadRequest(mediaItem.playbackProperties.sourceUri);
|
||||||
if (downloadRequest != null) {
|
if (downloadRequest != null) {
|
||||||
return DownloadHelper.createMediaSource(downloadRequest, dataSourceFactory);
|
return DownloadHelper.createMediaSource(downloadRequest, dataSourceFactory);
|
||||||
}
|
}
|
||||||
return mediaSourceFactory
|
return mediaSourceFactory
|
||||||
.setDrmHttpDataSourceFactory(drmDataSourceFactory)
|
.setDrmHttpDataSourceFactory(drmDataSourceFactory)
|
||||||
.createMediaSource(builder.build());
|
.createMediaSource(mediaItem);
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Map<String, String> createLicenseHeaders(@Nullable String[] drmKeyRequestProperties) {
|
|
||||||
if (drmKeyRequestProperties == null || drmKeyRequestProperties.length == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Map<String, String> headers = new HashMap<>();
|
|
||||||
for (int i = 0; i < drmKeyRequestProperties.length; i += 2) {
|
|
||||||
headers.put(drmKeyRequestProperties[i], drmKeyRequestProperties[i + 1]);
|
|
||||||
}
|
|
||||||
return headers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releasePlayer() {
|
private void releasePlayer() {
|
||||||
|
@ -34,11 +34,15 @@ import android.content.Intent;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/* package */ abstract class Sample {
|
/* package */ abstract class Sample {
|
||||||
@ -140,6 +144,35 @@ import java.util.UUID;
|
|||||||
subtitleInfo.addToIntent(intent, extrasKeySuffix);
|
subtitleInfo.addToIntent(intent, extrasKeySuffix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MediaItem toMediaItem() {
|
||||||
|
MediaItem.Builder builder = new MediaItem.Builder().setSourceUri(uri);
|
||||||
|
builder.setMimeType(inferAdaptiveStreamMimeType(uri, extension));
|
||||||
|
if (drmInfo != null) {
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
if (drmInfo.drmKeyRequestProperties != null) {
|
||||||
|
for (int i = 0; i < drmInfo.drmKeyRequestProperties.length; i += 2) {
|
||||||
|
headers.put(drmInfo.drmKeyRequestProperties[i], drmInfo.drmKeyRequestProperties[i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder
|
||||||
|
.setDrmLicenseUri(drmInfo.drmLicenseUrl)
|
||||||
|
.setDrmLicenseRequestHeaders(headers)
|
||||||
|
.setDrmUuid(drmInfo.drmScheme)
|
||||||
|
.setDrmMultiSession(drmInfo.drmMultiSession)
|
||||||
|
.setDrmSessionForClearTypes(Util.toList(drmInfo.drmSessionForClearTypes));
|
||||||
|
}
|
||||||
|
if (subtitleInfo != null) {
|
||||||
|
builder.setSubtitles(
|
||||||
|
Collections.singletonList(
|
||||||
|
new MediaItem.Subtitle(
|
||||||
|
subtitleInfo.uri,
|
||||||
|
subtitleInfo.mimeType,
|
||||||
|
subtitleInfo.language,
|
||||||
|
C.SELECTION_FLAG_DEFAULT)));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class PlaylistSample extends Sample {
|
public static final class PlaylistSample extends Sample {
|
||||||
|
@ -314,7 +314,7 @@ public final class MediaItem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the optional tag for custom attributes. The tag for the media source which will be
|
* Sets the optional tag for custom attributes. The tag for the media source which will be
|
||||||
* published in the {@link com.google.android.exoplayer2.Timeline} of the source as {@link
|
* published in the {@code com.google.android.exoplayer2.Timeline} of the source as {@code
|
||||||
* com.google.android.exoplayer2.Timeline.Window#tag}.
|
* com.google.android.exoplayer2.Timeline.Window#tag}.
|
||||||
*
|
*
|
||||||
* <p>If a {@link PlaybackProperties#sourceUri} is set, the tag is used to create a {@link
|
* <p>If a {@link PlaybackProperties#sourceUri} is set, the tag is used to create a {@link
|
||||||
@ -466,7 +466,7 @@ public final class MediaItem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional tag for custom attributes. The tag for the media source which will be published in
|
* Optional tag for custom attributes. The tag for the media source which will be published in
|
||||||
* the {@link com.google.android.exoplayer2.Timeline} of the source as {@link
|
* the {@code com.google.android.exoplayer2.Timeline} of the source as {@code
|
||||||
* com.google.android.exoplayer2.Timeline.Window#tag}.
|
* com.google.android.exoplayer2.Timeline.Window#tag}.
|
||||||
*/
|
*/
|
||||||
@Nullable public final Object tag;
|
@Nullable public final Object tag;
|
@ -50,6 +50,7 @@ import androidx.annotation.RequiresApi;
|
|||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -185,36 +186,67 @@ public final class Util {
|
|||||||
}
|
}
|
||||||
for (Uri uri : uris) {
|
for (Uri uri : uris) {
|
||||||
if (isLocalFileUri(uri)) {
|
if (isLocalFileUri(uri)) {
|
||||||
if (activity.checkSelfPermission(permission.READ_EXTERNAL_STORAGE)
|
return requestExternalStoragePermission(activity);
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
|
||||||
activity.requestPermissions(new String[] {permission.READ_EXTERNAL_STORAGE}, 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether it may be possible to load the given URIs based on the network security
|
* Checks whether it's necessary to request the {@link permission#READ_EXTERNAL_STORAGE}
|
||||||
* policy's cleartext traffic permissions.
|
* permission for the specified {@link MediaItem media items}, requesting the permission if
|
||||||
|
* necessary.
|
||||||
*
|
*
|
||||||
* @param uris A list of URIs that will be loaded.
|
* @param activity The host activity for checking and requesting the permission.
|
||||||
* @return Whether it may be possible to load the given URIs.
|
* @param mediaItems {@link MediaItem Media items}s that may require {@link
|
||||||
|
* permission#READ_EXTERNAL_STORAGE} to read.
|
||||||
|
* @return Whether a permission request was made.
|
||||||
*/
|
*/
|
||||||
public static boolean checkCleartextTrafficPermitted(Uri... uris) {
|
public static boolean maybeRequestReadExternalStoragePermission(
|
||||||
|
Activity activity, MediaItem... mediaItems) {
|
||||||
|
if (Util.SDK_INT < 23) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (MediaItem mediaItem : mediaItems) {
|
||||||
|
if (mediaItem.playbackProperties == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isLocalFileUri(mediaItem.playbackProperties.sourceUri)) {
|
||||||
|
return requestExternalStoragePermission(activity);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mediaItem.playbackProperties.subtitles.size(); i++) {
|
||||||
|
if (isLocalFileUri(mediaItem.playbackProperties.subtitles.get(i).uri)) {
|
||||||
|
return requestExternalStoragePermission(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether it may be possible to load the URIs of the given media items based on the
|
||||||
|
* network security policy's cleartext traffic permissions.
|
||||||
|
*
|
||||||
|
* @param mediaItems A list of {@link MediaItem media items}.
|
||||||
|
* @return Whether it may be possible to load the URIs of the given media items.
|
||||||
|
*/
|
||||||
|
public static boolean checkCleartextTrafficPermitted(MediaItem... mediaItems) {
|
||||||
if (Util.SDK_INT < 24) {
|
if (Util.SDK_INT < 24) {
|
||||||
// We assume cleartext traffic is permitted.
|
// We assume cleartext traffic is permitted.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (Uri uri : uris) {
|
for (MediaItem mediaItem : mediaItems) {
|
||||||
if ("http".equals(uri.getScheme())
|
if (mediaItem.playbackProperties == null) {
|
||||||
&& !NetworkSecurityPolicy.getInstance()
|
continue;
|
||||||
.isCleartextTrafficPermitted(Assertions.checkNotNull(uri.getHost()))) {
|
}
|
||||||
// The security policy prevents cleartext traffic.
|
if (isTrafficRestricted(mediaItem.playbackProperties.sourceUri)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < mediaItem.playbackProperties.subtitles.size(); i++) {
|
||||||
|
if (isTrafficRestricted(mediaItem.playbackProperties.subtitles.get(i).uri)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2185,6 +2217,24 @@ public final class Util {
|
|||||||
return replacedLanguages;
|
return replacedLanguages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
|
private static boolean requestExternalStoragePermission(Activity activity) {
|
||||||
|
if (activity.checkSelfPermission(permission.READ_EXTERNAL_STORAGE)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
activity.requestPermissions(
|
||||||
|
new String[] {permission.READ_EXTERNAL_STORAGE}, /* requestCode= */ 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||||
|
private static boolean isTrafficRestricted(Uri uri) {
|
||||||
|
return "http".equals(uri.getScheme())
|
||||||
|
&& !NetworkSecurityPolicy.getInstance()
|
||||||
|
.isCleartextTrafficPermitted(Assertions.checkNotNull(uri.getHost()));
|
||||||
|
}
|
||||||
|
|
||||||
private static String maybeReplaceGrandfatheredLanguageTags(String languageTag) {
|
private static String maybeReplaceGrandfatheredLanguageTags(String languageTag) {
|
||||||
for (int i = 0; i < isoGrandfatheredTagReplacements.length; i += 2) {
|
for (int i = 0; i < isoGrandfatheredTagReplacements.length; i += 2) {
|
||||||
if (languageTag.startsWith(isoGrandfatheredTagReplacements[i])) {
|
if (languageTag.startsWith(isoGrandfatheredTagReplacements[i])) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user