fix(YouTube - Downloads): Use new task context (#583)

Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
LisoUseInAIKyrios 2024-03-08 09:10:06 +04:00 committed by GitHub
parent 75a494e09b
commit 468dfac054
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 117 additions and 57 deletions

View File

@ -40,7 +40,7 @@ import kotlin.text.Regex;
public class Utils { public class Utils {
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
public static Context context; private static Context context;
private static String versionName; private static String versionName;
@ -233,6 +233,11 @@ public class Utils {
return context; return context;
} }
public static void setContext(Context appContext) {
context = appContext;
Logger.printDebug(() -> "Set context: " + appContext); // Cannot log before context is set.
}
public static void setClipboard(@NonNull String text) { public static void setClipboard(@NonNull String text) {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("ReVanced", text); android.content.ClipData clip = android.content.ClipData.newPlainText("ReVanced", text);

View File

@ -1,27 +1,84 @@
package app.revanced.integrations.youtube.patches; package app.revanced.integrations.youtube.patches;
import android.app.Activity;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.lang.ref.WeakReference;
import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.shared.StringRef; import app.revanced.integrations.shared.StringRef;
import app.revanced.integrations.shared.Utils; import app.revanced.integrations.shared.Utils;
import app.revanced.integrations.youtube.patches.spoof.SpoofAppVersionPatch;
import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.youtube.settings.Settings;
@SuppressWarnings("unused")
public final class DownloadsPatch { public final class DownloadsPatch {
public static boolean inAppDownloadButtonOnClick() {
if (!Settings.USE_IN_APP_DOWNLOAD_BUTTON.get())
return false;
launchExternalDownloader(); private static WeakReference<Activity> activityRef = new WeakReference<>(null);
return true;
/**
* Injection point.
*/
public static void activityCreated(Activity mainActivity) {
activityRef = new WeakReference<>(mainActivity);
} }
public static void launchExternalDownloader() { /**
Logger.printDebug(() -> "Launching external downloader"); * Injection point.
*
* Call if download playlist is pressed, or if download button is used
* for old spoofed version (both playlists and the player action button).
*
* Downloading playlists is not supported yet,
* as the hooked code does not easily expose the playlist id.
*/
public static boolean inAppDownloadPlaylistLegacyOnClick(@Nullable String videoId) {
if (videoId == null || videoId.isEmpty()) {
// videoId is null or empty if download playlist is pressed.
Logger.printDebug(() -> "Ignoring playlist download button press");
return false;
}
return inAppDownloadButtonOnClick();
}
final var context = Utils.getContext(); /**
* Injection point.
*/
public static boolean inAppDownloadButtonOnClick() {
try {
if (!Settings.EXTERNAL_DOWNLOADER_ACTION_BUTTON.get()) {
return false;
}
// If possible, use the main activity as the context.
// Otherwise fall back on using the application context.
Context context = activityRef.get();
boolean isActivityContext = true;
if (context == null) {
// Utils context is the application context, and not an activity context.
context = Utils.getContext();
isActivityContext = false;
}
launchExternalDownloader(context, isActivityContext);
return true;
} catch (Exception ex) {
Logger.printException(() -> "inAppDownloadButtonOnClick failure", ex);
}
return false;
}
/**
* @param isActivityContext If the context parameter is for an Activity. If this is false, then
* the downloader is opened as a new task (which forces YT to minimize).
*/
public static void launchExternalDownloader(@NonNull Context context, boolean isActivityContext) {
Logger.printDebug(() -> "Launching external downloader with context: " + context);
// Trim string to avoid any accidental whitespace. // Trim string to avoid any accidental whitespace.
var downloaderPackageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get().trim(); var downloaderPackageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get().trim();
@ -47,11 +104,13 @@ public final class DownloadsPatch {
intent.setType("text/plain"); intent.setType("text/plain");
intent.setPackage(downloaderPackageName); intent.setPackage(downloaderPackageName);
intent.putExtra("android.intent.extra.TEXT", content); intent.putExtra("android.intent.extra.TEXT", content);
if (!isActivityContext) {
Logger.printDebug(() -> "Using new task intent");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent); context.startActivity(intent);
Logger.printDebug(() -> "Launched the intent with the content: " + content);
} catch (Exception error) { } catch (Exception error) {
Logger.printException(() -> "Failed to launch the intent: " + error, error); Logger.printException(() -> "Failed to launch intent: " + error, error);
} }
} }
} }

View File

@ -16,7 +16,7 @@ public class HideBreakingNewsPatch {
* Breaking news does not appear to be present in these older versions anyways. * Breaking news does not appear to be present in these older versions anyways.
*/ */
private static final boolean isSpoofingOldVersionWithHorizontalCardListWatchHistory = private static final boolean isSpoofingOldVersionWithHorizontalCardListWatchHistory =
SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("17.31.00"); SpoofAppVersionPatch.isSpoofingToLessThan("18.01.00");
/** /**
* Injection point. * Injection point.

View File

@ -6,24 +6,12 @@ import androidx.annotation.Nullable;
import app.revanced.integrations.youtube.shared.PlayerOverlays; import app.revanced.integrations.youtube.shared.PlayerOverlays;
/**
* Hook receiver class for 'player-overlays-hook' patch
*
* @usedBy app.revanced.patches.youtube.misc.playeroverlay.patch.PlayerOverlaysHookPatch
* @smali Lapp/revanced/integrations/patches/PlayerOverlaysHookPatch;
*/
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class PlayerOverlaysHookPatch { public class PlayerOverlaysHookPatch {
/** /**
* Injection point. * Injection point.
*
* @param thisRef reference to the view
* @smali YouTubePlayerOverlaysLayout_onFinishInflateHook(Ljava / lang / Object ;)V
*/ */
public static void YouTubePlayerOverlaysLayout_onFinishInflateHook(@Nullable Object thisRef) { public static void playerOverlayInflated(ViewGroup group) {
if (thisRef == null) return; PlayerOverlays.attach(group);
if (thisRef instanceof ViewGroup) {
PlayerOverlays.attach((ViewGroup) thisRef);
}
} }
} }

View File

@ -46,7 +46,7 @@ import static app.revanced.integrations.youtube.returnyoutubedislike.ReturnYouTu
public class ReturnYouTubeDislikePatch { public class ReturnYouTubeDislikePatch {
public static final boolean IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER = public static final boolean IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER =
SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("18.33.40"); SpoofAppVersionPatch.isSpoofingToLessThan("18.34.00");
/** /**
* RYD data for the current video on screen. * RYD data for the current video on screen.

View File

@ -1,26 +1,12 @@
package app.revanced.integrations.youtube.patches.spoof; package app.revanced.integrations.youtube.patches.spoof;
import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.youtube.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class SpoofAppVersionPatch { public class SpoofAppVersionPatch {
private static final boolean SPOOF_APP_VERSION_ENABLED; private static final boolean SPOOF_APP_VERSION_ENABLED = Settings.SPOOF_APP_VERSION.get();
private static final String SPOOF_APP_VERSION_TARGET; private static final String SPOOF_APP_VERSION_TARGET = Settings.SPOOF_APP_VERSION_TARGET.get();
static {
// TODO: remove this migration code
// Spoof targets below 17.33 that no longer reliably work.
if (Settings.SPOOF_APP_VERSION_TARGET.get().compareTo("17.33.01") < 0) {
Logger.printInfo(() -> "Resetting spoof app version target");
Settings.SPOOF_APP_VERSION_TARGET.resetToDefault();
}
// End migration
SPOOF_APP_VERSION_ENABLED = Settings.SPOOF_APP_VERSION.get();
SPOOF_APP_VERSION_TARGET = Settings.SPOOF_APP_VERSION_TARGET.get();
}
/** /**
* Injection point * Injection point
@ -30,8 +16,8 @@ public class SpoofAppVersionPatch {
return version; return version;
} }
public static boolean isSpoofingToEqualOrLessThan(String version) { public static boolean isSpoofingToLessThan(String version) {
return SPOOF_APP_VERSION_ENABLED && SPOOF_APP_VERSION_TARGET.compareTo(version) <= 0; return SPOOF_APP_VERSION_ENABLED && SPOOF_APP_VERSION_TARGET.compareTo(version) < 0;
} }
} }

View File

@ -91,7 +91,7 @@ public class ReturnYouTubeDislike {
private static final char MIDDLE_SEPARATOR_CHARACTER = '◎'; // 'bullseye' private static final char MIDDLE_SEPARATOR_CHARACTER = '◎'; // 'bullseye'
private static final boolean IS_SPOOFING_TO_OLD_SEPARATOR_COLOR private static final boolean IS_SPOOFING_TO_OLD_SEPARATOR_COLOR
= SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("18.09.39"); = SpoofAppVersionPatch.isSpoofingToLessThan("18.10.00");
/** /**
* Cached lookup of all video ids. * Cached lookup of all video ids.

View File

@ -1,7 +1,9 @@
package app.revanced.integrations.youtube.settings; package app.revanced.integrations.youtube.settings;
import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.shared.settings.*; import app.revanced.integrations.shared.settings.*;
import app.revanced.integrations.shared.settings.preference.SharedPrefCategory; import app.revanced.integrations.shared.settings.preference.SharedPrefCategory;
import app.revanced.integrations.youtube.patches.spoof.SpoofAppVersionPatch;
import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings; import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings;
import java.util.Arrays; import java.util.Arrays;
@ -16,9 +18,9 @@ import static java.lang.Boolean.TRUE;
public class Settings extends BaseSettings { public class Settings extends BaseSettings {
// External downloader // External downloader
public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE); public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE);
public static final BooleanSetting EXTERNAL_DOWNLOADER_ACTION_BUTTON = new BooleanSetting("revanced_external_downloader_action_button", FALSE);
public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_name", public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_name",
"org.schabi.newpipe" /* NewPipe */, parent(EXTERNAL_DOWNLOADER)); "org.schabi.newpipe" /* NewPipe */, parentsAny(EXTERNAL_DOWNLOADER, EXTERNAL_DOWNLOADER_ACTION_BUTTON));
public static final BooleanSetting USE_IN_APP_DOWNLOAD_BUTTON = new BooleanSetting("revanced_use_in_app_download_button", TRUE);
// Copy video URL // Copy video URL
public static final BooleanSetting COPY_VIDEO_URL = new BooleanSetting("revanced_copy_video_url", FALSE); public static final BooleanSetting COPY_VIDEO_URL = new BooleanSetting("revanced_copy_video_url", FALSE);
@ -335,6 +337,14 @@ public class Settings extends BaseSettings {
// and more time should be given for users who rarely upgrade. // and more time should be given for users who rarely upgrade.
migrateOldSettingToNew(DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, SB_PRIVATE_USER_ID); migrateOldSettingToNew(DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, SB_PRIVATE_USER_ID);
// Old spoof versions that no longer work reliably.
if (SpoofAppVersionPatch.isSpoofingToLessThan("17.33.00")) {
Logger.printInfo(() -> "Resetting spoof app version target");
Settings.SPOOF_APP_VERSION_TARGET.resetToDefault();
}
// endregion // endregion
} }
} }

View File

@ -1,8 +1,15 @@
package app.revanced.integrations.youtube.settings.preference; package app.revanced.integrations.youtube.settings.preference;
import android.os.Build;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceGroup;
import androidx.annotation.RequiresApi;
import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.shared.settings.preference.AbstractPreferenceFragment; import app.revanced.integrations.shared.settings.preference.AbstractPreferenceFragment;
import app.revanced.integrations.youtube.patches.DownloadsPatch;
import app.revanced.integrations.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.integrations.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.youtube.settings.Settings;
@ -12,14 +19,20 @@ import app.revanced.integrations.youtube.settings.Settings;
* @noinspection deprecation * @noinspection deprecation
*/ */
public class ReVancedPreferenceFragment extends AbstractPreferenceFragment { public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override @Override
protected void initialize() { protected void initialize() {
super.initialize(); super.initialize();
// If the preference was included, then initialize it based on the available playback speed try {
Preference defaultSpeedPreference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key); // If the preference was included, then initialize it based on the available playback speed.
if (defaultSpeedPreference instanceof ListPreference) { Preference defaultSpeedPreference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key);
CustomPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference); if (defaultSpeedPreference instanceof ListPreference) {
CustomPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference);
}
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
} }
} }
} }

View File

@ -5,10 +5,9 @@ import android.view.ViewGroup;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.revanced.integrations.youtube.patches.DownloadsPatch;
import app.revanced.integrations.youtube.patches.VideoInformation;
import app.revanced.integrations.youtube.settings.Settings;
import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.youtube.patches.DownloadsPatch;
import app.revanced.integrations.youtube.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class ExternalDownloadButton extends BottomControlButton { public class ExternalDownloadButton extends BottomControlButton {
@ -44,7 +43,7 @@ public class ExternalDownloadButton extends BottomControlButton {
} }
private static void onDownloadClick(View view) { private static void onDownloadClick(View view) {
DownloadsPatch.launchExternalDownloader(); DownloadsPatch.launchExternalDownloader(view.getContext(), true);
} }
} }