From 32849f5279eb78c6e2518a9232cb7bd82c5d47b6 Mon Sep 17 00:00:00 2001 From: Niels van Velzen Date: Sat, 16 Dec 2023 12:24:41 +0100 Subject: [PATCH] Fix crash when starting player where playback controller may be null --- .../CustomPlaybackOverlayFragment.java | 78 +++++++++---------- .../overlay/LeanbackOverlayFragment.java | 12 +-- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/org/jellyfin/androidtv/ui/playback/CustomPlaybackOverlayFragment.java b/app/src/main/java/org/jellyfin/androidtv/ui/playback/CustomPlaybackOverlayFragment.java index cc28aec751..3dc02c8d21 100644 --- a/app/src/main/java/org/jellyfin/androidtv/ui/playback/CustomPlaybackOverlayFragment.java +++ b/app/src/main/java/org/jellyfin/androidtv/ui/playback/CustomPlaybackOverlayFragment.java @@ -127,7 +127,6 @@ public class CustomPlaybackOverlayFragment extends Fragment implements LiveTvGui private List mAllChannels; private String mFirstFocusChannelId; - private PlaybackController mPlaybackController; private List mItemsToPlay; private Animation fadeOut; @@ -195,7 +194,6 @@ public void onCreate(Bundle savedInstanceState) { int mediaPosition = videoQueueManager.getValue().getCurrentMediaPosition(); playbackControllerContainer.getValue().setPlaybackController(new PlaybackController(mItemsToPlay, this, mediaPosition)); - mPlaybackController = playbackControllerContainer.getValue().getPlaybackController(); // setup fade task mHideTask = () -> { @@ -350,7 +348,7 @@ public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, in int startPos = getArguments().getInt("Position", 0); // start playing - mPlaybackController.play(startPos); + playbackControllerContainer.getValue().getPlaybackController().play(startPos); leanbackOverlayFragment.updatePlayState(); } @@ -358,7 +356,7 @@ public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, in private void prepareOverlayFragment() { leanbackOverlayFragment = (LeanbackOverlayFragment) getChildFragmentManager().findFragmentById(R.id.leanback_fragment); if (leanbackOverlayFragment != null) { - leanbackOverlayFragment.initFromView(mPlaybackController, this); + leanbackOverlayFragment.initFromView(this); leanbackOverlayFragment.mediaInfoChanged(); leanbackOverlayFragment.setOnKeyInterceptListener(keyListener); } @@ -403,7 +401,7 @@ public void onAnimationRepeat(Animation animation) { public void onAudioFocusChange(int focusChange) { switch (focusChange) { case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: - mPlaybackController.pause(); + playbackControllerContainer.getValue().getPlaybackController().pause(); break; case AudioManager.AUDIOFOCUS_LOSS: // We don't do anything here on purpose @@ -424,7 +422,7 @@ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, switch (rowItem.getBaseRowType()) { case Chapter: Long start = rowItem.getChapterInfo().getStartPositionTicks() / 10000; - mPlaybackController.seek(start); + playbackControllerContainer.getValue().getPlaybackController().seek(start); hidePopupPanel(); break; } @@ -445,7 +443,7 @@ public void handleOnBackPressed() { leanbackOverlayFragment.hideOverlay(); // also close this if live tv - if (mPlaybackController.isLiveTv()) hide(); + if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) hide(); } else if (mGuideVisible) { hideGuide(); } else { @@ -490,19 +488,19 @@ else if (mSelectedProgramView instanceof GuideChannelHeader) } if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) { - mPlaybackController.play(0); + playbackControllerContainer.getValue().getPlaybackController().play(0); return true; } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) { - mPlaybackController.pause(); + playbackControllerContainer.getValue().getPlaybackController().pause(); return true; } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) { - mPlaybackController.playPause(); + playbackControllerContainer.getValue().getPlaybackController().playPause(); return true; } else if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD || keyCode == KeyEvent.KEYCODE_BUTTON_R1 || keyCode == KeyEvent.KEYCODE_BUTTON_R2) { - mPlaybackController.fastForward(); + playbackControllerContainer.getValue().getPlaybackController().fastForward(); return true; } else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND || keyCode == KeyEvent.KEYCODE_BUTTON_L1 || keyCode == KeyEvent.KEYCODE_BUTTON_L2) { - mPlaybackController.rewind(); + playbackControllerContainer.getValue().getPlaybackController().rewind(); return true; } } @@ -559,7 +557,7 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { leanbackOverlayFragment.hideOverlay(); // also close this if live tv - if (mPlaybackController.isLiveTv()) hide(); + if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) hide(); return true; } else if (mGuideVisible) { hideGuide(); @@ -567,7 +565,7 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { } } - if (mPlaybackController.isLiveTv() && !mPopupPanelVisible && !mGuideVisible && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { + if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv() && !mPopupPanelVisible && !mGuideVisible && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { if (!leanbackOverlayFragment.isControlsOverlayVisible()) { leanbackOverlayFragment.setShouldShowOverlay(false); leanbackOverlayFragment.hideOverlay(); @@ -596,7 +594,7 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { } } - if (mPlaybackController.isLiveTv() && keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BUTTON_Y) { + if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv() && keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BUTTON_Y) { showGuide(); return true; } @@ -612,7 +610,7 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { // up or down should close panel if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP) { hidePopupPanel(); - if (mPlaybackController.isLiveTv()) hide(); //also close this if live tv + if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) hide(); //also close this if live tv return true; } else { return false; @@ -620,22 +618,22 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { } // Control fast forward and rewind if overlay hidden and not showing live TV - if (!mPlaybackController.isLiveTv()) { + if (!playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) { if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD || keyCode == KeyEvent.KEYCODE_BUTTON_R1 || keyCode == KeyEvent.KEYCODE_BUTTON_R2) { - mPlaybackController.fastForward(); + playbackControllerContainer.getValue().getPlaybackController().fastForward(); setFadingEnabled(true); return true; } if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND || keyCode == KeyEvent.KEYCODE_BUTTON_L1 || keyCode == KeyEvent.KEYCODE_BUTTON_L2) { - mPlaybackController.rewind(); + playbackControllerContainer.getValue().getPlaybackController().rewind(); setFadingEnabled(true); return true; } } if (!mIsVisible) { - if (!mPlaybackController.isLiveTv()) { + if (!playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) { if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { setFadingEnabled(true); return true; @@ -648,10 +646,10 @@ public boolean onKey(View v, int keyCode, KeyEvent event) { } if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) - && mPlaybackController.canSeek()) { + && playbackControllerContainer.getValue().getPlaybackController().canSeek()) { // if the player is playing and the overlay is hidden, this will pause // if the player is paused and then 'back' is pressed to hide the overlay, this will play - mPlaybackController.playPause(); + playbackControllerContainer.getValue().getPlaybackController().playPause(); return true; } @@ -688,12 +686,12 @@ public void switchChannel(String id) { public void switchChannel(String id, boolean hideGuide) { if (Utils.isEmpty(id)) return; - if (mPlaybackController.getCurrentlyPlayingItem().getId().equals(id)) { + if (playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem().getId().equals(id)) { // same channel, just dismiss overlay if (hideGuide) hideGuide(); } else { - mPlaybackController.stop(); + playbackControllerContainer.getValue().getPlaybackController().stop(); if (hideGuide) hideGuide(); apiClient.getValue().GetItemAsync(id, KoinJavaComponent.get(UserRepository.class).getCurrentUser().getValue().getId().toString(), new LifecycleAwareResponse(getLifecycle()) { @@ -703,8 +701,8 @@ public void onResponse(BaseItemDto response) { List items = new ArrayList(); items.add(ModelCompat.asSdk(response)); - mPlaybackController.setItems(items); - mPlaybackController.play(0); + playbackControllerContainer.getValue().getPlaybackController().setItems(items); + playbackControllerContainer.getValue().getPlaybackController().play(0); } @Override @@ -729,7 +727,7 @@ public void onResume() { super.onResume(); // Close player when resuming without a valid playback contoller - if (!mPlaybackController.hasFragment()) { + if (!playbackControllerContainer.getValue().getPlaybackController().hasFragment()) { if (navigationRepository.getValue().getCanGoBack()) { navigationRepository.getValue().goBack(); } else { @@ -774,9 +772,9 @@ public void onStop() { // end playback from here if this fragment belongs to the current session. // if it doesn't, playback has already been stopped elsewhere, and the references to this have been replaced - if (mPlaybackController != null && mPlaybackController.getFragment() == this) { + if (playbackControllerContainer.getValue().getPlaybackController() != null && playbackControllerContainer.getValue().getPlaybackController().getFragment() == this) { Timber.d("this fragment belongs to the current session, ending it"); - mPlaybackController.endPlayback(); + playbackControllerContainer.getValue().getPlaybackController().endPlayback(); } // Reset display mode back to "no preference" @@ -812,7 +810,7 @@ public void showGuide() { hide(); leanbackOverlayFragment.setShouldShowOverlay(false); leanbackOverlayFragment.hideOverlay(); - mPlaybackController.mVideoManager.contractVideo(Utils.convertDpToPixel(requireContext(), 300)); + playbackControllerContainer.getValue().getPlaybackController().mVideoManager.contractVideo(Utils.convertDpToPixel(requireContext(), 300)); tvGuideBinding.getRoot().setVisibility(View.VISIBLE); mGuideVisible = true; Calendar now = Calendar.getInstance(); @@ -831,7 +829,7 @@ public void showGuide() { private void hideGuide() { tvGuideBinding.getRoot().setVisibility(View.GONE); - mPlaybackController.mVideoManager.setVideoFullSize(true); + playbackControllerContainer.getValue().getPlaybackController().mVideoManager.setVideoFullSize(true); mGuideVisible = false; } @@ -904,7 +902,7 @@ protected void onPreExecute() { Timber.d("*** Display programs pre-execute"); tvGuideBinding.channels.removeAllViews(); tvGuideBinding.programRows.removeAllViews(); - mFirstFocusChannelId = mPlaybackController.getCurrentlyPlayingItem().getId().toString(); + mFirstFocusChannelId = playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem().getId().toString(); if (mCurrentDisplayChannelStartNdx > 0) { // Show a paging row for channels above @@ -1238,7 +1236,7 @@ public void showChapterSelector() { mHandler.postDelayed(() -> { if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) return; - int ndx = getCurrentChapterIndex(mPlaybackController.getCurrentlyPlayingItem(), mPlaybackController.getCurrentPosition() * 10000); + int ndx = getCurrentChapterIndex(playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem(), playbackControllerContainer.getValue().getPlaybackController().getCurrentPosition() * 10000); if (ndx > 0) { mPopupRowPresenter.setPosition(ndx); } @@ -1303,7 +1301,7 @@ public void onResponse() { if (!getActive()) return; Utils.showToast(requireContext(), R.string.msg_recording_cancelled); - mPlaybackController.updateTvProgramInfo(); + playbackControllerContainer.getValue().getPlaybackController().updateTvProgramInfo(); TvManager.forceReload(); } @@ -1321,7 +1319,7 @@ public void onResponse() { if (!getActive()) return; Utils.showToast(requireContext(), R.string.msg_recording_cancelled); - mPlaybackController.updateTvProgramInfo(); + playbackControllerContainer.getValue().getPlaybackController().updateTvProgramInfo(); TvManager.forceReload(); } @@ -1351,7 +1349,7 @@ public void onResponse() { if (!getActive()) return; Utils.showToast(requireContext(), R.string.msg_set_to_record); - mPlaybackController.updateTvProgramInfo(); + playbackControllerContainer.getValue().getPlaybackController().updateTvProgramInfo(); TvManager.forceReload(); } @@ -1369,7 +1367,7 @@ public void onResponse() { if (!getActive()) return; Utils.showToast(requireContext(), R.string.msg_set_to_record); - mPlaybackController.updateTvProgramInfo(); + playbackControllerContainer.getValue().getPlaybackController().updateTvProgramInfo(); TvManager.forceReload(); } @@ -1409,7 +1407,7 @@ public void setPlayPauseActionState(final int state) { } public void updateDisplay() { - org.jellyfin.sdk.model.api.BaseItemDto current = mPlaybackController.getCurrentlyPlayingItem(); + org.jellyfin.sdk.model.api.BaseItemDto current = playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem(); if (current != null && getContext() != null) { leanbackOverlayFragment.mediaInfoChanged(); leanbackOverlayFragment.onFullyInitialized(); @@ -1437,7 +1435,7 @@ public void updateDisplay() { binding.itemTitle.setVisibility(View.VISIBLE); } - if (mPlaybackController.isLiveTv()) { + if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) { prepareChannelAdapter(); } else { prepareChapterAdapter(); @@ -1446,7 +1444,7 @@ public void updateDisplay() { } private void prepareChapterAdapter() { - org.jellyfin.sdk.model.api.BaseItemDto item = mPlaybackController.getCurrentlyPlayingItem(); + org.jellyfin.sdk.model.api.BaseItemDto item = playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem(); List chapters = item.getChapters(); if (chapters != null && !chapters.isEmpty()) { diff --git a/app/src/main/java/org/jellyfin/androidtv/ui/playback/overlay/LeanbackOverlayFragment.java b/app/src/main/java/org/jellyfin/androidtv/ui/playback/overlay/LeanbackOverlayFragment.java index 3e978b91e6..bdeaa705e5 100644 --- a/app/src/main/java/org/jellyfin/androidtv/ui/playback/overlay/LeanbackOverlayFragment.java +++ b/app/src/main/java/org/jellyfin/androidtv/ui/playback/overlay/LeanbackOverlayFragment.java @@ -11,10 +11,9 @@ import org.jellyfin.androidtv.ui.playback.PlaybackControllerContainer; import kotlin.Lazy; +import timber.log.Timber; public class LeanbackOverlayFragment extends PlaybackSupportFragment { - - private PlaybackController playbackController; private CustomPlaybackTransportControlGlue playerGlue; private VideoPlayerAdapter playerAdapter; private boolean shouldShowOverlay = true; @@ -27,14 +26,17 @@ public void onCreate(Bundle savedInstanceState) { setBackgroundType(BG_LIGHT); PlaybackController playbackController = playbackControllerContainer.getValue().getPlaybackController(); + if (playbackController == null) { + Timber.w("PlaybackController is null, skipping initialization."); + return; + } playerAdapter = new VideoPlayerAdapter(playbackController, this); playerGlue = new CustomPlaybackTransportControlGlue(getContext(), playerAdapter, playbackController); playerGlue.setHost(new CustomPlaybackFragmentGlueHost(this)); } - public void initFromView(PlaybackController playbackController, CustomPlaybackOverlayFragment customPlaybackOverlayFragment) { - this.playbackController = playbackController; + public void initFromView(CustomPlaybackOverlayFragment customPlaybackOverlayFragment) { playerGlue.setInitialPlaybackDrawable(); playerAdapter.setMasterOverlayFragment(customPlaybackOverlayFragment); } @@ -69,7 +71,7 @@ public void setFading(boolean fadingEnabled) { } public void mediaInfoChanged() { - org.jellyfin.sdk.model.api.BaseItemDto currentlyPlayingItem = playbackController.getCurrentlyPlayingItem(); + org.jellyfin.sdk.model.api.BaseItemDto currentlyPlayingItem = playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem(); if (currentlyPlayingItem == null) return; playerGlue.invalidatePlaybackControls();