Skip to content

Commit 6a2dbc0

Browse files
committed
Add more specific error messages and deduplicate their handling
1 parent e9922fe commit 6a2dbc0

8 files changed

Lines changed: 52 additions & 79 deletions

File tree

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ dependencies {
214214
// the corresponding commit hash, since JitPack sometimes deletes artifacts.
215215
// If there’s already a git hash, just add more of it to the end (or remove a letter)
216216
// to cause jitpack to regenerate the artifact.
217-
implementation 'com.github.TeamNewPipe:NewPipeExtractor:7adbc48a0aa872c016b8ec089e278d5e12772054'
217+
implementation 'com.github.Stypox:NewPipeExtractor:1c04bd88c3f1e6b1e0c912814035745e61bb9aba'
218218
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'
219219

220220
/** Checkstyle **/

app/src/main/java/org/schabi/newpipe/RouterActivity.java

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,13 @@
5858
import org.schabi.newpipe.extractor.StreamingService;
5959
import org.schabi.newpipe.extractor.StreamingService.LinkType;
6060
import org.schabi.newpipe.extractor.channel.ChannelInfo;
61-
import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException;
6261
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
6362
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
6463
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
65-
import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException;
66-
import org.schabi.newpipe.extractor.exceptions.PaidContentException;
67-
import org.schabi.newpipe.extractor.exceptions.PrivateContentException;
6864
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
69-
import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException;
70-
import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException;
7165
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
7266
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
7367
import org.schabi.newpipe.extractor.stream.StreamInfo;
74-
import org.schabi.newpipe.ktx.ExceptionUtils;
7568
import org.schabi.newpipe.local.dialog.PlaylistDialog;
7669
import org.schabi.newpipe.player.PlayerType;
7770
import org.schabi.newpipe.player.helper.PlayerHelper;
@@ -279,28 +272,11 @@ private static void handleError(final Context context, final ErrorInfo errorInfo
279272
final Intent intent = new Intent(context, ReCaptchaActivity.class);
280273
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
281274
context.startActivity(intent);
282-
} else if (errorInfo.getThrowable() != null
283-
&& ExceptionUtils.isNetworkRelated(errorInfo.getThrowable())) {
284-
Toast.makeText(context, R.string.network_error, Toast.LENGTH_LONG).show();
285-
} else if (errorInfo.getThrowable() instanceof AgeRestrictedContentException) {
286-
Toast.makeText(context, R.string.restricted_video_no_stream,
287-
Toast.LENGTH_LONG).show();
288-
} else if (errorInfo.getThrowable() instanceof GeographicRestrictionException) {
289-
Toast.makeText(context, R.string.georestricted_content, Toast.LENGTH_LONG).show();
290-
} else if (errorInfo.getThrowable() instanceof PaidContentException) {
291-
Toast.makeText(context, R.string.paid_content, Toast.LENGTH_LONG).show();
292-
} else if (errorInfo.getThrowable() instanceof PrivateContentException) {
293-
Toast.makeText(context, R.string.private_content, Toast.LENGTH_LONG).show();
294-
} else if (errorInfo.getThrowable() instanceof SoundCloudGoPlusContentException) {
295-
Toast.makeText(context, R.string.soundcloud_go_plus_content,
296-
Toast.LENGTH_LONG).show();
297-
} else if (errorInfo.getThrowable() instanceof YoutubeMusicPremiumContentException) {
298-
Toast.makeText(context, R.string.youtube_music_premium_content,
299-
Toast.LENGTH_LONG).show();
300-
} else if (errorInfo.getThrowable() instanceof ContentNotAvailableException) {
301-
Toast.makeText(context, R.string.content_not_available, Toast.LENGTH_LONG).show();
302-
} else if (errorInfo.getThrowable() instanceof ContentNotSupportedException) {
303-
Toast.makeText(context, R.string.content_not_supported, Toast.LENGTH_LONG).show();
275+
} else if (errorInfo.getThrowable() instanceof ContentNotAvailableException
276+
|| errorInfo.getThrowable() instanceof ContentNotSupportedException) {
277+
// this exception does not usually indicate a problem that should be reported,
278+
// so just show a toast instead of the notification
279+
Toast.makeText(context, errorInfo.getMessageStringId(), Toast.LENGTH_LONG).show();
304280
} else {
305281
ErrorUtil.createNotification(context, errorInfo);
306282
}

app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,25 @@ package org.schabi.newpipe.error
33
import android.os.Parcelable
44
import androidx.annotation.StringRes
55
import com.google.android.exoplayer2.ExoPlaybackException
6+
import com.google.android.exoplayer2.upstream.HttpDataSource
7+
import com.google.android.exoplayer2.upstream.Loader
68
import kotlinx.parcelize.IgnoredOnParcel
79
import kotlinx.parcelize.Parcelize
810
import org.schabi.newpipe.R
911
import org.schabi.newpipe.extractor.Info
1012
import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException
13+
import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException
1114
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException
1215
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException
1316
import org.schabi.newpipe.extractor.exceptions.ExtractionException
17+
import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException
18+
import org.schabi.newpipe.extractor.exceptions.PaidContentException
19+
import org.schabi.newpipe.extractor.exceptions.PrivateContentException
20+
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
21+
import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException
22+
import org.schabi.newpipe.extractor.exceptions.UnsupportedContentInCountryException
23+
import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException
24+
import org.schabi.newpipe.extractor.exceptions.YoutubeSignInConfirmNotBotException
1425
import org.schabi.newpipe.ktx.isNetworkRelated
1526
import org.schabi.newpipe.util.ServiceHelper
1627

@@ -91,25 +102,44 @@ class ErrorInfo(
91102
action: UserAction
92103
): Int {
93104
return when {
105+
// content not available exceptions
94106
throwable is AccountTerminatedException -> R.string.account_terminated
107+
throwable is AgeRestrictedContentException -> R.string.restricted_video_no_stream
108+
throwable is GeographicRestrictionException -> R.string.georestricted_content
109+
throwable is PaidContentException -> R.string.paid_content
110+
throwable is PrivateContentException -> R.string.private_content
111+
throwable is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content
112+
throwable is UnsupportedContentInCountryException -> R.string.unsupported_content_in_country
113+
throwable is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content
114+
throwable is YoutubeSignInConfirmNotBotException -> R.string.youtube_sign_in_confirm_not_bot_error
95115
throwable is ContentNotAvailableException -> R.string.content_not_available
96-
throwable != null && throwable.isNetworkRelated -> R.string.network_error
116+
117+
// ReCaptchas should have already been handled elsewhere,
118+
// but return an error message here just in case
119+
throwable is ReCaptchaException -> R.string.recaptcha_request_toast
120+
121+
// other extractor exceptions
97122
throwable is ContentNotSupportedException -> R.string.content_not_supported
123+
throwable != null && throwable.isNetworkRelated -> R.string.network_error
98124
throwable is ExtractionException -> R.string.parsing_error
125+
126+
// ExoPlayer exceptions
99127
throwable is ExoPlaybackException -> {
100128
when (throwable.type) {
101129
ExoPlaybackException.TYPE_SOURCE -> R.string.player_stream_failure
102130
ExoPlaybackException.TYPE_UNEXPECTED -> R.string.player_recoverable_failure
103131
else -> R.string.player_unrecoverable_failure
104132
}
105133
}
134+
135+
// user actions (in case the exception is unrecognizable)
106136
action == UserAction.UI_ERROR -> R.string.app_ui_crash
107137
action == UserAction.REQUESTED_COMMENTS -> R.string.error_unable_to_load_comments
108138
action == UserAction.SUBSCRIPTION_CHANGE -> R.string.subscription_change_failed
109139
action == UserAction.SUBSCRIPTION_UPDATE -> R.string.subscription_update_failed
110140
action == UserAction.LOAD_IMAGE -> R.string.could_not_load_thumbnails
111141
action == UserAction.DOWNLOAD_OPEN_DIALOG -> R.string.could_not_setup_download_menu
112-
else -> R.string.general_error
142+
else -> R.string.error_snackbar_message
113143
}
114144
}
115145
}

app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,12 @@ import io.reactivex.rxjava3.disposables.Disposable
1515
import org.schabi.newpipe.MainActivity
1616
import org.schabi.newpipe.R
1717
import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException
18-
import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException
1918
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException
2019
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException
21-
import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException
22-
import org.schabi.newpipe.extractor.exceptions.PaidContentException
23-
import org.schabi.newpipe.extractor.exceptions.PrivateContentException
2420
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
25-
import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException
26-
import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException
2721
import org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty
2822
import org.schabi.newpipe.ktx.animate
2923
import org.schabi.newpipe.ktx.isInterruptedCaused
30-
import org.schabi.newpipe.ktx.isNetworkRelated
3124
import org.schabi.newpipe.util.ServiceHelper
3225
import org.schabi.newpipe.util.external_communication.ShareUtils
3326
import java.util.concurrent.TimeUnit
@@ -127,7 +120,7 @@ class ErrorPanelHelper(
127120
ErrorUtil.openActivity(context, errorInfo)
128121
}
129122

130-
errorTextView.setText(getExceptionDescription(errorInfo.throwable))
123+
errorTextView.setText(errorInfo.messageStringId)
131124

132125
if (errorInfo.throwable !is ContentNotAvailableException &&
133126
errorInfo.throwable !is ContentNotSupportedException
@@ -192,27 +185,5 @@ class ErrorPanelHelper(
192185
companion object {
193186
val TAG: String = ErrorPanelHelper::class.simpleName!!
194187
val DEBUG: Boolean = MainActivity.DEBUG
195-
196-
@StringRes
197-
fun getExceptionDescription(throwable: Throwable?): Int {
198-
return when (throwable) {
199-
is AgeRestrictedContentException -> R.string.restricted_video_no_stream
200-
is GeographicRestrictionException -> R.string.georestricted_content
201-
is PaidContentException -> R.string.paid_content
202-
is PrivateContentException -> R.string.private_content
203-
is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content
204-
is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content
205-
is ContentNotAvailableException -> R.string.content_not_available
206-
is ContentNotSupportedException -> R.string.content_not_supported
207-
else -> {
208-
// show retry button only for content which is not unavailable or unsupported
209-
if (throwable != null && throwable.isNetworkRelated) {
210-
R.string.network_error
211-
} else {
212-
R.string.error_snackbar_message
213-
}
214-
}
215-
}
216-
}
217188
}
218189
}

app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class ErrorUtil {
153153
// fallback to showing a notification if no root view is available
154154
createNotification(context, errorInfo)
155155
} else {
156-
Snackbar.make(rootView, R.string.error_snackbar_message, Snackbar.LENGTH_LONG)
156+
Snackbar.make(rootView, errorInfo.messageStringId, Snackbar.LENGTH_LONG)
157157
.setActionTextColor(Color.YELLOW)
158158
.setAction(context.getString(R.string.error_snackbar_action).uppercase()) {
159159
openActivity(context, errorInfo)

app/src/main/java/org/schabi/newpipe/error/UserAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ public enum UserAction {
3333
SHARE_TO_NEWPIPE("share to newpipe"),
3434
CHECK_FOR_NEW_APP_VERSION("check for new app version"),
3535
OPEN_INFO_ITEM_DIALOG("open info item dialog"),
36-
GETTING_MAIN_SCREEN_TAB("getting main screen tab");
36+
GETTING_MAIN_SCREEN_TAB("getting main screen tab"),
37+
PLAY_ON_POPUP("play on popup");
3738

3839
private final String message;
3940

app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package org.schabi.newpipe.util.text;
22

33
import android.content.Context;
4-
import android.util.Log;
54

65
import androidx.annotation.NonNull;
7-
import androidx.appcompat.app.AlertDialog;
86

97
import org.schabi.newpipe.MainActivity;
10-
import org.schabi.newpipe.R;
11-
import org.schabi.newpipe.error.ErrorPanelHelper;
8+
import org.schabi.newpipe.error.ErrorInfo;
9+
import org.schabi.newpipe.error.ErrorUtil;
10+
import org.schabi.newpipe.error.UserAction;
1211
import org.schabi.newpipe.extractor.NewPipe;
1312
import org.schabi.newpipe.extractor.StreamingService;
1413
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@@ -158,19 +157,13 @@ public static boolean playOnPopup(final Context context,
158157
disposables.add(single.subscribeOn(Schedulers.io())
159158
.observeOn(AndroidSchedulers.mainThread())
160159
.subscribe(info -> {
161-
final PlayQueue playQueue =
162-
new SinglePlayQueue(info, seconds * 1000L);
160+
final PlayQueue playQueue = new SinglePlayQueue(info, seconds * 1000L);
163161
NavigationHelper.playOnPopupPlayer(context, playQueue, false);
164162
}, throwable -> {
165-
if (DEBUG) {
166-
Log.e(TAG, "Could not play on popup: " + url, throwable);
167-
}
168-
new AlertDialog.Builder(context)
169-
.setTitle(R.string.player_stream_failure)
170-
.setMessage(
171-
ErrorPanelHelper.Companion.getExceptionDescription(throwable))
172-
.setPositiveButton(R.string.ok, null)
173-
.show();
163+
final var errorInfo = new ErrorInfo(throwable, UserAction.PLAY_ON_POPUP, url);
164+
// This will only show a snackbar if the passed context has a root view:
165+
// otherwise it will resort to showing a notification, so we are safe here.
166+
ErrorUtil.showSnackbar(context, errorInfo);
174167
}));
175168
return true;
176169
}

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,4 +866,6 @@
866866
<string name="import_settings_vulnerable_format">The settings in the export being imported use a vulnerable format that was deprecated since NewPipe 0.27.0. Make sure the export being imported is from a trusted source, and prefer using only exports obtained from NewPipe 0.27.0 or newer in the future. Support for importing settings in this vulnerable format will soon be removed completely, and then old versions of NewPipe will not be able to import settings of exports from new versions anymore.</string>
867867
<string name="migration_info_6_7_title">SoundCloud Top 50 page removed</string>
868868
<string name="migration_info_6_7_message">SoundCloud has discontinued the original Top 50 charts. The corresponding tab has been removed from your main page.</string>
869+
<string name="youtube_sign_in_confirm_not_bot_error">YouTube refused to provide data, asking for a login.\n\nYour IP might have been temporarily banned by YouTube, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data).</string>
870+
<string name="unsupported_content_in_country">This content is not available for the currently selected content country.\n\nChange your selection from \"Settings > Content > Default content country\".</string>
869871
</resources>

0 commit comments

Comments
 (0)