mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-22 02:53:09 +01:00
Added a "Crash the player" debug option
This commit is contained in:
parent
e632fab4d0
commit
769791af7a
@ -205,6 +205,9 @@ public final class VideoDetailFragment
|
||||
private Player player;
|
||||
private final PlayerHolder playerHolder = PlayerHolder.getInstance();
|
||||
|
||||
@Nullable
|
||||
private VideoDetailPlayerCrasher videoDetailPlayerCrasher = null;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Service management
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@ -594,6 +597,18 @@ public final class VideoDetailFragment
|
||||
// Init
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull final View rootView, final Bundle savedInstanceState) {
|
||||
super.onViewCreated(rootView, savedInstanceState);
|
||||
|
||||
if (DEBUG) {
|
||||
this.videoDetailPlayerCrasher = new VideoDetailPlayerCrasher(
|
||||
() -> this.getContext(),
|
||||
() -> this.getLayoutInflater()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // called from onViewCreated in {@link BaseFragment#onViewCreated}
|
||||
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
||||
super.initViews(rootView, savedInstanceState);
|
||||
@ -604,6 +619,18 @@ public final class VideoDetailFragment
|
||||
|
||||
binding.detailThumbnailRootLayout.requestFocus();
|
||||
|
||||
binding.detailControlsPlayWithKodi.setVisibility(
|
||||
KoreUtils.shouldShowPlayWithKodi(requireContext(), serviceId)
|
||||
? View.VISIBLE
|
||||
: View.GONE
|
||||
);
|
||||
binding.detailControlsCrashThePlayer.setVisibility(
|
||||
DEBUG && PreferenceManager.getDefaultSharedPreferences(getContext())
|
||||
.getBoolean(getString(R.string.show_crash_the_player_key), false)
|
||||
? View.VISIBLE
|
||||
: View.GONE
|
||||
);
|
||||
|
||||
if (DeviceUtils.isTv(getContext())) {
|
||||
// remove ripple effects from detail controls
|
||||
final int transparent = ContextCompat.getColor(requireContext(),
|
||||
@ -638,8 +665,10 @@ public final class VideoDetailFragment
|
||||
binding.detailControlsShare.setOnClickListener(this);
|
||||
binding.detailControlsOpenInBrowser.setOnClickListener(this);
|
||||
binding.detailControlsPlayWithKodi.setOnClickListener(this);
|
||||
binding.detailControlsPlayWithKodi.setVisibility(KoreUtils.shouldShowPlayWithKodi(
|
||||
requireContext(), serviceId) ? View.VISIBLE : View.GONE);
|
||||
if (DEBUG) {
|
||||
binding.detailControlsCrashThePlayer.setOnClickListener(
|
||||
v -> videoDetailPlayerCrasher.onCrashThePlayer(this.player));
|
||||
}
|
||||
|
||||
binding.overlayThumbnail.setOnClickListener(this);
|
||||
binding.overlayThumbnail.setOnLongClickListener(this);
|
||||
|
@ -0,0 +1,165 @@
|
||||
package org.schabi.newpipe.fragments.detail;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
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;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.RendererCapabilities;
|
||||
|
||||
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;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class VideoDetailPlayerCrasher {
|
||||
|
||||
private static final String TAG = "VideoDetPlayerCrasher";
|
||||
|
||||
@NonNull
|
||||
private final Supplier<Context> contextSupplier;
|
||||
@NonNull
|
||||
private final Supplier<LayoutInflater> layoutInflaterSupplier;
|
||||
|
||||
public VideoDetailPlayerCrasher(
|
||||
@NonNull final Supplier<Context> contextSupplier,
|
||||
@NonNull final Supplier<LayoutInflater> layoutInflaterSupplier
|
||||
) {
|
||||
this.contextSupplier = contextSupplier;
|
||||
this.layoutInflaterSupplier = layoutInflaterSupplier;
|
||||
}
|
||||
|
||||
private static Map<String, Supplier<ExoPlaybackException>> getExceptionTypes() {
|
||||
final String defaultMsg = "Dummy";
|
||||
final Map<String, Supplier<ExoPlaybackException>> exceptionTypes = new LinkedHashMap<>();
|
||||
exceptionTypes.put(
|
||||
"Source",
|
||||
() -> ExoPlaybackException.createForSource(
|
||||
new IOException(defaultMsg)
|
||||
)
|
||||
);
|
||||
exceptionTypes.put(
|
||||
"Renderer",
|
||||
() -> ExoPlaybackException.createForRenderer(
|
||||
new Exception(defaultMsg),
|
||||
"Dummy renderer",
|
||||
0,
|
||||
null,
|
||||
RendererCapabilities.FORMAT_HANDLED
|
||||
)
|
||||
);
|
||||
exceptionTypes.put(
|
||||
"Unexpected",
|
||||
() -> ExoPlaybackException.createForUnexpected(
|
||||
new RuntimeException(defaultMsg)
|
||||
)
|
||||
);
|
||||
exceptionTypes.put(
|
||||
"Remote",
|
||||
() -> ExoPlaybackException.createForRemote(defaultMsg)
|
||||
);
|
||||
exceptionTypes.put(
|
||||
"Timeout",
|
||||
() -> ExoPlaybackException.createForTimeout(
|
||||
new TimeoutException(defaultMsg),
|
||||
ExoPlaybackException.TIMEOUT_OPERATION_UNDEFINED
|
||||
)
|
||||
);
|
||||
|
||||
return exceptionTypes;
|
||||
}
|
||||
|
||||
private Context getContext() {
|
||||
return this.contextSupplier.get();
|
||||
}
|
||||
|
||||
private LayoutInflater getLayoutInflater() {
|
||||
return this.layoutInflaterSupplier.get();
|
||||
}
|
||||
|
||||
private Context getThemeWrapperContext() {
|
||||
return new ContextThemeWrapper(
|
||||
getContext(),
|
||||
ThemeHelper.isLightThemeSelected(getContext())
|
||||
? R.style.LightTheme
|
||||
: R.style.DarkTheme);
|
||||
}
|
||||
|
||||
public void onCrashThePlayer(final Player player) {
|
||||
if (!isPlayerAvailable(player)) {
|
||||
Log.d(TAG, "Player is not available");
|
||||
Toast.makeText(getContext(), "Player is not available", Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final Context themeWrapperContext = getThemeWrapperContext();
|
||||
|
||||
final LayoutInflater inflater = LayoutInflater.from(themeWrapperContext);
|
||||
final RadioGroup radioGroup = SingleChoiceDialogViewBinding.inflate(getLayoutInflater())
|
||||
.list;
|
||||
|
||||
final AlertDialog alertDialog = new AlertDialog.Builder(getThemeWrapperContext())
|
||||
.setTitle("Choose an exception")
|
||||
.setView(radioGroup)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create();
|
||||
|
||||
for (final Map.Entry<String, Supplier<ExoPlaybackException>> entry
|
||||
: getExceptionTypes().entrySet()) {
|
||||
final RadioButton radioButton = ListRadioIconItemBinding.inflate(inflater).getRoot();
|
||||
radioButton.setText(entry.getKey());
|
||||
radioButton.setChecked(false);
|
||||
radioButton.setLayoutParams(
|
||||
new RadioGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
);
|
||||
radioButton.setOnClickListener(v -> {
|
||||
tryCrashPlayerWith(player, entry.getValue().get());
|
||||
if (alertDialog != null) {
|
||||
alertDialog.cancel();
|
||||
}
|
||||
});
|
||||
radioGroup.addView(radioButton);
|
||||
}
|
||||
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
private void tryCrashPlayerWith(
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPlayerAvailable(final Player player) {
|
||||
return player != null;
|
||||
}
|
||||
}
|
@ -213,7 +213,7 @@
|
||||
android:layout_below="@id/detail_title_root_layout"
|
||||
android:layout_marginTop="@dimen/video_item_detail_error_panel_margin"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="gone" />
|
||||
|
||||
<!--HIDING ROOT-->
|
||||
<LinearLayout
|
||||
@ -547,6 +547,22 @@
|
||||
android:textSize="@dimen/detail_control_text_size"
|
||||
app:drawableTopCompat="@drawable/ic_cast" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_controls_crash_the_player"
|
||||
android:layout_width="@dimen/detail_control_width"
|
||||
android:layout_height="@dimen/detail_control_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/crash_the_player"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="@dimen/detail_control_padding"
|
||||
android:text="@string/crash_the_player"
|
||||
android:textSize="@dimen/detail_control_text_size"
|
||||
app:drawableTopCompat="@drawable/ic_bug_report" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
|
@ -190,6 +190,7 @@
|
||||
<string name="disable_media_tunneling_key" translatable="false">disable_media_tunneling_key</string>
|
||||
<string name="crash_the_app_key" translatable="false">crash_the_app_key</string>
|
||||
<string name="show_image_indicators_key" translatable="false">show_image_indicators_key</string>
|
||||
<string name="show_crash_the_player_key" translatable="false">show_crash_the_player_key</string>
|
||||
|
||||
<!-- THEMES -->
|
||||
<string name="theme_key" translatable="false">theme</string>
|
||||
|
@ -52,6 +52,7 @@
|
||||
<string name="kore_package" translatable="false">org.xbmc.kore</string>
|
||||
<string name="show_play_with_kodi_title">Show \"Play with Kodi\" option</string>
|
||||
<string name="show_play_with_kodi_summary">Display an option to play a video via Kodi media center</string>
|
||||
<string name="crash_the_player">Crash the player</string>
|
||||
<string name="report_player_errors_title">Report player errors</string>
|
||||
<string name="report_player_errors_summary">Reports player errors in full detail instead of showing a short-lived toast message (useful for diagnosing problems)</string>
|
||||
<string name="notification_scale_to_square_image_title">Scale thumbnail to 1:1 aspect ratio</string>
|
||||
@ -475,6 +476,8 @@
|
||||
<string name="show_image_indicators_title">Show image indicators</string>
|
||||
<string name="show_image_indicators_summary">Show Picasso colored ribbons on top of images indicating their source: red for network, blue for disk and green for memory</string>
|
||||
<string name="crash_the_app">Crash the app</string>
|
||||
<string name="show_crash_the_player_title">Show \"crash the player\"</string>
|
||||
<string name="show_crash_the_player_summary">Shows a crash option when using the player</string>
|
||||
<!-- Subscriptions import/export -->
|
||||
<string name="import_title">Import</string>
|
||||
<string name="import_from">Import from</string>
|
||||
|
@ -54,4 +54,13 @@
|
||||
android:title="@string/crash_the_app"
|
||||
app:singleLineTitle="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:defaultValue="false"
|
||||
android:key="@string/show_crash_the_player_key"
|
||||
android:summary="@string/show_crash_the_player_summary"
|
||||
android:title="@string/show_crash_the_player_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceScreen>
|
||||
|
Loading…
Reference in New Issue
Block a user