fix(TikTok): Hook application context earlier to prevent crash (#588)

This commit is contained in:
LisoUseInAIKyrios 2024-03-18 04:21:16 +04:00 committed by GitHub
parent 74b6ab8712
commit 9ac2d63489
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 57 additions and 33 deletions

View File

@ -5,14 +5,15 @@ import static app.revanced.integrations.shared.settings.BaseSettings.DEBUG_STACK
import static app.revanced.integrations.shared.settings.BaseSettings.DEBUG_TOAST_ON_ERROR; import static app.revanced.integrations.shared.settings.BaseSettings.DEBUG_TOAST_ON_ERROR;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.revanced.integrations.shared.settings.BaseSettings;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import app.revanced.integrations.shared.settings.BaseSettings;
public class Logger { public class Logger {
/** /**
@ -24,7 +25,7 @@ public class Logger {
/** /**
* @return For outer classes, this returns {@link Class#getSimpleName()}. * @return For outer classes, this returns {@link Class#getSimpleName()}.
* For inner, static, or anonymous classes, this returns the simple name of the enclosing class.<br> * For static, inner, or anonymous classes, this returns the simple name of the enclosing class.
* <br> * <br>
* For example, each of these classes return 'SomethingView': * For example, each of these classes return 'SomethingView':
* <code> * <code>
@ -38,13 +39,13 @@ public class Logger {
String fullClassName = selfClass.getName(); String fullClassName = selfClass.getName();
final int dollarSignIndex = fullClassName.indexOf('$'); final int dollarSignIndex = fullClassName.indexOf('$');
if (dollarSignIndex == -1) { if (dollarSignIndex < 0) {
return selfClass.getSimpleName(); // already an outer class return selfClass.getSimpleName(); // Already an outer class.
} }
// class is inner, static, or anonymous // Class is inner, static, or anonymous.
// parse the simple name full name // Parse the simple name full name.
// a class with no package returns index of -1, but incrementing gives index zero which is correct // A class with no package returns index of -1, but incrementing gives index zero which is correct.
final int simpleClassNameStartIndex = fullClassName.lastIndexOf('.') + 1; final int simpleClassNameStartIndex = fullClassName.lastIndexOf('.') + 1;
return fullClassName.substring(simpleClassNameStartIndex, dollarSignIndex); return fullClassName.substring(simpleClassNameStartIndex, dollarSignIndex);
} }
@ -137,11 +138,19 @@ public class Logger {
} }
/** /**
* Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#context} may not be initialized. * Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized.
* Always logs even if Debugging is not enabled.
* Normally this method should not be used. * Normally this method should not be used.
*/ */
public static void initializationError(@NonNull Class<?> callingClass, @NonNull String message, @Nullable Exception ex) { public static void initializationInfo(@NonNull Class<?> callingClass, @NonNull String message) {
Log.i(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message);
}
/**
* Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized.
* Normally this method should not be used.
*/
public static void initializationException(@NonNull Class<?> callingClass, @NonNull String message,
@Nullable Exception ex) {
Log.e(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message, ex); Log.e(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message, ex);
} }

View File

@ -54,13 +54,14 @@ public class Utils {
try { try {
final var packageName = Objects.requireNonNull(getContext()).getPackageName(); final var packageName = Objects.requireNonNull(getContext()).getPackageName();
PackageManager packageManager = context.getPackageManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
packageInfo = context.getPackageManager().getPackageInfo( packageInfo = packageManager.getPackageInfo(
packageName, packageName,
PackageManager.PackageInfoFlags.of(0) PackageManager.PackageInfoFlags.of(0)
); );
else else
packageInfo = context.getPackageManager().getPackageInfo( packageInfo = packageManager.getPackageInfo(
packageName, packageName,
0 0
); );
@ -228,14 +229,23 @@ public class Utils {
public static Context getContext() { public static Context getContext() {
if (context == null) { if (context == null) {
Logger.initializationError(Utils.class, "Context is null, returning null!", null); Logger.initializationException(Utils.class, "Context is null, returning null!", null);
} }
return context; return context;
} }
public static void setContext(Context appContext) { public static void setContext(Context appContext) {
context = appContext; context = appContext;
Logger.printDebug(() -> "Set context: " + appContext); // Cannot log before context is set. // In some apps like TikTok, the Setting classes can load in weird orders due to cyclic class dependencies.
// Calling the regular printDebug method here can cause a Settings context null pointer exception,
// even though the context is already set before the call.
//
// The initialization logger methods do not directly or indirectly
// reference the Context or any Settings and are unaffected by this problem.
//
// Info level also helps debug if a patch hook is called before
// the context is set since debug logging is off by default.
Logger.initializationInfo(Utils.class, "Set context: " + appContext);
} }
public static void setClipboard(@NonNull String text) { public static void setClipboard(@NonNull String text) {
@ -280,7 +290,7 @@ public class Utils {
Objects.requireNonNull(messageToToast); Objects.requireNonNull(messageToToast);
runOnMainThreadNowOrLater(() -> { runOnMainThreadNowOrLater(() -> {
if (context == null) { if (context == null) {
Logger.initializationError(Utils.class, "Cannot show toast (context is null): " + messageToToast, null); Logger.initializationException(Utils.class, "Cannot show toast (context is null): " + messageToToast, null);
} else { } else {
Logger.printDebug(() -> "Showing toast: " + messageToToast); Logger.printDebug(() -> "Showing toast: " + messageToToast);
Toast.makeText(context, messageToToast, toastDuration).show(); Toast.makeText(context, messageToToast, toastDuration).show();

View File

@ -1,32 +1,37 @@
package app.revanced.integrations.tiktok.spoof.sim; package app.revanced.integrations.tiktok.spoof.sim;
import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.tiktok.settings.Settings; import app.revanced.integrations.tiktok.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class SpoofSimPatch { public class SpoofSimPatch {
public static boolean isEnable() {
return Settings.SIM_SPOOF.get();
}
public static String getCountryIso(String value) {
if (isEnable()) {
return Settings.SIM_SPOOF_ISO.get();
} else {
return value;
}
private static final Boolean ENABLED = Settings.SIM_SPOOF.get();
public static String getCountryIso(String value) {
if (ENABLED) {
String iso = Settings.SIM_SPOOF_ISO.get();
Logger.printDebug(() -> "Spoofing sim ISO from: " + value + " to: " + iso);
return iso;
}
return value;
} }
public static String getOperator(String value) { public static String getOperator(String value) {
if (isEnable()) { if (ENABLED) {
return Settings.SIMSPOOF_MCCMNC.get(); String mcc_mnc = Settings.SIMSPOOF_MCCMNC.get();
} else { Logger.printDebug(() -> "Spoofing sim MCC-MNC from: " + value + " to: " + mcc_mnc);
return value; return mcc_mnc;
} }
return value;
} }
public static String getOperatorName(String value) { public static String getOperatorName(String value) {
if (isEnable()) { if (ENABLED) {
return Settings.SIMSPOOF_OP_NAME.get(); String operator = Settings.SIMSPOOF_OP_NAME.get();
} else { Logger.printDebug(() -> "Spoofing sim operator from: " + value + " to: " + operator);
return value; return operator;
} }
return value;
} }
} }