我试图找出许多不同链接中的问题,但我无法找到任何解决方案。
当设备互联网断开连接并且当我点击重试按钮重新连接互联网连接后,视频确实恢复,但搜索栏和开始持续时间被重置,之后搜索栏确实表现异常(例如,如果我寻求向前走20分钟。它只寻找2-3分钟,或者如果我稍微回头,开始持续时间变为负值,这是完全不合逻辑的。)
我在Playback Control View中做了一些更改,主要是UI更改,并在状态上添加了加载程序(自定义进度对话框)以显示缓冲。 我认为这不会影响ExoPlayer的搜索栏功能。
下面是我的播放器活动类的代码(即PlayerActivity1)以及此类的进度更新方法的日志,以交叉检查SeekBar的位置,为什么它在重试按钮点击后重置。
/**
* An activity that plays media using {@link SimpleExoPlayer}.
*/
public class PlayerActivity1 extends Activity implements OnClickListener, ExoPlayer.EventListener,
PlaybackControlView.VisibilityListener {
public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";
public static final String DRM_LICENSE_URL = "drm_license_url";
public static final String DRM_KEY_REQUEST_PROPERTIES = "drm_key_request_properties";
public static final String PREFER_EXTENSION_DECODERS = "prefer_extension_decoders";
public static final String ACTION_VIEW = "com.google.android.exoplayer.demo.action.VIEW";
public static final String EXTENSION_EXTRA = "extension";
public static final String ACTION_VIEW_LIST =
"com.google.android.exoplayer.demo.action.VIEW_LIST";
public static final String URI_LIST_EXTRA = "uri_list";
public static final String EXTENSION_LIST_EXTRA = "extension_list";
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
private static final CookieManager DEFAULT_COOKIE_MANAGER;
static {
DEFAULT_COOKIE_MANAGER = new CookieManager();
DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
}
private Handler mainHandler;
private EventLogger eventLogger;
private SimpleExoPlayerView simpleExoPlayerView;
private LinearLayout debugRootView;
private TextView debugTextView;
private Button retryButton;
private DataSource.Factory mediaDataSourceFactory;
private SimpleExoPlayer player;
private DefaultTrackSelector trackSelector;
private TrackSelectionHelper trackSelectionHelper;
private DebugTextViewHelper debugViewHelper;
private boolean needRetrySource;
private boolean shouldAutoPlay;
private int resumeWindow;
private long resumePosition;
private String Url;
// Activity lifecycle
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
shouldAutoPlay = true;
clearResumePosition();
mediaDataSourceFactory = buildDataSourceFactory(true);
mainHandler = new Handler();
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);
}
setContentView(R.layout.player_activity);
Url = getIntent().getExtras().getString(Const.VIDEO_LINK);
// Create a PlaylistItem that points to your content
Log.e("URL", Url);
View rootView = findViewById(R.id.root);
rootView.setOnClickListener(this);
debugRootView = (LinearLayout) findViewById(R.id.controls_root);
debugTextView = (TextView) findViewById(R.id.debug_text_view);
retryButton = (Button) findViewById(R.id.retry_button);
retryButton.setOnClickListener(this);
simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
simpleExoPlayerView.setControllerVisibilityListener(this);
simpleExoPlayerView.requestFocus();
}
@Override
public void onNewIntent(Intent intent) {
releasePlayer();
shouldAutoPlay = true;
clearResumePosition();
setIntent(intent);
}
@Override
public void onStart() {
super.onStart();
if (Util.SDK_INT > 23) {
initializePlayer();
}
}
@Override
public void onResume() {
super.onResume();
if ((Util.SDK_INT <= 23 || player == null)) {
initializePlayer();
}
}
@Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayer();
}
}
@Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
releasePlayer();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initializePlayer();
} else {
showToast(R.string.storage_permission_denied);
finish();
}
}
// Activity input
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// Show the controls on any key event.
simpleExoPlayerView.showController();
// If the event was not handled then see if the player view can handle it as a media key event.
return super.dispatchKeyEvent(event) || simpleExoPlayerView.dispatchMediaKeyEvent(event);
}
// OnClickListener methods
@Override
public void onClick(View view) {
if (view == retryButton) {
initializePlayer();
} else if (view.getParent() == debugRootView) {
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
trackSelectionHelper.showSelectionDialog(this, ((Button) view).getText(),
trackSelector.getCurrentMappedTrackInfo(), (int) view.getTag());
}
}
}
// PlaybackControlView.VisibilityListener implementation
@Override
public void onVisibilityChange(int visibility) {
debugRootView.setVisibility(visibility);
}
// Internal methods
private void initializePlayer() {
Intent intent = getIntent();
boolean needNewPlayer = player == null;
if (needNewPlayer) {
boolean preferExtensionDecoders = intent.getBooleanExtra(PREFER_EXTENSION_DECODERS, false);
UUID drmSchemeUuid = intent.hasExtra(DRM_SCHEME_UUID_EXTRA)
? UUID.fromString(intent.getStringExtra(DRM_SCHEME_UUID_EXTRA)) : null;
DrmSessionManager<FrameworkMediaCrypto> drmSessionManager = null;
if (drmSchemeUuid != null) {
String drmLicenseUrl = intent.getStringExtra(DRM_LICENSE_URL);
String[] keyRequestPropertiesArray = intent.getStringArrayExtra(DRM_KEY_REQUEST_PROPERTIES);
try {
drmSessionManager = buildDrmSessionManager(drmSchemeUuid, drmLicenseUrl,
keyRequestPropertiesArray);
} catch (UnsupportedDrmException e) {
int errorStringId = Util.SDK_INT < 18 ? R.string.error_drm_not_supported
: (e.reason == UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME
? R.string.error_drm_unsupported_scheme : R.string.error_drm_unknown);
showToast(errorStringId);
return;
}
}
@SimpleExoPlayer.ExtensionRendererMode int extensionRendererMode =
((demoApp) getApplication()).useExtensionRenderers()
? (preferExtensionDecoders ? SimpleExoPlayer.EXTENSION_RENDERER_MODE_PREFER
: SimpleExoPlayer.EXTENSION_RENDERER_MODE_ON)
: SimpleExoPlayer.EXTENSION_RENDERER_MODE_OFF;
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelectionHelper = new TrackSelectionHelper(trackSelector, videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, new DefaultLoadControl(),
drmSessionManager, extensionRendererMode);
player.addListener(this);
eventLogger = new EventLogger(trackSelector);
player.addListener(eventLogger);
player.setAudioDebugListener(eventLogger);
player.setVideoDebugListener(eventLogger);
player.setMetadataOutput(eventLogger);
simpleExoPlayerView.setPlayer(player);
player.setPlayWhenReady(shouldAutoPlay);
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
debugViewHelper.start();
}
if (needNewPlayer || needRetrySource) {
Uri[] uris;
String[] extensions;
uris = new Uri[]{Uri.parse(Url)};
extensions = new String[]{intent.getStringExtra(EXTENSION_EXTRA)};
if (Util.maybeRequestReadExternalStoragePermission(this, uris)) {
// The player will be reinitialized if the permission is granted.
return;
}
MediaSource[] mediaSources = new MediaSource[uris.length];
for (int i = 0; i < uris.length; i++) {
mediaSources[i] = buildMediaSource(uris[i], extensions[i]);
}
MediaSource mediaSource = mediaSources.length == 1 ? mediaSources[0]
: new ConcatenatingMediaSource(mediaSources);
boolean haveResumePosition = resumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
player.seekTo(resumeWindow, resumePosition);
}
player.prepare(mediaSource, !haveResumePosition, false);
needRetrySource = false;
updateButtonVisibilities();
}
Log.e("PlayerActivity1 ", "initializePlayer ");
}
private MediaSource buildMediaSource(Uri uri, String overrideExtension) {
int type = TextUtils.isEmpty(overrideExtension) ? Util.inferContentType(uri)
: Util.inferContentType("." + overrideExtension);
switch (type) {
case C.TYPE_SS:
return new SsMediaSource(uri, buildDataSourceFactory(false),
new DefaultSsChunkSource.Factory(mediaDataSourceFactory), mainHandler, eventLogger);
case C.TYPE_DASH:
return new DashMediaSource(uri, buildDataSourceFactory(false),
new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mainHandler, eventLogger);
case C.TYPE_HLS:
return new HlsMediaSource(uri, mediaDataSourceFactory, mainHandler, eventLogger);
case C.TYPE_OTHER:
return new ExtractorMediaSource(uri, mediaDataSourceFactory, new DefaultExtractorsFactory(),
mainHandler, eventLogger);
default: {
throw new IllegalStateException("Unsupported type: " + type);
}
}
}
private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager(UUID uuid,
String licenseUrl, String[] keyRequestPropertiesArray) throws UnsupportedDrmException {
if (Util.SDK_INT < 18) {
return null;
}
HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl,
buildHttpDataSourceFactory(false));
if (keyRequestPropertiesArray != null) {
for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) {
drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i],
keyRequestPropertiesArray[i + 1]);
}
}
return new DefaultDrmSessionManager<>(uuid,
FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, eventLogger);
}
private void releasePlayer() {
if (player != null) {
debugViewHelper.stop();
debugViewHelper = null;
shouldAutoPlay = player.getPlayWhenReady();
updateResumePosition();
player.release();
player = null;
trackSelector = null;
trackSelectionHelper = null;
eventLogger = null;
}
Log.e("PlayerActivity1 ", "releasePlayer ");
}
private void updateResumePosition() {
resumeWindow = player.getCurrentWindowIndex();
resumePosition = player.isCurrentWindowSeekable() ? Math.max(0, player.getCurrentPosition())
: C.TIME_UNSET;
Log.e("PlayerActivity1 ", "updateResumePosition ");
}
private void clearResumePosition() {
resumeWindow = C.INDEX_UNSET;
resumePosition = C.TIME_UNSET;
Log.e("PlayerActivity1 ", "clearResumePosition ");
}
/**
* Returns a new DataSource factory.
*
* @param useBandwidthMeter Whether to set {@link #BANDWIDTH_METER} as a listener to the new
* DataSource factory.
* @return A new DataSource factory.
*/
private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) {
return ((demoApp) getApplication())
.buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
}
/**
* Returns a new HttpDataSource factory.
*
* @param useBandwidthMeter Whether to set {@link #BANDWIDTH_METER} as a listener to the new
* DataSource factory.
* @return A new HttpDataSource factory.
*/
private HttpDataSource.Factory buildHttpDataSourceFactory(boolean useBandwidthMeter) {
return ((demoApp) getApplication())
.buildHttpDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
}
// ExoPlayer.EventListener implementation
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
Log.e("PlayerActivity1 ", "onLoadingChanged ");
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_ENDED) {
showControls();
}
updateButtonVisibilities();
Log.e("PlayerActivity1 ", "onPlayerStateChanged ");
}
@Override
public void onPositionDiscontinuity() {
if (needRetrySource) {
// This will only occur if the user has performed a seek whilst in the error state. Update the
// resume position so that if the user then retries, playback will resume from the position to
// which they seeked.
updateResumePosition();
}
Log.e("PlayerActivity1 ", "onPositionDiscontinuity ");
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
// Do nothing.
Log.e("PlayerActivity1 ", "onTimelineChanged ");
}
@Override
public void onPlayerError(ExoPlaybackException e) {
String errorString = null;
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
Exception cause = e.getRendererException();
if (cause instanceof DecoderInitializationException) {
// Special case for decoder initialization failures.
DecoderInitializationException decoderInitializationException =
(DecoderInitializationException) cause;
if (decoderInitializationException.decoderName == null) {
if (decoderInitializationException.getCause() instanceof DecoderQueryException) {
errorString = getString(R.string.error_querying_decoders);
} else if (decoderInitializationException.secureDecoderRequired) {
errorString = getString(R.string.error_no_secure_decoder,
decoderInitializationException.mimeType);
} else {
errorString = getString(R.string.error_no_decoder,
decoderInitializationException.mimeType);
}
} else {
errorString = getString(R.string.error_instantiating_decoder,
decoderInitializationException.decoderName);
}
}
}
if (errorString != null) {
showToast(errorString);
}
needRetrySource = true;
if (isBehindLiveWindow(e)) {
clearResumePosition();
initializePlayer();
} else {
updateResumePosition();
updateButtonVisibilities();
showControls();
}
Log.e("PlayerActivity1 ", "onPlayerError ");
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
updateButtonVisibilities();
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_VIDEO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_video);
}
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_AUDIO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_audio);
}
}
Log.e("PlayerActivity1 ", "onTracksChanged ");
}
// User controls
private void updateButtonVisibilities() {
debugRootView.removeAllViews();
retryButton.setVisibility(needRetrySource ? View.VISIBLE : View.GONE);
debugRootView.addView(retryButton);
if (player == null) {
return;
}
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo == null) {
return;
}
// for (int i = 0; i < mappedTrackInfo.length; i++) {
// TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(i);
// if (trackGroups.length != 0) {
// Button button = new Button(this);
// int label;
// switch (player.getRendererType(i)) {
// case C.TRACK_TYPE_AUDIO:
// label = R.string.audio;
// break;
// case C.TRACK_TYPE_VIDEO:
// label = R.string.video;
// break;
// case C.TRACK_TYPE_TEXT:
// label = R.string.text;
// break;
// default:
// continue;
// }
// button.setText(label);
// button.setTag(i);
// button.setOnClickListener(this);
// debugRootView.addView(button, debugRootView.getChildCount() - 1);
// }
// }
}
private void showControls() {
debugRootView.setVisibility(View.VISIBLE);
}
private void showToast(int messageId) {
showToast(getString(messageId));
}
private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
return false;
}
Throwable cause = e.getSourceException();
while (cause != null) {
if (cause instanceof BehindLiveWindowException) {
return true;
}
cause = cause.getCause();
}
return false;
}
}
断开互联网连接并重新连接时记录
11-09 11:29:18.619 31502-31502/com.xyz.app E/EventLogger: internalError [34.41, loadError]
11-09 11:29:19.519 31502-31502/com.xyz.app E/updateProgress: 844433
11-09 11:29:20.522 31502-31502/com.xyz.app E/updateProgress: 844433
11-09 11:29:20.642 31502-31502/com.xyz.app E/EventLogger: internalError [36.43, loadError]
11-09 11:29:20.644 31502-861/com.xyz.app E/ExoPlayerImplInternal: Source error.
11-09 11:29:20.646 31502-31502/com.xyz.app E/PlayerActivity1: updateResumePosition
11-09 11:29:20.647 31502-31502/com.xyz.app E/PlayerActivity1: onPlayerError
11-09 11:29:20.647 31502-31502/com.demo.app E/EventLogger: playerFailed [36.44]
11-09 11:29:20.647 31502-31502/com.demo.app E/ComponentListener: onPlayerError custom
11-09 11:29:20.734 31502-31502/com.demo.app E/PlayerActivity1: onLoadingChanged
11-09 11:29:20.734 31502-31502/com.demo.app E/ComponentListener: onLoadingChanged
11-09 11:29:20.737 31502-31502/com.demo.app E/PlayerActivity1: onPlayerStateChanged
11-09 11:29:20.738 31502-31502/com.demo.app E/updateProgress: 844433
[ 11-09 11:29:20.748 14756:32165 D/ ]
x = 0.792153, y = -0.017963, z = 10.968591
11-09 11:29:20.778 31502-31502/com.demo.app E/ComponentListener: onPlayerStateChanged 1
11-09 11:29:36.963 31502-31502/com.demo.app E/updateProgress: 844433
11-09 11:29:37.648 31502-31502/com.demo.app E/PlayerActivity1: updateResumePosition
11-09 11:29:37.648 31502-31502/com.demo.app E/PlayerActivity1: onPositionDiscontinuity
11-09 11:29:37.649 31502-31502/com.demo.app E/updateProgress: 844433
11-09 11:29:37.649 31502-31502/com.demo.app E/ComponentListener: onPositionDiscontinuity
11-09 11:29:37.654 31502-31502/com.demo.app E/PlayerActivity1: initializePlayer
11-09 11:29:37.659 31502-31502/com.demo.app E/PlayerActivity1: onPlayerStateChanged
11-09 11:29:37.660 31502-31502/com.demo.app E/updateProgress: 844433
[ 11-09 11:29:37.663 14756:32165 D/ ]
x = 0.803529, y = 0.000599, z = 10.944042
11-09 11:29:37.681 31502-31502/com.demo.app E/ComponentListener: onPlayerStateChanged 2
11-09 11:29:37.681 31502-31502/com.demo.app E/PlayerActivity1: onTimelineChanged
11-09 11:29:37.683 31502-31502/com.demo.app E/updateProgress: 844433
11-09 11:29:37.683 31502-31502/com.demo.app E/ComponentListener: onProgressChanged
11-09 11:29:37.684 31502-31502/com.demo.app E/ComponentListener: onTimelineChanged
11-09 11:29:37.684 31502-31502/com.demo.app E/PlayerActivity1: onLoadingChanged
11-09 11:29:37.684 31502-31502/com.demo.app E/ComponentListener: onLoadingChanged
11-09 11:29:38.684 31502-31502/com.demo.app E/updateProgress: 844433
11-09 11:29:39.686 31502-31502/com.demo.app E/updateProgress: 844433
[ 11-09 11:29:39.734 14756:32165 D/ ]
x = 0.814307, y = 0.007185, z = 10.950628
[ 11-09 11:29:39.800 14756:32165 D/ ]
x = 0.805325, y = -0.015568, z = 10.953023
11-09 11:29:40.687 31502-31502/com.demo.app E/updateProgress: 844433
11-09 11:29:41.688 31502-31502/com.demo.app E/updateProgress: 844433
11-09 11:29:49.859 31502-31502/com.demo.app E/PlayerActivity1: onTimelineChanged
11-09 11:29:49.859 31502-31502/com.demo.app E/ComponentListener: onTimelineChanged
11-09 11:29:49.860 31502-31502/com.demo.app E/PlayerActivity1: onTracksChanged
11-09 11:29:49.862 31502-31502/com.demo.app E/ComponentListener: onTracksChanged
11-09 11:29:50.656 31502-2914/com.demo.app E/ACodec: cannot find aac bit rate
11-09 11:29:52.574 31502-31502/com.demo.app E/PlayerActivity1: onPlayerStateChanged
11-09 11:29:52.688 31502-31502/com.demo.app E/ComponentListener: onPlayerStateChanged 3
11-09 11:29:55.823 31502-31502/com.demo.app E/PlayerActivity1: onLoadingChanged
11-09 11:29:55.823 31502-31502/com.demo.app E/ComponentListener: onLoadingChanged
11-09 11:29:59.221 31502-31502/com.demo.app E/updateProgress: 6566
11-09 11:29:59.221 31502-31502/com.demo.app E/ComponentListener: onProgressChanged
11-09 11:29:59.658 31502-31502/com.demo.app E/updateProgress: 7004
11-09 11:30:00.655 31502-31502/com.demo.app E/updateProgress: 7997
11-09 11:30:00.725 31502-31502/com.demo.app E/PlayerActivity1: onPlayerStateChanged
11-09 11:30:00.728 31502-31502/com.demo.app E/updateProgress: 8069
11-09 11:30:00.728 31502-31502/com.demo.app E/ComponentListener: onPlayerStateChanged 3