From cbcb0f756aefc84687bf85fb11d82acb20c67635 Mon Sep 17 00:00:00 2001 From: polymorphicshade Date: Tue, 8 Dec 2020 00:02:32 -0700 Subject: [PATCH] SponsorBlock: removed deprecated AsyncTask and improved performance --- .../fragments/detail/VideoDetailFragment.java | 41 ++++++++++ .../org/schabi/newpipe/player/BasePlayer.java | 73 ++++-------------- .../SponsorBlockUtils.java} | 76 +++++++++---------- 3 files changed, 93 insertions(+), 97 deletions(-) rename app/src/main/java/org/schabi/newpipe/{SponsorBlockApiTask.java => util/SponsorBlockUtils.java} (82%) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 427cff06e..47cf2d1b3 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -103,7 +103,9 @@ import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.ShareUtils; +import org.schabi.newpipe.util.SponsorBlockUtils; import org.schabi.newpipe.util.ThemeHelper; +import org.schabi.newpipe.util.VideoSegment; import org.schabi.newpipe.views.AnimatedProgressBar; import org.schabi.newpipe.views.LargeTextMovementMethod; @@ -192,6 +194,7 @@ public final class VideoDetailFragment private int selectedVideoStreamIndex = -1; private BottomSheetBehavior bottomSheetBehavior; private BroadcastReceiver broadcastReceiver; + private VideoSegment[] videoSegments; /*////////////////////////////////////////////////////////////////////////// // Views @@ -262,6 +265,8 @@ public final class VideoDetailFragment final MainPlayer connectedPlayerService, final boolean playAfterConnect) { player = connectedPlayer; + player.setVideoSegments(videoSegments); + playerService = connectedPlayerService; // It will do nothing if the player is not in fullscreen mode @@ -945,7 +950,43 @@ public final class VideoDetailFragment private void runWorker(final boolean forceLoad, final boolean addToBackStack) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); + + final String apiUrl = prefs.getString(getContext() + .getString(R.string.sponsor_block_api_url_key), null); + final boolean isSponsorBlockEnabled = prefs.getBoolean(getContext() + .getString(R.string.sponsor_block_enable_key), false); + final boolean includeSponsorCategory = prefs.getBoolean(getContext() + .getString(R.string.sponsor_block_category_sponsor_key), false); + final boolean includeIntroCategory = prefs.getBoolean(getContext() + .getString(R.string.sponsor_block_category_intro_key), false); + final boolean includeOutroCategory = prefs.getBoolean(getContext() + .getString(R.string.sponsor_block_category_outro_key), false); + final boolean includeInteractionCategory = prefs.getBoolean(getContext() + .getString(R.string.sponsor_block_category_interaction_key), false); + final boolean includeSelfPromoCategory = prefs.getBoolean(getContext() + .getString(R.string.sponsor_block_category_self_promo_key), false); + final boolean includeMusicCategory = prefs.getBoolean(getContext() + .getString(R.string.sponsor_block_category_non_music_key), false); + currentWorker = ExtractorHelper.getStreamInfo(serviceId, url, forceLoad) + .flatMap(streamInfo -> Single.fromCallable(() -> { + if (isSponsorBlockEnabled + && streamInfo.getUrl().startsWith("https://www.youtube.com") + && apiUrl != null + && !apiUrl.isEmpty()) { + this.videoSegments = SponsorBlockUtils.getYouTubeVideoSegments( + apiUrl, + streamInfo.getId(), + includeSponsorCategory, + includeIntroCategory, + includeOutroCategory, + includeInteractionCategory, + includeSelfPromoCategory, + includeMusicCategory); + } + + return streamInfo; + })) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index e8d5bfc0d..94ef64581 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -59,7 +59,6 @@ import org.schabi.newpipe.App; import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; -import org.schabi.newpipe.SponsorBlockApiTask; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.helper.AudioReactor; @@ -118,6 +117,7 @@ public abstract class BasePlayer implements @NonNull protected final SharedPreferences mPrefs; + private boolean wereSponsorsMarked; private VideoSegment[] videoSegments; /*////////////////////////////////////////////////////////////////////////// @@ -1211,65 +1211,11 @@ public abstract class BasePlayer implements context.getString(R.string.sponsor_block_whitelist_key), null); if (uploaderWhitelist != null && uploaderWhitelist.contains(info.getUploaderName())) { - sponsorBlockMode = SponsorBlockMode.IGNORE; + setSponsorBlockMode(SponsorBlockMode.IGNORE); } else { - sponsorBlockMode = isSponsorBlockEnabled + setSponsorBlockMode(isSponsorBlockEnabled ? SponsorBlockMode.ENABLED - : SponsorBlockMode.DISABLED; - } - - if (info.getUrl().startsWith("https://www.youtube.com")) { - final String apiUrl = mPrefs - .getString(context.getString(R.string.sponsor_block_api_url_key), null); - - if (apiUrl != null && !apiUrl.isEmpty() && isSponsorBlockEnabled) { - try { - final boolean includeSponsorCategory = - mPrefs.getBoolean( - context.getString( - R.string.sponsor_block_category_sponsor_key), - false); - - final boolean includeIntroCategory = - mPrefs.getBoolean( - context.getString( - R.string.sponsor_block_category_intro_key), - false); - - final boolean includeOutroCategory = - mPrefs.getBoolean( - context.getString( - R.string.sponsor_block_category_outro_key), - false); - - final boolean includeInteractionCategory = - mPrefs.getBoolean( - context.getString( - R.string.sponsor_block_category_interaction_key), - false); - final boolean includeSelfPromoCategory = - mPrefs.getBoolean( - context.getString( - R.string.sponsor_block_category_self_promo_key), - false); - final boolean includeMusicCategory = - mPrefs.getBoolean( - context.getString( - R.string.sponsor_block_category_non_music_key), - false); - - videoSegments = new SponsorBlockApiTask(apiUrl) - .getYouTubeVideoSegments(info.getId(), - includeSponsorCategory, - includeIntroCategory, - includeOutroCategory, - includeInteractionCategory, - includeSelfPromoCategory, - includeMusicCategory); - } catch (final Exception e) { - Log.e("SPONSOR_BLOCK", "Error getting YouTube video segments.", e); - } - } + : SponsorBlockMode.DISABLED); } } @@ -1822,4 +1768,15 @@ public abstract class BasePlayer implements public VideoSegment[] getVideoSegments() { return videoSegments; } + + public void setVideoSegments(final VideoSegment[] videoSegments) { + // use a flag to ignore null values later (i.e. when the video goes fullscreen) + // TODO: there's probably a better way to deal with stuff like that + if (wereSponsorsMarked) { + return; + } + + this.videoSegments = videoSegments; + wereSponsorsMarked = true; + } } diff --git a/app/src/main/java/org/schabi/newpipe/SponsorBlockApiTask.java b/app/src/main/java/org/schabi/newpipe/util/SponsorBlockUtils.java similarity index 82% rename from app/src/main/java/org/schabi/newpipe/SponsorBlockApiTask.java rename to app/src/main/java/org/schabi/newpipe/util/SponsorBlockUtils.java index 6c3792660..4ee901e59 100644 --- a/app/src/main/java/org/schabi/newpipe/SponsorBlockApiTask.java +++ b/app/src/main/java/org/schabi/newpipe/util/SponsorBlockUtils.java @@ -1,9 +1,8 @@ -package org.schabi.newpipe; +package org.schabi.newpipe.util; import android.app.Application; import android.content.Context; import android.net.ConnectivityManager; -import android.os.AsyncTask; import android.text.TextUtils; import android.util.Log; @@ -11,34 +10,34 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; -import org.schabi.newpipe.util.VideoSegment; +import org.schabi.newpipe.App; +import org.schabi.newpipe.DownloaderImpl; +import org.schabi.newpipe.MainActivity; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.ArrayList; -import java.util.concurrent.ExecutionException; -public class SponsorBlockApiTask extends AsyncTask { +public final class SponsorBlockUtils { private static final Application APP = App.getApp(); - private String apiUrl; - private static final String TAG = SponsorBlockApiTask.class.getSimpleName(); + private static final String TAG = SponsorBlockUtils.class.getSimpleName(); private static final boolean DEBUG = MainActivity.DEBUG; - public SponsorBlockApiTask(final String apiUrl) { - this.apiUrl = apiUrl; + private SponsorBlockUtils() { } - public VideoSegment[] getYouTubeVideoSegments(final String videoId, + @SuppressWarnings("CheckStyle") + public static VideoSegment[] getYouTubeVideoSegments(final String apiUrl, + final String videoId, final boolean includeSponsorCategory, final boolean includeIntroCategory, final boolean includeOutroCategory, final boolean includeInteractionCategory, final boolean includeSelfPromoCategory, final boolean includeMusicCategory) - throws ExecutionException, InterruptedException, UnsupportedEncodingException { - + throws UnsupportedEncodingException { final ArrayList categoryParamList = new ArrayList<>(); if (includeSponsorCategory) { @@ -76,7 +75,30 @@ public class SponsorBlockApiTask extends AsyncTask { final String params = "skipSegments/" + videoIdHash.substring(0, 4) + "?categories=" + categoryParams; - final JsonArray responseArray = execute(params).get(); + if (!isConnected()) { + return null; + } + + JsonArray responseArray = null; + + try { + final String responseBody = + DownloaderImpl + .getInstance() + .get(apiUrl + params) + .responseBody(); + + responseArray = JsonParser.array().from(responseBody); + + } catch (final Exception ex) { + if (DEBUG) { + Log.w(TAG, Log.getStackTraceString(ex)); + } + } + + if (responseArray == null) { + return null; + } final ArrayList result = new ArrayList<>(); @@ -113,38 +135,14 @@ public class SponsorBlockApiTask extends AsyncTask { return result.toArray(new VideoSegment[0]); } - @Override - protected JsonArray doInBackground(final String... strings) { - if (isCancelled() || !isConnected()) { - return null; - } - - try { - final String responseBody = - DownloaderImpl - .getInstance() - .get(apiUrl + strings[0]) - .responseBody(); - - return JsonParser.array().from(responseBody); - - } catch (final Exception ex) { - if (DEBUG) { - Log.w(TAG, Log.getStackTraceString(ex)); - } - } - - return null; - } - - private boolean isConnected() { + private static boolean isConnected() { final ConnectivityManager cm = (ConnectivityManager) APP.getSystemService(Context.CONNECTIVITY_SERVICE); return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected(); } - private String toSha256(final String videoId) { + private static String toSha256(final String videoId) { try { final MessageDigest digest = MessageDigest.getInstance("SHA-256"); final byte[] bytes = digest.digest(videoId.getBytes(StandardCharsets.UTF_8));