2021-09-21 19:01:10 +00:00
|
|
|
package org.schabi.newpipe.fragments.detail;
|
|
|
|
|
2022-05-27 22:39:02 +00:00
|
|
|
import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW;
|
|
|
|
import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_DECODING_FAILED;
|
|
|
|
import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_UNSPECIFIED;
|
|
|
|
|
2021-09-21 19:01:10 +00:00
|
|
|
import android.content.Context;
|
|
|
|
import android.util.Log;
|
2022-07-15 02:43:08 +00:00
|
|
|
import android.util.Pair;
|
2021-09-21 19:01:10 +00:00
|
|
|
import android.view.ContextThemeWrapper;
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import android.widget.RadioButton;
|
|
|
|
import android.widget.RadioGroup;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull;
|
2021-11-28 12:42:26 +00:00
|
|
|
import androidx.annotation.Nullable;
|
2021-09-21 19:01:10 +00:00
|
|
|
import androidx.appcompat.app.AlertDialog;
|
|
|
|
|
2021-11-23 19:21:59 +00:00
|
|
|
import com.google.android.exoplayer2.C;
|
2021-09-21 19:01:10 +00:00
|
|
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
2022-03-13 05:22:47 +00:00
|
|
|
import com.google.android.exoplayer2.PlaybackException;
|
2021-09-21 19:01:10 +00:00
|
|
|
|
|
|
|
import org.schabi.newpipe.R;
|
|
|
|
import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
|
|
|
|
import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding;
|
|
|
|
import org.schabi.newpipe.player.Player;
|
|
|
|
import org.schabi.newpipe.util.ThemeHelper;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
2022-07-15 02:43:08 +00:00
|
|
|
import java.util.List;
|
2021-09-21 19:01:10 +00:00
|
|
|
import java.util.function.Supplier;
|
|
|
|
|
2021-10-01 16:44:47 +00:00
|
|
|
/**
|
|
|
|
* Outsourced logic for crashing the player in the {@link VideoDetailFragment}.
|
|
|
|
*/
|
2021-11-23 19:11:36 +00:00
|
|
|
public final class VideoDetailPlayerCrasher {
|
2021-09-21 19:01:10 +00:00
|
|
|
|
2021-10-01 16:44:47 +00:00
|
|
|
// This has to be <= 23 chars on devices running Android 7 or lower (API <= 25)
|
|
|
|
// or it fails with an IllegalArgumentException
|
|
|
|
// https://stackoverflow.com/a/54744028
|
2021-09-21 19:01:10 +00:00
|
|
|
private static final String TAG = "VideoDetPlayerCrasher";
|
|
|
|
|
2022-07-15 02:43:08 +00:00
|
|
|
private static final String DEFAULT_MSG = "Dummy";
|
|
|
|
|
|
|
|
private static final List<Pair<String, Supplier<ExoPlaybackException>>>
|
|
|
|
AVAILABLE_EXCEPTION_TYPES = List.of(
|
|
|
|
new Pair<>("Source", () -> ExoPlaybackException.createForSource(
|
|
|
|
new IOException(DEFAULT_MSG),
|
|
|
|
ERROR_CODE_BEHIND_LIVE_WINDOW
|
|
|
|
)),
|
|
|
|
new Pair<>("Renderer", () -> ExoPlaybackException.createForRenderer(
|
|
|
|
new Exception(DEFAULT_MSG),
|
|
|
|
"Dummy renderer",
|
|
|
|
0,
|
|
|
|
null,
|
|
|
|
C.FORMAT_HANDLED,
|
|
|
|
/*isRecoverable=*/false,
|
|
|
|
ERROR_CODE_DECODING_FAILED
|
|
|
|
)),
|
|
|
|
new Pair<>("Unexpected", () -> ExoPlaybackException.createForUnexpected(
|
|
|
|
new RuntimeException(DEFAULT_MSG),
|
|
|
|
ERROR_CODE_UNSPECIFIED
|
|
|
|
)),
|
|
|
|
new Pair<>("Remote", () -> ExoPlaybackException.createForRemote(DEFAULT_MSG))
|
|
|
|
);
|
2021-09-21 19:01:10 +00:00
|
|
|
|
2021-11-23 19:11:36 +00:00
|
|
|
private VideoDetailPlayerCrasher() {
|
|
|
|
// No impls
|
2021-09-21 19:01:10 +00:00
|
|
|
}
|
|
|
|
|
2021-11-23 19:11:36 +00:00
|
|
|
private static Context getThemeWrapperContext(final Context context) {
|
2021-09-21 19:01:10 +00:00
|
|
|
return new ContextThemeWrapper(
|
2021-11-23 19:11:36 +00:00
|
|
|
context,
|
|
|
|
ThemeHelper.isLightThemeSelected(context)
|
2021-09-21 19:01:10 +00:00
|
|
|
? R.style.LightTheme
|
|
|
|
: R.style.DarkTheme);
|
|
|
|
}
|
|
|
|
|
2021-11-28 12:42:26 +00:00
|
|
|
public static void onCrashThePlayer(
|
|
|
|
@NonNull final Context context,
|
2022-05-27 22:39:02 +00:00
|
|
|
@Nullable final Player player
|
2021-11-28 12:42:26 +00:00
|
|
|
) {
|
|
|
|
if (player == null) {
|
2021-09-21 19:01:10 +00:00
|
|
|
Log.d(TAG, "Player is not available");
|
2021-11-23 19:11:36 +00:00
|
|
|
Toast.makeText(context, "Player is not available", Toast.LENGTH_SHORT)
|
2021-09-21 19:01:10 +00:00
|
|
|
.show();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-10-01 16:44:47 +00:00
|
|
|
// -- Build the dialog/UI --
|
2021-11-23 19:11:36 +00:00
|
|
|
final Context themeWrapperContext = getThemeWrapperContext(context);
|
2021-09-21 19:01:10 +00:00
|
|
|
final LayoutInflater inflater = LayoutInflater.from(themeWrapperContext);
|
|
|
|
|
2022-05-27 22:39:02 +00:00
|
|
|
final SingleChoiceDialogViewBinding binding =
|
|
|
|
SingleChoiceDialogViewBinding.inflate(inflater);
|
|
|
|
|
|
|
|
final AlertDialog alertDialog = new AlertDialog.Builder(themeWrapperContext)
|
2021-09-21 19:01:10 +00:00
|
|
|
.setTitle("Choose an exception")
|
2022-05-27 22:39:02 +00:00
|
|
|
.setView(binding.getRoot())
|
2021-09-21 19:01:10 +00:00
|
|
|
.setCancelable(true)
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
.create();
|
|
|
|
|
2022-07-15 02:43:08 +00:00
|
|
|
for (final Pair<String, Supplier<ExoPlaybackException>> entry : AVAILABLE_EXCEPTION_TYPES) {
|
2021-09-21 19:01:10 +00:00
|
|
|
final RadioButton radioButton = ListRadioIconItemBinding.inflate(inflater).getRoot();
|
2022-07-15 02:43:08 +00:00
|
|
|
radioButton.setText(entry.first);
|
2021-09-21 19:01:10 +00:00
|
|
|
radioButton.setChecked(false);
|
|
|
|
radioButton.setLayoutParams(
|
|
|
|
new RadioGroup.LayoutParams(
|
|
|
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
|
|
)
|
|
|
|
);
|
|
|
|
radioButton.setOnClickListener(v -> {
|
2022-07-15 02:43:08 +00:00
|
|
|
tryCrashPlayerWith(player, entry.second.get());
|
2022-05-27 22:39:02 +00:00
|
|
|
alertDialog.cancel();
|
2021-09-21 19:01:10 +00:00
|
|
|
});
|
2022-05-27 22:39:02 +00:00
|
|
|
binding.list.addView(radioButton);
|
2021-09-21 19:01:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
alertDialog.show();
|
|
|
|
}
|
|
|
|
|
2021-09-21 19:18:54 +00:00
|
|
|
/**
|
|
|
|
* Note that this method does not crash the underlying exoplayer directly (it's not possible).
|
2022-03-13 05:22:47 +00:00
|
|
|
* It simply supplies a Exception to {@link Player#onPlayerError(PlaybackException)}.
|
2021-09-21 19:18:54 +00:00
|
|
|
* @param player
|
|
|
|
* @param exception
|
|
|
|
*/
|
2021-11-23 19:11:36 +00:00
|
|
|
private static void tryCrashPlayerWith(
|
2021-09-21 19:01:10 +00:00
|
|
|
@NonNull final Player player,
|
|
|
|
@NonNull final ExoPlaybackException exception
|
|
|
|
) {
|
|
|
|
Log.d(TAG, "Crashing the player using player.onPlayerError(ex)");
|
|
|
|
try {
|
|
|
|
player.onPlayerError(exception);
|
|
|
|
} catch (final Exception exPlayer) {
|
|
|
|
Log.e(TAG,
|
|
|
|
"Run into an exception while crashing the player:",
|
|
|
|
exPlayer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|