fix(YouTube - Overlay buttons): App crashes due to incorrect Context access https://github.com/inotia00/ReVanced_Extended/issues/2831

This commit is contained in:
inotia00 2025-03-14 18:14:56 +09:00
parent 699cd055ac
commit 806976b6d8
5 changed files with 82 additions and 48 deletions

View File

@ -7,6 +7,7 @@ import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@SuppressWarnings({"unused", "deprecation", "DiscouragedApi"})
public class ResourceUtils extends Utils {
@ -100,13 +101,19 @@ public class ResourceUtils extends Utils {
return getIdentifier(str, ResourceType.XML);
}
@Nullable
public static Animation getAnimation(@NonNull String str) {
int identifier = getAnimIdentifier(str);
if (identifier == 0) {
try {
int identifier = getAnimIdentifier(str);
if (identifier == 0) {
handleException(str, ResourceType.ANIM);
identifier = android.R.anim.fade_in;
}
return AnimationUtils.loadAnimation(getContext(), identifier);
} catch (Exception ex) {
handleException(str, ResourceType.ANIM);
identifier = android.R.anim.fade_in;
}
return AnimationUtils.loadAnimation(getContext(), identifier);
return null;
}
public static int getColor(@NonNull String str) {

View File

@ -53,7 +53,8 @@ import kotlin.text.Regex;
public class Utils {
private static WeakReference<Activity> activityRef = new WeakReference<>(null);
private static WeakReference<Context> contextRef = new WeakReference<>(null);
@SuppressLint("StaticFieldLeak")
private static volatile Context context;
protected Utils() {
} // utility class
@ -274,17 +275,15 @@ public class Utils {
}
public static Context getContext() {
Context mContext = contextRef.get();
if (mContext == null) {
if (context == null) {
Logger.initializationException(Utils.class, "Context is null, returning null!", null);
}
return mContext;
return context;
}
public static Resources getResources() {
Context mContext = contextRef.get();
if (mContext != null) {
return mContext.getResources();
if (context != null) {
return context.getResources();
}
Activity mActivity = activityRef.get();
if (mActivity != null) {
@ -347,7 +346,7 @@ public class Utils {
}
// Must initially set context to check the app language.
contextRef = new WeakReference<>(appContext);
context = appContext;
Logger.initializationInfo(Utils.class, "Set context: " + appContext);
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
@ -355,7 +354,7 @@ public class Utils {
// Create a new context with the desired language.
Configuration config = appContext.getResources().getConfiguration();
config.setLocale(language.getLocale());
contextRef = new WeakReference<>(appContext.createConfigurationContext(config));
context = appContext.createConfigurationContext(config);
}
}
@ -364,8 +363,7 @@ public class Utils {
}
public static void setClipboard(@NonNull String text, @Nullable String toastMessage) {
Context mContext = contextRef.get();
if (mContext != null && mContext.getSystemService(Context.CLIPBOARD_SERVICE) instanceof ClipboardManager clipboardManager) {
if (context != null && context.getSystemService(Context.CLIPBOARD_SERVICE) instanceof ClipboardManager clipboardManager) {
android.content.ClipData clip = android.content.ClipData.newPlainText("ReVanced", text);
clipboardManager.setPrimaryClip(clip);
@ -516,20 +514,18 @@ public class Utils {
}
public static int dpToPx(float dp) {
Context mContext = contextRef.get();
if (mContext == null) {
if (context == null) {
return (int) dp;
} else {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources().getDisplayMetrics());
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}
}
public static int dpToPx(int dp) {
Context mContext = contextRef.get();
if (mContext == null) {
if (context == null) {
return dp;
} else {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources().getDisplayMetrics());
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}
}
@ -550,20 +546,18 @@ public class Utils {
private static void showToast(@NonNull String messageToToast, int toastDuration) {
Objects.requireNonNull(messageToToast);
runOnMainThreadNowOrLater(() -> {
Context mContext = contextRef.get();
if (mContext == null) {
if (context == null) {
Logger.initializationException(Utils.class, "Cannot show toast (context is null): " + messageToToast, null);
} else {
Logger.printDebug(() -> "Showing toast: " + messageToToast);
Toast.makeText(mContext, messageToToast, toastDuration).show();
Toast.makeText(context, messageToToast, toastDuration).show();
}
});
}
public static boolean isLandscapeOrientation() {
Context mContext = contextRef.get();
if (mContext == null) return false;
final int orientation = mContext.getResources().getConfiguration().orientation;
if (context == null) return false;
final int orientation = context.getResources().getConfiguration().orientation;
return orientation == Configuration.ORIENTATION_LANDSCAPE;
}
@ -654,8 +648,7 @@ public class Utils {
@SuppressLint("MissingPermission") // permission already included in YouTube
public static NetworkType getNetworkType() {
Context mContext = contextRef.get();
if (mContext == null || !(mContext.getSystemService(Context.CONNECTIVITY_SERVICE) instanceof ConnectivityManager cm))
if (context == null || !(context.getSystemService(Context.CONNECTIVITY_SERVICE) instanceof ConnectivityManager cm))
return NetworkType.NONE;
final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
@ -762,7 +755,6 @@ public class Utils {
* If a preference has no key or no {@link Sort} suffix,
* then the preferences are left unsorted.
*/
@SuppressWarnings("deprecation")
public static void sortPreferenceGroups(@NonNull PreferenceGroup group) {
Sort groupSort = Sort.fromKey(group.getKey(), Sort.UNSORTED);
SortedMap<String, Preference> preferences = new TreeMap<>();

View File

@ -25,8 +25,11 @@ import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.shared.utils.Utils;
public abstract class BottomControlButton {
@Nullable
private static final Animation fadeIn;
@Nullable
private static final Animation fadeOut;
@Nullable
private static final Animation fadeOutImmediate;
private final ColorFilter cf =
@ -40,29 +43,35 @@ public abstract class BottomControlButton {
static {
fadeIn = getAnimation("fade_in");
// android.R.integer.config_shortAnimTime, 200
fadeIn.setDuration(getInteger("fade_duration_fast"));
if (fadeIn != null) {
// android.R.integer.config_shortAnimTime, 200
fadeIn.setDuration(getInteger("fade_duration_fast"));
}
fadeOut = getAnimation("fade_out");
// android.R.integer.config_mediumAnimTime, 400
fadeOut.setDuration(getInteger("fade_overlay_fade_duration"));
if (fadeOut != null) {
// android.R.integer.config_mediumAnimTime, 400
fadeOut.setDuration(getInteger("fade_overlay_fade_duration"));
}
fadeOutImmediate = getAnimation("abc_fade_out");
// android.R.integer.config_shortAnimTime, 200
fadeOutImmediate.setDuration(getInteger("fade_duration_fast"));
if (fadeOutImmediate != null) {
// android.R.integer.config_shortAnimTime, 200
fadeOutImmediate.setDuration(getInteger("fade_duration_fast"));
}
}
@NonNull
@Nullable
public static Animation getButtonFadeIn() {
return fadeIn;
}
@NonNull
@Nullable
public static Animation getButtonFadeOut() {
return fadeOut;
}
@NonNull
@Nullable
public static Animation getButtonFadeOutImmediate() {
return fadeOutImmediate;
}
@ -153,11 +162,15 @@ public abstract class BottomControlButton {
imageView.clearAnimation();
if (visible && setting.get()) {
imageView.setVisibility(View.VISIBLE);
if (animation) imageView.startAnimation(fadeIn);
if (animation && fadeIn != null) {
imageView.startAnimation(fadeIn);
}
return;
}
if (imageView.getVisibility() == View.VISIBLE) {
if (animation) imageView.startAnimation(fadeOut);
if (animation && fadeOut != null) {
imageView.startAnimation(fadeOut);
}
imageView.setVisibility(View.GONE);
}
}
@ -168,7 +181,9 @@ public abstract class BottomControlButton {
if (!setting.get()) return;
imageView.clearAnimation();
imageView.startAnimation(fadeOutImmediate);
if (fadeOutImmediate != null) {
imageView.startAnimation(fadeOutImmediate);
}
imageView.setVisibility(View.GONE);
}
}

View File

@ -3,6 +3,7 @@ package app.revanced.extension.youtube.sponsorblock.ui;
import static app.revanced.extension.shared.utils.Utils.getChildView;
import android.view.View;
import android.view.animation.Animation;
import android.widget.ImageView;
import java.lang.ref.WeakReference;
@ -45,7 +46,10 @@ public class CreateSegmentButtonController {
return;
}
if (animation) {
imageView.startAnimation(BottomControlButton.getButtonFadeIn());
Animation fadeIn = BottomControlButton.getButtonFadeIn();
if (fadeIn != null) {
imageView.startAnimation(fadeIn);
}
}
imageView.setVisibility(View.VISIBLE);
return;
@ -53,7 +57,10 @@ public class CreateSegmentButtonController {
if (imageView.getVisibility() == View.VISIBLE) {
imageView.clearAnimation();
if (animation) {
imageView.startAnimation(BottomControlButton.getButtonFadeOut());
Animation fadeOut = BottomControlButton.getButtonFadeOut();
if (fadeOut != null) {
imageView.startAnimation(fadeOut);
}
}
imageView.setVisibility(View.GONE);
}
@ -65,7 +72,10 @@ public class CreateSegmentButtonController {
if (!shouldBeShown()) return;
imageView.clearAnimation();
imageView.startAnimation(BottomControlButton.getButtonFadeOutImmediate());
Animation fadeOutImmediate = BottomControlButton.getButtonFadeOutImmediate();
if (fadeOutImmediate != null) {
imageView.startAnimation(fadeOutImmediate);
}
imageView.setVisibility(View.GONE);
}

View File

@ -4,6 +4,7 @@ import static app.revanced.extension.shared.utils.Utils.getChildView;
import static app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController.videoHasSegments;
import android.view.View;
import android.view.animation.Animation;
import android.widget.ImageView;
import java.lang.ref.WeakReference;
@ -47,7 +48,10 @@ public class VotingButtonController {
return;
}
if (animation) {
imageView.startAnimation(BottomControlButton.getButtonFadeIn());
Animation fadeIn = BottomControlButton.getButtonFadeIn();
if (fadeIn != null) {
imageView.startAnimation(fadeIn);
}
}
imageView.setVisibility(View.VISIBLE);
return;
@ -55,7 +59,10 @@ public class VotingButtonController {
if (imageView.getVisibility() == View.VISIBLE) {
imageView.clearAnimation();
if (animation) {
imageView.startAnimation(BottomControlButton.getButtonFadeOut());
Animation fadeOut = BottomControlButton.getButtonFadeOut();
if (fadeOut != null) {
imageView.startAnimation(fadeOut);
}
}
imageView.setVisibility(View.GONE);
}
@ -68,7 +75,10 @@ public class VotingButtonController {
imageView.clearAnimation();
imageView.startAnimation(BottomControlButton.getButtonFadeOutImmediate());
Animation fadeOutImmediate = BottomControlButton.getButtonFadeOutImmediate();
if (fadeOutImmediate != null) {
imageView.startAnimation(fadeOutImmediate);
}
imageView.setVisibility(View.GONE);
}