diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/utils/ResourceUtils.java b/extensions/shared/src/main/java/app/revanced/extension/shared/utils/ResourceUtils.java index 55b7c1ac6..e3252ef9a 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/utils/ResourceUtils.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/utils/ResourceUtils.java @@ -1,5 +1,6 @@ package app.revanced.extension.shared.utils; +import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; import android.view.animation.Animation; @@ -16,12 +17,25 @@ public class ResourceUtils extends Utils { } // utility class public static int getIdentifier(@NonNull String str, @NonNull ResourceType resourceType) { - return getIdentifier(str, resourceType, getContext()); + Activity mActivity = getActivity(); + Context mContext = mActivity != null + ? mActivity + : getContext(); + if (mContext == null) { + handleException(str, resourceType); + return 0; + } + return getIdentifier(str, resourceType, mContext); } public static int getIdentifier(@NonNull String str, @NonNull ResourceType resourceType, @NonNull Context context) { - return getResources().getIdentifier(str, resourceType.getType(), context.getPackageName()); + try { + return context.getResources().getIdentifier(str, resourceType.getType(), context.getPackageName()); + } catch (Exception ex) { + handleException(str, resourceType); + } + return 0; } public static int getAnimIdentifier(@NonNull String str) { diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/utils/StringRef.java b/extensions/shared/src/main/java/app/revanced/extension/shared/utils/StringRef.java index f51b49ed0..902e354e2 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/utils/StringRef.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/utils/StringRef.java @@ -1,6 +1,7 @@ package app.revanced.extension.shared.utils; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; import android.content.res.Resources; @@ -104,7 +105,10 @@ public class StringRef extends Utils { public String toString() { if (!resolved) { try { - Context context = getContext(); + Activity mActivity = getActivity(); + Context context = mActivity != null + ? mActivity + : getContext(); if (resources == null) { resources = getResources(); } diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/utils/Utils.java b/extensions/shared/src/main/java/app/revanced/extension/shared/utils/Utils.java index 3d500e657..ed3e96428 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/utils/Utils.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/utils/Utils.java @@ -54,8 +54,6 @@ public class Utils { @SuppressLint("StaticFieldLeak") public static Context context; - private static Resources resources; - protected Utils() { } // utility class @@ -282,11 +280,15 @@ public class Utils { } public static Resources getResources() { - if (resources == null) { - return getLocalizedContextAndSetResources(getContext()).getResources(); - } else { - return resources; + Activity mActivity = activityRef.get(); + if (mActivity != null) { + return mActivity.getResources(); } + Context mContext = getContext(); + if (mContext != null) { + return mContext.getResources(); + } + throw new IllegalStateException("Get resources failed"); } /** @@ -304,6 +306,9 @@ public class Utils { if (mActivity == null) { return mContext; } + if (mContext == null) { + return null; + } // Locale of MainActivity. Locale applicationLocale; @@ -321,7 +326,6 @@ public class Utils { // If they are identical, no need to override them. if (applicationLocale == contextLocale) { - resources = mActivity.getResources(); return mContext; } @@ -329,9 +333,7 @@ public class Utils { Locale.setDefault(applicationLocale); Configuration configuration = new Configuration(mContext.getResources().getConfiguration()); configuration.setLocale(applicationLocale); - Context localizedContext = mContext.createConfigurationContext(configuration); - resources = localizedContext.getResources(); - return localizedContext; + return mContext.createConfigurationContext(configuration); } public static void setActivity(Activity mainActivity) { diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/GeneralPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/GeneralPatch.java index af5337825..1223d4115 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/GeneralPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/GeneralPatch.java @@ -40,7 +40,6 @@ import java.util.EnumMap; import java.util.Map; import java.util.Objects; -import app.revanced.extension.shared.utils.Logger; import app.revanced.extension.shared.utils.ResourceUtils; import app.revanced.extension.shared.utils.Utils; import app.revanced.extension.youtube.settings.Settings; @@ -109,12 +108,7 @@ public class GeneralPatch { // region [Disable splash animation] patch public static boolean disableSplashAnimation(boolean original) { - try { - return !Settings.DISABLE_SPLASH_ANIMATION.get() && original; - } catch (Exception ex) { - Logger.printException(() -> "Failed to load disableSplashAnimation", ex); - } - return original; + return !Settings.DISABLE_SPLASH_ANIMATION.get() && original; } // endregion @@ -130,12 +124,7 @@ public class GeneralPatch { // region [Hide layout components] patch public static boolean disableTranslucentStatusBar(boolean original) { - try { - return !Settings.DISABLE_TRANSLUCENT_STATUS_BAR.get() && original; - } catch (Exception ex) { - Logger.printException(() -> "Failed to load disableTranslucentStatusBar", ex); - } - return original; + return !Settings.DISABLE_TRANSLUCENT_STATUS_BAR.get() && original; } private static String[] accountMenuBlockList; @@ -240,12 +229,7 @@ public class GeneralPatch { } public static boolean switchCreateWithNotificationButton(boolean original) { - try { - return Settings.SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON.get() || original; - } catch (Exception ex) { - Logger.printException(() -> "switchCreateWithNotificationButton Failed", ex); - } - return original; + return Settings.SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON.get() || original; } public static void navigationTabCreated(NavigationButton button, View tabView) { @@ -327,6 +311,9 @@ public class GeneralPatch { // region [Toolbar components] patch + private static final int generalHeaderAttributeId = ResourceUtils.getAttrIdentifier("ytWordmarkHeader"); + private static final int premiumHeaderAttributeId = ResourceUtils.getAttrIdentifier("ytPremiumWordmarkHeader"); + public static void setDrawerNavigationHeader(View lithoView) { final int headerAttributeId = getHeaderAttributeId(); @@ -344,8 +331,8 @@ public class GeneralPatch { public static int getHeaderAttributeId() { return Settings.CHANGE_YOUTUBE_HEADER.get() - ? ResourceUtils.getAttrIdentifier("ytPremiumWordmarkHeader") - : ResourceUtils.getAttrIdentifier("ytWordmarkHeader"); + ? premiumHeaderAttributeId + : generalHeaderAttributeId; } public static boolean overridePremiumHeader() { @@ -357,6 +344,11 @@ public class GeneralPatch { return ResourceUtils.getDrawable(""); } + private static final int searchBarId = ResourceUtils.getIdIdentifier("search_bar"); + private static final int youtubeTextId = ResourceUtils.getIdIdentifier("youtube_text"); + private static final int searchBoxId = ResourceUtils.getIdIdentifier("search_box"); + private static final int searchIconId = ResourceUtils.getIdIdentifier("search_icon"); + private static final boolean wideSearchbarEnabled = Settings.ENABLE_WIDE_SEARCH_BAR.get(); // Loads the search bar deprecated by Google. private static final boolean wideSearchbarWithHeaderEnabled = Settings.ENABLE_WIDE_SEARCH_BAR_WITH_HEADER.get(); @@ -396,17 +388,12 @@ public class GeneralPatch { if (!wideSearchbarEnabled) return; - final int searchBarId = ResourceUtils.getIdIdentifier("search_bar"); if (!(view.findViewById(searchBarId) instanceof RelativeLayout searchBarView)) return; // When the deprecated search bar is loaded, two search bars overlap. // Manually hides another search bar. if (wideSearchbarWithHeaderEnabled) { - final int youtubeTextId = ResourceUtils.getIdIdentifier("youtube_text"); - final int searchBoxId = ResourceUtils.getIdIdentifier("search_box"); - final int searchIconId = ResourceUtils.getIdIdentifier("search_icon"); - final View searchIconView = searchBarView.findViewById(searchIconId); final View searchBoxView = searchBarView.findViewById(searchBoxId); final View textView = searchBarView.findViewById(youtubeTextId); @@ -521,14 +508,16 @@ public class GeneralPatch { imageView.setImageDrawable(drawable); } + private static final int settingsDrawableId = + ResourceUtils.getDrawableIdentifier("yt_outline_gear_black_24"); + private static final int settingsCairoDrawableId = + ResourceUtils.getDrawableIdentifier("yt_outline_gear_cairo_black_24"); + public static int getCreateButtonDrawableId(int original) { if (!Settings.REPLACE_TOOLBAR_CREATE_BUTTON.get()) { return original; } - final int settingsDrawableId = - ResourceUtils.getDrawableIdentifier("yt_outline_gear_black_24"); - if (settingsDrawableId == 0) { return original; } @@ -539,9 +528,6 @@ public class GeneralPatch { return settingsDrawableId; } - final int settingsCairoDrawableId = - ResourceUtils.getDrawableIdentifier("yt_outline_gear_cairo_black_24"); - return settingsCairoDrawableId == 0 ? settingsDrawableId : settingsCairoDrawableId; diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/SharedExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/SharedExtensionPatch.kt index bab6ee3da..263d4fb8c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/SharedExtensionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/SharedExtensionPatch.kt @@ -2,8 +2,10 @@ package app.revanced.patches.youtube.utils.extension import app.revanced.patches.shared.extension.sharedExtensionPatch import app.revanced.patches.youtube.utils.extension.hooks.applicationInitHook +import app.revanced.patches.youtube.utils.extension.hooks.mainActivityBaseContextHook // TODO: Move this to a "Hook.kt" file. Same for other extension hook patches. val sharedExtensionPatch = sharedExtensionPatch( applicationInitHook, + mainActivityBaseContextHook, ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/hooks/MainActivityBaseContextHook.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/hooks/MainActivityBaseContextHook.kt new file mode 100644 index 000000000..7543cc3d8 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/hooks/MainActivityBaseContextHook.kt @@ -0,0 +1,35 @@ +package app.revanced.patches.youtube.utils.extension.hooks + +import app.revanced.patches.shared.extension.extensionHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +private var attachBaseContextIndex = -1 + +internal val mainActivityBaseContextHook = extensionHook( + insertIndexResolver = { method -> + attachBaseContextIndex = method.indexOfFirstInstructionOrThrow { + getReference()?.name == "attachBaseContext" + } + + attachBaseContextIndex + 1 + }, + contextRegisterResolver = { method -> + val overrideInstruction = method.implementation!!.instructions.elementAt(attachBaseContextIndex) + as FiveRegisterInstruction + "v${overrideInstruction.registerD}" + }, +) { + returns("V") + parameters("Landroid/content/Context;") + custom { method, classDef -> + method.name == "attachBaseContext" && + ( + classDef.endsWith("/MainActivity;") || + // Old versions of YouTube called this class "WatchWhileActivity" instead. + classDef.endsWith("/WatchWhileActivity;") + ) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt index 901ef8d7a..ae9c22223 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/PlayerResponseMethodHookPatch.kt @@ -70,7 +70,7 @@ val playerResponseMethodHookPatch = bytecodePatch( """ invoke-static {$registerVideoId, $registerPlayerParameter, $registerPlaylistId, $registerIsShortAndOpeningOrPlaying}, $hook move-result-object $registerPlayerParameter - """, + """, ) numberOfInstructionsAdded += 2 }