我用exoplayer从一个url上播放一些mp4。当用户单击home按钮,或任何导致应用程序从用户视图中删除,然后返回到我的应用程序(和视频活动)的操作时,我希望视频从停止的位置继续。我试图通过将视频位置保存在 onStop()
然后重建播放器并使用 seekTo()
在 onStart()
. 我有一个检查,看看我当前的exoplayer是否为空 onStart()
但是,这张支票从来没有通过,所以我认为这就是问题所在。现在我的视频再也不会恢复了。如果我按home按钮离开应用程序 onStop()
接到电话然后 onStart()
当我回到我的应用程序时会被调用,但是视频播放器仍然是黑色的并且从不播放视频。如果我去掉null检查,每当我从主活动启动一个视频时,我就会得到两个视频播放示例,因为它会同时被调用 onCreate()
以及 onStart()
. 有没有更好的方法来获得我想要的功能?感谢您的帮助!
public class VideoActivity extends AppCompatActivity {
private SimpleExoPlayer exoPlayer;
private SimpleExoPlayerView simpleExoPlayerView;
private long playerPosition;
private String mp4Url;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.player_activity);
// Get the Intent that started this activity and extract the video url
Intent intent = getIntent();
mp4Url = intent.getStringExtra(MainActivity.VIDEO_URL);
// Create an exoplayer instance and start playing video
buildPlayer(mp4Url);
}
private void buildPlayer(String mp4Url) {
// Create a default TrackSelector
Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
// Create the player
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector); // no LoadControl?
simpleExoPlayerView = new SimpleExoPlayerView(this);
simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
// Set media controller
simpleExoPlayerView.setUseController(true);
simpleExoPlayerView.requestFocus();
// Bind player to the view
simpleExoPlayerView.setPlayer(exoPlayer);
// Create Uri from video location
// TODO: should this be in some network class? Should I be appending APIKEY here?
Uri mp4Uri = Uri.parse(mp4Url + "?api_key=" + BuildConfig.GIANTBOMB_API_KEY);
Timber.v("Video url with api key: " + mp4Uri.toString());
// Create another bandwidth meter for bandwidth during playback (not strictly necessary)
DefaultBandwidthMeter playbackBandwidthMeter = new DefaultBandwidthMeter();
// DataSourceFactory to produce DataSource instances through which media data is loaded
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, "GiantBombForAndroid"),
playbackBandwidthMeter);
// Produces Extractor instances for parsing the media data
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
ExtractorMediaSource.EventListener eventListener = new ExtractorMediaSource.EventListener() {
@Override
public void onLoadError(IOException error) {
Timber.e("Error loading video from source");
}
};
final MediaSource videoSource = new ExtractorMediaSource(mp4Uri,
dataSourceFactory,
extractorsFactory,
mainHandler,
eventListener);
exoPlayer.prepare(videoSource);
exoPlayer.addListener(new ExoPlayer.EventListener() {
@Override
public void onLoadingChanged(boolean isLoading) {
Timber.v("Listener-onLoadingChanged...");
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Timber.v("Listener-onPlayerStateChanged...");
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
Timber.v("Listener-onTimelineChanged...");
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
// TODO: Do I need anything here?
}
@Override
public void onPlayerError(ExoPlaybackException error) {
Timber.v("Listener-onPlayerError...");
exoPlayer.stop();
exoPlayer.prepare(videoSource);
exoPlayer.setPlayWhenReady(true);
}
@Override
public void onPositionDiscontinuity() {
Timber.v("Listener-onPositionDiscontinuity...");
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
// TODO: Do I need anything here?
}
});
exoPlayer.setPlayWhenReady(true);
}
@Override
protected void onStart() {
super.onStart();
Timber.v("onStart()...");
if (exoPlayer == null) {
Timber.v("No exoplayer instance, recreating...");
buildPlayer(mp4Url);
exoPlayer.seekTo(playerPosition);
}
}
@Override
protected void onStop(){
super.onStop();
Timber.v("onStop()...");
//TODO: pull player creation code into it's own method so it can be called here as well
playerPosition = exoPlayer.getCurrentPosition();
exoPlayer.release();
}
@Override
protected void onDestroy() {
super.onDestroy();
Timber.v("onDestroy()...");
exoPlayer.release();
}
}
4条答案
按热度按时间nqwrtyyt1#
目前你正在呼叫释放
onStop()
这将消除所有的球员的重要部分,但不是exoPlayer
场(并摧毁任何你没有跟踪自己的状态)。有几种不同的方法。但不管你做什么,你都可能想自己记录一些状态。下面我将它们用作字段,但它们也可以放在
onSavedInstanceState()
. 在onStop()
我们保存了两条信息,然后把它们提取出来onStart()
. 1) 我们球员的最后一个位置是暂停时,以及2)我们是否应该继续比赛时。你可以移动你的seekTo
把电话拨出去if == null
阻止,因为您可能总是希望从上次停止的位置继续我在代码示例中看到的另一个问题是
exoPlayer.release()
不会使字段无效exoPlayer
. 所以你可以再加上一行exoPlayer = null
之后exoPlayer.release()
希望能解决你的多个外星玩家的问题。你也可以移动release()
呼叫onDestroy()
但前提是你知道你正在正确地重新测试一切。x759pob22#
没有必要再束缚玩家。下面的代码就足够了:
56lgkhnf3#
请尝试以下操作
在onpause中获得玩家的位置。
在onresume中再次启动palyer并将seek设置到玩家的最后一个位置
1bqhqjot4#
在我的情况下,如果我最小化或试图从这个播放器视频应用程序移动到另一个应用程序。视频播放器应用程序始终从0开始播放。我试着成功地,视频播放器应用程序播放视频从上一个当前位置时,你最小化或移动到另一个应用程序,这就是它。
去
添加
然后
你可以试着把
从