From 0eeb47ee1e2ad4d2f91c1851480af80fcc364181 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 24 Oct 2021 12:33:45 +0200 Subject: [PATCH] Show actual error messages instead of just the error codes --- .../playback/CancelablePSMPCallback.java | 8 ----- .../service/playback/DefaultPSMPCallback.java | 5 --- .../PlaybackServiceMediaPlayerTest.java | 29 --------------- .../activity/VideoplayerActivity.java | 20 +++++------ .../fragment/AudioPlayerFragment.java | 36 +++++++++---------- .../core/event/PlayerErrorEvent.java | 13 +++++++ .../service/playback/ExoPlayerWrapper.java | 12 ++++--- .../core/service/playback/LocalPSMP.java | 12 +++++-- .../service/playback/PlaybackService.java | 25 ++++++------- .../playback/PlaybackServiceMediaPlayer.java | 2 -- .../util/playback/PlaybackController.java | 26 -------------- core/src/main/res/values/strings.xml | 1 - 12 files changed, 69 insertions(+), 120 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/PlayerErrorEvent.java diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/CancelablePSMPCallback.java b/app/src/androidTest/java/de/test/antennapod/service/playback/CancelablePSMPCallback.java index ae38fd5e7..30a84ecb9 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/CancelablePSMPCallback.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/CancelablePSMPCallback.java @@ -66,14 +66,6 @@ public class CancelablePSMPCallback implements PlaybackServiceMediaPlayer.PSMPCa return originalCallback.onMediaPlayerInfo(code, resourceId); } - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - if (isCancelled) { - return true; - } - return originalCallback.onMediaPlayerError(inObj, what, extra); - } - @Override public void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, boolean playingNext) { if (isCancelled) { diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/DefaultPSMPCallback.java b/app/src/androidTest/java/de/test/antennapod/service/playback/DefaultPSMPCallback.java index 29a854f20..167b1b55c 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/DefaultPSMPCallback.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/DefaultPSMPCallback.java @@ -37,11 +37,6 @@ public class DefaultPSMPCallback implements PlaybackServiceMediaPlayer.PSMPCallb return false; } - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - return false; - } - @Override public void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, boolean playingNext) { diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java index dfb0e3e36..87a5fa65c 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java @@ -514,13 +514,6 @@ public class PlaybackServiceMediaPlayerTest { if (assertionError == null) assertionError = new AssertionFailedError("Unexpected call to shouldStop"); } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - if (assertionError == null) - assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError"); - return false; - } }); PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL); @@ -604,14 +597,6 @@ public class PlaybackServiceMediaPlayerTest { } } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - if (assertionError == null) { - assertionError = new AssertionFailedError("Unexpected call of onMediaPlayerError"); - } - return false; - } }); PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); if (initialState == PlayerStatus.PREPARED || initialState == PlayerStatus.PLAYING || initialState == PlayerStatus.PAUSED) { @@ -664,13 +649,6 @@ public class PlaybackServiceMediaPlayerTest { } } } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - if (assertionError == null) - assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError"); - return false; - } }); PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL); @@ -738,13 +716,6 @@ public class PlaybackServiceMediaPlayerTest { } } } - - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - if (assertionError == null) - assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError"); - return false; - } }); PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback); Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java index d436acf0d..c35709f05 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java @@ -37,6 +37,7 @@ import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import com.bumptech.glide.Glide; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.event.PlaybackPositionEvent; +import de.danoeh.antennapod.core.event.PlayerErrorEvent; import de.danoeh.antennapod.core.event.ServiceEvent; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; @@ -50,7 +51,6 @@ import de.danoeh.antennapod.core.util.ShareUtils; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.TimeSpeedConverter; import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; -import de.danoeh.antennapod.core.util.playback.MediaPlayerError; import de.danoeh.antennapod.core.util.playback.PlaybackController; import de.danoeh.antennapod.databinding.VideoplayerActivityBinding; import de.danoeh.antennapod.dialog.PlaybackControlsDialog; @@ -207,15 +207,6 @@ public class VideoplayerActivity extends CastEnabledActivity implements SeekBar. viewBinding.sbPosition.setSecondaryProgress((int) (progress * viewBinding.sbPosition.getMax())); } - @Override - public void handleError(int code) { - final AlertDialog.Builder errorDialog = new AlertDialog.Builder(VideoplayerActivity.this); - errorDialog.setTitle(R.string.error_label); - errorDialog.setMessage(MediaPlayerError.getErrorString(VideoplayerActivity.this, code)); - errorDialog.setNeutralButton(android.R.string.ok, (dialog, which) -> finish()); - errorDialog.show(); - } - @Override public void onReloadNotification(int code) { VideoplayerActivity.this.onReloadNotification(code); @@ -550,6 +541,15 @@ public class VideoplayerActivity extends CastEnabledActivity implements SeekBar. } } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMediaPlayerError(PlayerErrorEvent event) { + final AlertDialog.Builder errorDialog = new AlertDialog.Builder(VideoplayerActivity.this); + errorDialog.setTitle(R.string.error_label); + errorDialog.setMessage(event.getMessage()); + errorDialog.setNeutralButton(android.R.string.ok, (dialog, which) -> finish()); + errorDialog.show(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java index 168133c7a..eef2c0fff 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java @@ -25,6 +25,7 @@ import androidx.viewpager2.widget.ViewPager2; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.snackbar.Snackbar; +import de.danoeh.antennapod.core.event.PlayerErrorEvent; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -50,7 +51,6 @@ import de.danoeh.antennapod.core.util.ChapterUtils; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.TimeSpeedConverter; -import de.danoeh.antennapod.core.util.playback.MediaPlayerError; import de.danoeh.antennapod.model.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; import de.danoeh.antennapod.dialog.PlaybackControlsDialog; @@ -300,23 +300,6 @@ public class AudioPlayerFragment extends Fragment implements } } - @Override - public void handleError(int code) { - final AlertDialog.Builder errorDialog = new AlertDialog.Builder(getContext()); - errorDialog.setTitle(R.string.error_label); - errorDialog.setMessage(MediaPlayerError.getErrorString(getContext(), code)); - errorDialog.setPositiveButton(android.R.string.ok, (dialog, which) -> - ((MainActivity) getActivity()).getBottomSheet().setState(BottomSheetBehavior.STATE_COLLAPSED)); - if (!UserPreferences.useExoplayer()) { - errorDialog.setNeutralButton(R.string.media_player_switch_to_exoplayer, (dialog, which) -> { - UserPreferences.enableExoplayer(); - ((MainActivity) getActivity()).showSnackbarAbovePlayer( - R.string.media_player_switched_to_exoplayer, Snackbar.LENGTH_LONG); - }); - } - errorDialog.create().show(); - } - @Override public void onSleepTimerUpdate() { AudioPlayerFragment.this.loadMediaInfo(false); @@ -419,6 +402,23 @@ public class AudioPlayerFragment extends Fragment implements AudioPlayerFragment.this.loadMediaInfo(false); } + @Subscribe(threadMode = ThreadMode.MAIN) + public void mediaPlayerError(PlayerErrorEvent event) { + final AlertDialog.Builder errorDialog = new AlertDialog.Builder(getContext()); + errorDialog.setTitle(R.string.error_label); + errorDialog.setMessage(event.getMessage()); + errorDialog.setPositiveButton(android.R.string.ok, (dialog, which) -> + ((MainActivity) getActivity()).getBottomSheet().setState(BottomSheetBehavior.STATE_COLLAPSED)); + if (!UserPreferences.useExoplayer()) { + errorDialog.setNeutralButton(R.string.media_player_switch_to_exoplayer, (dialog, which) -> { + UserPreferences.enableExoplayer(); + ((MainActivity) getActivity()).showSnackbarAbovePlayer( + R.string.media_player_switched_to_exoplayer, Snackbar.LENGTH_LONG); + }); + } + errorDialog.create().show(); + } + @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (controller == null || txtvLength == null) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/PlayerErrorEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/PlayerErrorEvent.java new file mode 100644 index 000000000..2fb27e958 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/PlayerErrorEvent.java @@ -0,0 +1,13 @@ +package de.danoeh.antennapod.core.event; + +public class PlayerErrorEvent { + private final String message; + + public PlayerErrorEvent(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java index 0a9bf5f43..30e76787d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java @@ -5,6 +5,8 @@ import android.net.Uri; import android.text.TextUtils; import android.util.Log; import android.view.SurfaceHolder; +import androidx.annotation.NonNull; +import androidx.core.util.Consumer; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.DefaultRenderersFactory; @@ -54,7 +56,7 @@ public class ExoPlayerWrapper implements IPlayer { private MediaSource mediaSource; private MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener; private MediaPlayer.OnCompletionListener audioCompletionListener; - private MediaPlayer.OnErrorListener audioErrorListener; + private Consumer audioErrorListener; private MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener; private PlaybackParameters playbackParameters; private MediaPlayer.OnInfoListener infoListener; @@ -98,9 +100,11 @@ public class ExoPlayerWrapper implements IPlayer { } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(@NonNull ExoPlaybackException error) { if (audioErrorListener != null) { - audioErrorListener.onError(null, error.type + ERROR_CODE_OFFSET, 0); + Throwable cause = error.getCause(); + audioErrorListener.accept(cause != null + ? cause.getLocalizedMessage() : error.getLocalizedMessage()); } } @@ -323,7 +327,7 @@ public class ExoPlayerWrapper implements IPlayer { this.audioSeekCompleteListener = audioSeekCompleteListener; } - void setOnErrorListener(MediaPlayer.OnErrorListener audioErrorListener) { + void setOnErrorListener(Consumer audioErrorListener) { this.audioErrorListener = audioErrorListener; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index f74e3b9ad..90b3b6ae2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -14,7 +14,9 @@ import android.view.SurfaceHolder; import androidx.media.AudioAttributesCompat; import androidx.media.AudioFocusRequestCompat; import androidx.media.AudioManagerCompat; +import de.danoeh.antennapod.core.event.PlayerErrorEvent; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.util.playback.MediaPlayerError; import org.antennapod.audio.MediaPlayer; import java.io.File; @@ -41,6 +43,7 @@ import de.danoeh.antennapod.core.util.playback.IPlayer; import de.danoeh.antennapod.model.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter; import de.danoeh.antennapod.core.util.playback.VideoPlayer; +import org.greenrobot.eventbus.EventBus; /** * Manages the MediaPlayer object of the PlaybackService. @@ -294,6 +297,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } catch (IOException | IllegalStateException e) { e.printStackTrace(); setPlayerStatus(PlayerStatus.ERROR, null); + EventBus.getDefault().postSticky(new PlayerErrorEvent(e.getLocalizedMessage())); } } @@ -402,6 +406,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } catch (IOException e) { e.printStackTrace(); setPlayerStatus(PlayerStatus.ERROR, null); + EventBus.getDefault().postSticky(new PlayerErrorEvent(e.getLocalizedMessage())); } } playerLock.unlock(); @@ -734,7 +739,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { ap.setOnErrorListener((mediaPlayer, i, i1) -> true); } else if (mediaPlayer instanceof ExoPlayerWrapper) { ExoPlayerWrapper ap = (ExoPlayerWrapper) mediaPlayer; - ap.setOnErrorListener((mediaPlayer, i, i1) -> true); + ap.setOnErrorListener(message -> { }); } } @@ -1033,7 +1038,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { ap.setOnCompletionListener(audioCompletionListener); ap.setOnSeekCompleteListener(audioSeekCompleteListener); ap.setOnBufferingUpdateListener(audioBufferingUpdateListener); - ap.setOnErrorListener(audioErrorListener); + ap.setOnErrorListener(message -> EventBus.getDefault().postSticky(new PlayerErrorEvent(message))); ap.setOnInfoListener(audioInfoListener); } else { Log.w(TAG, "Unknown media player: " + mp); @@ -1084,7 +1089,8 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { private final android.media.MediaPlayer.OnErrorListener videoErrorListener = this::genericOnError; private boolean genericOnError(Object inObj, int what, int extra) { - return callback.onMediaPlayerError(inObj, what, extra); + EventBus.getDefault().postSticky(new PlayerErrorEvent(MediaPlayerError.getErrorString(context, what))); + return true; } private final MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener = diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index d1dcd463a..49a4fb021 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -43,6 +43,7 @@ import androidx.core.app.NotificationManagerCompat; import androidx.media.MediaBrowserServiceCompat; import androidx.preference.PreferenceManager; +import de.danoeh.antennapod.core.event.PlayerErrorEvent; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -161,7 +162,6 @@ public class PlaybackService extends MediaBrowserServiceCompat { public static final int EXTRA_CODE_VIDEO = 2; public static final int EXTRA_CODE_CAST = 3; - public static final int NOTIFICATION_TYPE_ERROR = 0; public static final int NOTIFICATION_TYPE_BUFFER_UPDATE = 2; /** @@ -938,19 +938,6 @@ public class PlaybackService extends MediaBrowserServiceCompat { } } - @Override - public boolean onMediaPlayerError(Object inObj, int what, int extra) { - final String TAG = "PlaybackSvc.onErrorLtsn"; - Log.w(TAG, "An error has occured: " + what + " " + extra); - if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { - mediaPlayer.pause(true, false); - } - sendNotificationBroadcast(NOTIFICATION_TYPE_ERROR, what); - PlaybackPreferences.writeNoMediaPlaying(); - stateManager.stopService(); - return true; - } - @Override public void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, boolean playingNext) { @@ -996,6 +983,16 @@ public class PlaybackService extends MediaBrowserServiceCompat { } }; + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressWarnings("unused") + public void playerError(PlayerErrorEvent event) { + if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { + mediaPlayer.pause(true, false); + } + PlaybackPreferences.writeNoMediaPlaying(); + stateManager.stopService(); + } + private Playable getNextInQueue(final Playable currentMedia) { if (!(currentMedia instanceof FeedMedia)) { Log.d(TAG, "getNextInQueue(), but playable not an instance of FeedMedia, so not proceeding"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index e093383b9..2aeb84cb0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -356,8 +356,6 @@ public abstract class PlaybackServiceMediaPlayer { boolean onMediaPlayerInfo(int code, @StringRes int resourceId); - boolean onMediaPlayerError(Object inObj, int what, int extra); - void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, boolean playingNext); void onPlaybackStart(@NonNull Playable playable, int position); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index 7f4c1ceaf..ec74b2fe3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -7,14 +7,11 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; -import android.media.MediaPlayer; import android.os.IBinder; import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; import androidx.annotation.NonNull; -import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.event.ServiceEvent; import de.danoeh.antennapod.model.playback.MediaType; import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils; @@ -209,9 +206,6 @@ public abstract class PlaybackController { return; } switch (type) { - case PlaybackService.NOTIFICATION_TYPE_ERROR: - handleError(code); - break; case PlaybackService.NOTIFICATION_TYPE_BUFFER_UPDATE: float progress = ((float) code) / 100; onBufferUpdate(progress); @@ -264,8 +258,6 @@ public abstract class PlaybackController { public void onSleepTimerUpdate() {} - public void handleError(int code) {} - public void onPlaybackEnd() {} /** @@ -276,10 +268,6 @@ public abstract class PlaybackController { Log.d(TAG, "status: " + status.toString()); checkMediaInfoLoaded(); switch (status) { - case ERROR: - EventBus.getDefault().post(new MessageEvent(activity.getString(R.string.player_error_msg))); - handleError(MediaPlayer.MEDIA_ERROR_UNKNOWN); - break; case PAUSED: onPositionObserverUpdate(); updatePlayButtonShowsPlay(true); @@ -555,20 +543,6 @@ public abstract class PlaybackController { } } - /** - * Move service into INITIALIZED state if it's paused to save bandwidth - */ - public void reinitServiceIfPaused() { - if (playbackService != null - && playbackService.isStreaming() - && !PlaybackService.isCasting() - && (playbackService.getStatus() == PlayerStatus.PAUSED || - (playbackService.getStatus() == PlayerStatus.PREPARING && - !playbackService.isStartWhenPrepared()))) { - playbackService.reinit(); - } - } - public boolean isStreaming() { return playbackService != null && playbackService.isStreaming(); } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5d86109c3..804bf7af8 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -295,7 +295,6 @@ Allow temporarily - Error! Server died Unsupported media type Operation timed out