diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index eb9dc3b64..4f642af3b 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -239,10 +239,6 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List return mHistory != null && mHistory.getScale() != -1 ? mHistory.getScale() : Setting.getScale(); } - private boolean isReplay() { - return Setting.getReset() == 1; - } - private boolean isFromCollect() { return getIntent().getBooleanExtra("collect", false); } @@ -505,12 +501,12 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List }; } - private void getPlayer(Flag flag, Episode episode, boolean replay) { + private void getPlayer(Flag flag, Episode episode) { mBinding.widget.title.setText(getString(R.string.detail_title, mBinding.name.getText(), episode.getName())); mViewModel.playerContent(getKey(), flag.getFlag(), episode.getUrl()); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mBinding.widget.title.setSelected(true); - updateHistory(episode, replay); + updateHistory(episode); showProgress(); setMetadata(); hideCenter(); @@ -747,22 +743,25 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List return true; } - private void onRefresh() { - onReset(false); + private void onReset() { + boolean refresh = Setting.getReset() == 0; + if (refresh) onRefresh(); + else onReplay(); } - private void onReset() { - onReset(isReplay()); + private void onReplay() { + if (mPlayers.isEmpty()) onRefresh(); + else mPlayers.replay(); } - private void onReset(boolean replay) { + private void onRefresh() { saveHistory(); mPlayers.stop(); mPlayers.clear(); mClock.setCallback(null); if (mFlagAdapter.size() == 0) return; if (mEpisodeAdapter.size() == 0) return; - getPlayer(getFlag(), getEpisode(), replay); + getPlayer(getFlag(), getEpisode()); } private boolean onResetToggle() { @@ -976,12 +975,11 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List } } - private void updateHistory(Episode item, boolean replay) { - replay = replay || !item.equals(mHistory.getEpisode()); - mHistory.setEpisodeUrl(item.getUrl()); - mHistory.setVodRemarks(item.getName()); + private void updateHistory(Episode item) { + mHistory.setPosition(item.equals(mHistory.getEpisode()) ? mHistory.getPosition() : C.TIME_UNSET); mHistory.setVodFlag(getFlag().getFlag()); - mHistory.setPosition(replay ? C.TIME_UNSET : mHistory.getPosition()); + mHistory.setVodRemarks(item.getName()); + mHistory.setEpisodeUrl(item.getUrl()); } private void checkKeepImg() { @@ -1053,7 +1051,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List } else if (ActionEvent.LOOP.equals(event.getAction())) { onLoop(); } else if (ActionEvent.REPLAY.equals(event.getAction())) { - onReset(true); + onReplay(); } else if (ActionEvent.STOP.equals(event.getAction())) { finish(); } @@ -1104,7 +1102,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List private void checkEnded(boolean notify) { if (mBinding.control.loop.isActivated()) { - onReset(true); + onReplay(); } else { getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); checkNext(notify); diff --git a/app/src/main/java/com/fongmi/android/tv/player/Players.java b/app/src/main/java/com/fongmi/android/tv/player/Players.java index 3f1bfaba1..49a4eef11 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/Players.java +++ b/app/src/main/java/com/fongmi/android/tv/player/Players.java @@ -254,10 +254,6 @@ public class Players implements Player.Listener, ParseCallback { return exoPlayer == null ? 0 : exoPlayer.getBufferedPosition(); } - public boolean retried() { - return ++retry > 2; - } - public boolean haveTrack(int type) { return exoPlayer != null && TrackUtil.count(exoPlayer.getCurrentTracks(), type) > 0; } @@ -406,6 +402,12 @@ public class Players implements Player.Listener, ParseCallback { stopParse(); } + public void replay() { + seekTo(C.TIME_UNSET); + prepare(); + play(); + } + public void release() { stopParse(); releasePlayer(); @@ -668,27 +670,28 @@ public class Players implements Player.Listener, ParseCallback { } @Override - public void onPlayerError(@NonNull PlaybackException error) { - if (retried()) ErrorEvent.extract(tag, provider.get(error)); - else switch (error.errorCode) { - case PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW: - seekToDefaultPosition(); - break; - case PlaybackException.ERROR_CODE_DECODER_INIT_FAILED: - case PlaybackException.ERROR_CODE_DECODER_QUERY_FAILED: - case PlaybackException.ERROR_CODE_DECODING_FAILED: - toggleDecode(); - break; - case PlaybackException.ERROR_CODE_IO_UNSPECIFIED: - case PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED: - case PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED: - case PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED: - case PlaybackException.ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED: - setFormat(ExoUtil.getMimeType(error.errorCode)); - break; - default: - ErrorEvent.extract(tag, provider.get(error)); - break; - } + public void onPlayerError(@NonNull PlaybackException e) { + if (++retry > 2) ErrorEvent.extract(tag, provider.get(e)); + else if (provider.isInvalidLength(e)) replay(); + else switch (e.errorCode) { + case PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW: + seekToDefaultPosition(); + break; + case PlaybackException.ERROR_CODE_DECODER_INIT_FAILED: + case PlaybackException.ERROR_CODE_DECODER_QUERY_FAILED: + case PlaybackException.ERROR_CODE_DECODING_FAILED: + toggleDecode(); + break; + case PlaybackException.ERROR_CODE_IO_UNSPECIFIED: + case PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED: + case PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED: + case PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED: + case PlaybackException.ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED: + setFormat(ExoUtil.getMimeType(e.errorCode)); + break; + default: + setMediaItem(); + break; + } } } diff --git a/app/src/main/java/com/fongmi/android/tv/player/exo/ErrorMsgProvider.java b/app/src/main/java/com/fongmi/android/tv/player/exo/ErrorMsgProvider.java index ef96e63a7..7c1ccfb63 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/exo/ErrorMsgProvider.java +++ b/app/src/main/java/com/fongmi/android/tv/player/exo/ErrorMsgProvider.java @@ -4,6 +4,10 @@ import androidx.media3.common.PlaybackException; public class ErrorMsgProvider { + public boolean isInvalidLength(PlaybackException e) { + return e.getCause() != null && e.getCause().getMessage() != null && e.getCause().getMessage().startsWith("Invalid NAL length"); + } + public String get(PlaybackException e) { return switch (e.errorCode) { case PlaybackException.ERROR_CODE_TIMEOUT -> "Timeout"; diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index 13a716c1c..27a22d9b1 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -234,10 +234,6 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo return mHistory != null && mHistory.getScale() != -1 ? mHistory.getScale() : Setting.getScale(); } - private boolean isReplay() { - return Setting.getReset() == 1; - } - private boolean isFromCollect() { return getIntent().getBooleanExtra("collect", false); } @@ -536,12 +532,12 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo view.setText(Util.substring(sb.toString(), 2)); } - private void getPlayer(Flag flag, Episode episode, boolean replay) { + private void getPlayer(Flag flag, Episode episode) { mBinding.control.title.setText(getString(R.string.detail_title, mBinding.name.getText(), episode.getName())); mViewModel.playerContent(getKey(), flag.getFlag(), episode.getUrl()); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mBinding.control.title.setSelected(true); - updateHistory(episode, replay); + updateHistory(episode); showProgress(); setMetadata(); } @@ -779,22 +775,25 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo return true; } - private void onRefresh() { - onReset(false); + private void onReset() { + boolean refresh = Setting.getReset() == 0; + if (refresh) onRefresh(); + else onReplay(); } - private void onReset() { - onReset(isReplay()); + private void onReplay() { + if (mPlayers.isEmpty()) onRefresh(); + else mPlayers.replay(); } - private void onReset(boolean replay) { + private void onRefresh() { saveHistory(); mPlayers.stop(); mPlayers.clear(); mClock.setCallback(null); if (mFlagAdapter.isEmpty()) return; if (mEpisodeAdapter.isEmpty()) return; - getPlayer(getFlag(), getEpisode(), replay); + getPlayer(getFlag(), getEpisode()); } private boolean onResetToggle() { @@ -1055,12 +1054,11 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo } } - private void updateHistory(Episode item, boolean replay) { - replay = replay || !item.equals(mHistory.getEpisode()); - mHistory.setEpisodeUrl(item.getUrl()); - mHistory.setVodRemarks(item.getName()); + private void updateHistory(Episode item) { + mHistory.setPosition(item.equals(mHistory.getEpisode()) ? mHistory.getPosition() : C.TIME_UNSET); mHistory.setVodFlag(getFlag().getFlag()); - mHistory.setPosition(replay ? C.TIME_UNSET : mHistory.getPosition()); + mHistory.setVodRemarks(item.getName()); + mHistory.setEpisodeUrl(item.getUrl()); } private void checkControl() { @@ -1154,7 +1152,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo } else if (ActionEvent.LOOP.equals(event.getAction())) { onLoop(); } else if (ActionEvent.REPLAY.equals(event.getAction())) { - onReset(true); + onReplay(); } else if (ActionEvent.AUDIO.equals(event.getAction())) { moveTaskToBack(true); setAudioOnly(true); @@ -1240,7 +1238,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo private void checkEnded(boolean notify) { if (mBinding.control.action.loop.isActivated()) { - onReset(true); + onReplay(); } else { getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); checkNext(notify); @@ -1515,12 +1513,14 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo @Override public void onFlingUp() { - checkNext(); + if (mEpisodeAdapter.getItemCount() == 1) onRefresh(); + else checkNext(); } @Override public void onFlingDown() { - checkPrev(); + if (mEpisodeAdapter.getItemCount() == 1) onRefresh(); + else checkPrev(); } @Override