Merge pull request #5485 from ByteHamster/media-player-errors

Show actual error messages instead of just the error codes
This commit is contained in:
ByteHamster 2021-10-24 17:55:02 +02:00 committed by GitHub
commit a4a9a0f4ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 69 additions and 120 deletions

View File

@ -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) {

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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<String> 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<String> audioErrorListener) {
this.audioErrorListener = audioErrorListener;
}

View File

@ -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 =

View File

@ -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");

View File

@ -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);

View File

@ -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();
}

View File

@ -295,7 +295,6 @@
<string name="confirm_mobile_download_dialog_enable_temporarily">Allow temporarily</string>
<!-- Mediaplayer messages -->
<string name="player_error_msg">Error!</string>
<string name="playback_error_server_died">Server died</string>
<string name="playback_error_unsupported">Unsupported media type</string>
<string name="playback_error_timeout">Operation timed out</string>