exoplayer 的方向改变延迟
Delay in exoplayer on orientaion change
问题是当我尝试更改播放器的方向时出现延迟。在视频恢复之前有大约 2 或 3 秒的延迟。除了方向改变外,其他一切都很好。
public class MainActivity extends AppCompatActivity {
private final String STATE_RESUME_WINDOW = "resumeWindow";
private final String STATE_RESUME_POSITION = "resumePosition";
private final String STATE_PLAYER_FULLSCREEN = "playerFullscreen";
private SimpleExoPlayerView mExoPlayerView;
private MediaSource mVideoSource;
private boolean mExoPlayerFullscreen = false;
private FrameLayout mFullScreenButton;
private ImageView mFullScreenIcon;
private Dialog mFullScreenDialog;
private int mResumeWindow;
private long mResumePosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
mResumeWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW);
mResumePosition = savedInstanceState.getLong(STATE_RESUME_POSITION);
mExoPlayerFullscreen = savedInstanceState.getBoolean(STATE_PLAYER_FULLSCREEN);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(STATE_RESUME_WINDOW, mResumeWindow);
outState.putLong(STATE_RESUME_POSITION, mResumePosition);
outState.putBoolean(STATE_PLAYER_FULLSCREEN, mExoPlayerFullscreen);
super.onSaveInstanceState(outState);
}
private void initFullscreenDialog() {
mFullScreenDialog = new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
public void onBackPressed() {
if (mExoPlayerFullscreen)
closeFullscreenDialog();
super.onBackPressed();
}
};
}
private void openFullscreenDialog() {
((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_fullscreen_shrink));
mExoPlayerFullscreen = true;
mFullScreenDialog.show();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
private void closeFullscreenDialog() {
((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
((FrameLayout) findViewById(R.id.main_media_frame)).addView(mExoPlayerView);
mExoPlayerFullscreen = false;
mFullScreenDialog.dismiss();
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_fullscreen_expand));
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
private void initFullscreenButton() {
PlaybackControlView controlView = mExoPlayerView.findViewById(R.id.exo_controller);
mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
mFullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button);
mFullScreenButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mExoPlayerFullscreen)
openFullscreenDialog();
else
closeFullscreenDialog();
}
});
}
private void initExoPlayer() {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this),trackSelector, loadControl);
mExoPlayerView.setPlayer(player);
boolean haveResumePosition = mResumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
mExoPlayerView.getPlayer().seekTo(mResumeWindow, mResumePosition);
}
mExoPlayerView.getPlayer().prepare(mVideoSource);
mExoPlayerView.getPlayer().setPlayWhenReady(true);
}
@Override
protected void onResume() {
super.onResume();
if (mExoPlayerView == null) {
mExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.exoplayer);
initFullscreenDialog();
initFullscreenButton();
String streamUrl = "https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8";
String userAgent = Util.getUserAgent(MainActivity.this, getApplicationContext().getApplicationInfo().packageName);
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent, null,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true);
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(MainActivity.this, null,httpDataSourceFactory);
Uri daUri = Uri.parse(streamUrl);
mVideoSource = new HlsMediaSource(daUri, dataSourceFactory, 1, null, null);
}
initExoPlayer();
if (mExoPlayerFullscreen) {
((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this,
R.drawable.ic_fullscreen_shrink));
mFullScreenDialog.show();
}
}
@Override
protected void onPause() {
super.onPause();
if (mExoPlayerView != null && mExoPlayerView.getPlayer() != null) {
mResumeWindow = mExoPlayerView.getPlayer().getCurrentWindowIndex();
mResumePosition = Math.max(0, mExoPlayerView.getPlayer().getContentPosition());
mExoPlayerView.getPlayer().release();
}
if (mFullScreenDialog != null)
mFullScreenDialog.dismiss();
}
}
您应该研究 handling configuration changes yourself - 正如@marcbaechinger 上面提到的那样。
必要的部分在这里:
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name">
最重要的部分是:
Remember: When you declare your activity to handle a configuration change, you are responsible for resetting any elements for which you provide alternatives. If you declare your activity to handle the orientation change and have images that should change between landscape and portrait, you must re-assign each resource to each element during onConfigurationChanged().
但是,如果您没有任何横向特定的布局文件或图像,那么您可能没问题。
我们必须编写自己的全屏旋转逻辑,但考虑到 Android 为您提供配置更改事件,这就足够简单了。
为了增加这种方法的有效性,Google 通过 Youtube player documentation 推荐(特别是关于全屏):
To achieve this for an activity that supports portrait, you need to specify that your activity handles some configuration changes on its own in your application's manifest, including orientation, keyboardHidden and screenSize.
问题是当我尝试更改播放器的方向时出现延迟。在视频恢复之前有大约 2 或 3 秒的延迟。除了方向改变外,其他一切都很好。
public class MainActivity extends AppCompatActivity {
private final String STATE_RESUME_WINDOW = "resumeWindow";
private final String STATE_RESUME_POSITION = "resumePosition";
private final String STATE_PLAYER_FULLSCREEN = "playerFullscreen";
private SimpleExoPlayerView mExoPlayerView;
private MediaSource mVideoSource;
private boolean mExoPlayerFullscreen = false;
private FrameLayout mFullScreenButton;
private ImageView mFullScreenIcon;
private Dialog mFullScreenDialog;
private int mResumeWindow;
private long mResumePosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
mResumeWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW);
mResumePosition = savedInstanceState.getLong(STATE_RESUME_POSITION);
mExoPlayerFullscreen = savedInstanceState.getBoolean(STATE_PLAYER_FULLSCREEN);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(STATE_RESUME_WINDOW, mResumeWindow);
outState.putLong(STATE_RESUME_POSITION, mResumePosition);
outState.putBoolean(STATE_PLAYER_FULLSCREEN, mExoPlayerFullscreen);
super.onSaveInstanceState(outState);
}
private void initFullscreenDialog() {
mFullScreenDialog = new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
public void onBackPressed() {
if (mExoPlayerFullscreen)
closeFullscreenDialog();
super.onBackPressed();
}
};
}
private void openFullscreenDialog() {
((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_fullscreen_shrink));
mExoPlayerFullscreen = true;
mFullScreenDialog.show();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
private void closeFullscreenDialog() {
((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
((FrameLayout) findViewById(R.id.main_media_frame)).addView(mExoPlayerView);
mExoPlayerFullscreen = false;
mFullScreenDialog.dismiss();
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_fullscreen_expand));
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
private void initFullscreenButton() {
PlaybackControlView controlView = mExoPlayerView.findViewById(R.id.exo_controller);
mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
mFullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button);
mFullScreenButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mExoPlayerFullscreen)
openFullscreenDialog();
else
closeFullscreenDialog();
}
});
}
private void initExoPlayer() {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this),trackSelector, loadControl);
mExoPlayerView.setPlayer(player);
boolean haveResumePosition = mResumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
mExoPlayerView.getPlayer().seekTo(mResumeWindow, mResumePosition);
}
mExoPlayerView.getPlayer().prepare(mVideoSource);
mExoPlayerView.getPlayer().setPlayWhenReady(true);
}
@Override
protected void onResume() {
super.onResume();
if (mExoPlayerView == null) {
mExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.exoplayer);
initFullscreenDialog();
initFullscreenButton();
String streamUrl = "https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8";
String userAgent = Util.getUserAgent(MainActivity.this, getApplicationContext().getApplicationInfo().packageName);
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent, null,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true);
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(MainActivity.this, null,httpDataSourceFactory);
Uri daUri = Uri.parse(streamUrl);
mVideoSource = new HlsMediaSource(daUri, dataSourceFactory, 1, null, null);
}
initExoPlayer();
if (mExoPlayerFullscreen) {
((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this,
R.drawable.ic_fullscreen_shrink));
mFullScreenDialog.show();
}
}
@Override
protected void onPause() {
super.onPause();
if (mExoPlayerView != null && mExoPlayerView.getPlayer() != null) {
mResumeWindow = mExoPlayerView.getPlayer().getCurrentWindowIndex();
mResumePosition = Math.max(0, mExoPlayerView.getPlayer().getContentPosition());
mExoPlayerView.getPlayer().release();
}
if (mFullScreenDialog != null)
mFullScreenDialog.dismiss();
}
}
您应该研究 handling configuration changes yourself - 正如@marcbaechinger 上面提到的那样。
必要的部分在这里:
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name">
最重要的部分是:
Remember: When you declare your activity to handle a configuration change, you are responsible for resetting any elements for which you provide alternatives. If you declare your activity to handle the orientation change and have images that should change between landscape and portrait, you must re-assign each resource to each element during onConfigurationChanged().
但是,如果您没有任何横向特定的布局文件或图像,那么您可能没问题。
我们必须编写自己的全屏旋转逻辑,但考虑到 Android 为您提供配置更改事件,这就足够简单了。
为了增加这种方法的有效性,Google 通过 Youtube player documentation 推荐(特别是关于全屏):
To achieve this for an activity that supports portrait, you need to specify that your activity handles some configuration changes on its own in your application's manifest, including orientation, keyboardHidden and screenSize.