merge changes from KettuXposed and bump to 1.2.1
only issue is not working recovery menu, but who cares?
This commit is contained in:
parent
5b510a9552
commit
056d6d81d9
14 changed files with 131 additions and 123 deletions
|
|
@ -12,8 +12,8 @@ android {
|
|||
applicationId = "ShiggyXposed.xposed"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 1200
|
||||
versionName = "1.2.0"
|
||||
versionCode = 1210
|
||||
versionName = "1.2.1"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
|
|
|||
|
|
@ -35,24 +35,24 @@ object HookStateHolder {
|
|||
|
||||
class Main : Module(), IXposedHookLoadPackage, IXposedHookZygoteInit {
|
||||
private var hooked = false
|
||||
private val modules = mutableListOf(
|
||||
HookScriptLoaderModule(),
|
||||
BridgeModule(),
|
||||
AdditionalBridgeMethodsModule(),
|
||||
private val modules = mutableListOf<Module>(
|
||||
HookScriptLoaderModule,
|
||||
BridgeModule,
|
||||
AdditionalBridgeMethodsModule,
|
||||
PluginsModule(),
|
||||
UpdaterModule,
|
||||
FixResourcesModule(),
|
||||
BlockDeepLinksTrackingModule(),
|
||||
BlockCrashReportingModule(),
|
||||
LogBoxModule(),
|
||||
CacheModule(),
|
||||
FontsModule(),
|
||||
ThemesModule(),
|
||||
SysColorsModule()
|
||||
FixResourcesModule,
|
||||
BlockDeepLinksTrackingModule,
|
||||
BlockCrashReportingModule,
|
||||
LogBoxModule,
|
||||
CacheModule,
|
||||
FontsModule,
|
||||
ThemesModule,
|
||||
SysColorsModule
|
||||
)
|
||||
|
||||
init {
|
||||
modules.add(PayloadGlobalModule(modules))
|
||||
modules += PayloadGlobalModule(modules)
|
||||
}
|
||||
|
||||
override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) {
|
||||
|
|
|
|||
|
|
@ -33,30 +33,30 @@ import java.io.*
|
|||
* The caches are versioned and tied to the app version code. When the app is updated,
|
||||
* the caches are invalidated and new cache files are created.
|
||||
*/
|
||||
class CacheModule : Module() {
|
||||
private companion object {
|
||||
const val CACHE_DIR = "Shiggy"
|
||||
object CacheModule : Module() {
|
||||
|
||||
private const val CACHE_DIR = "revenge"
|
||||
|
||||
private const val MODULES_CACHE_PREFIX = "modules"
|
||||
private const val ASSETS_CACHE_PREFIX = "assets"
|
||||
|
||||
const val MODULES_CACHE_PREFIX = "modules"
|
||||
const val ASSETS_CACHE_PREFIX = "assets"
|
||||
}
|
||||
|
||||
private lateinit var modulesCache: ModulesCache
|
||||
private lateinit var assetsCache: AssetsCache
|
||||
|
||||
override fun onContext(context: Context) = with(context) {
|
||||
val ShiggyCacheDir = File(cacheDir, CACHE_DIR).apply { asDir() }
|
||||
val revengeCacheDir = File(cacheDir, CACHE_DIR).apply { asDir() }
|
||||
val (_, _, _, versionCode) = getAppInfo()
|
||||
|
||||
val modulesCacheFile = File(
|
||||
ShiggyCacheDir, "$MODULES_CACHE_PREFIX.$versionCode"
|
||||
revengeCacheDir, "$MODULES_CACHE_PREFIX.$versionCode"
|
||||
).apply { asFile() }
|
||||
|
||||
val assetsCacheFile = File(
|
||||
ShiggyCacheDir, "$ASSETS_CACHE_PREFIX.$versionCode"
|
||||
revengeCacheDir, "$ASSETS_CACHE_PREFIX.$versionCode"
|
||||
).apply { asFile() }
|
||||
|
||||
BridgeModule.registerMethod("Shiggy.caches.modules.read") {
|
||||
BridgeModule.registerMethod("revenge.caches.modules.read") {
|
||||
if (::modulesCache.isInitialized) modulesCache.toMap() else ModulesCache.loadFromFileOrNull(modulesCacheFile)
|
||||
?.let {
|
||||
modulesCache = it
|
||||
|
|
@ -64,7 +64,7 @@ class CacheModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("Shiggy.caches.modules.write") {
|
||||
BridgeModule.registerMethod("revenge.caches.modules.write") {
|
||||
val (blacklist, finds) = it
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
modulesCache = ModulesCache(
|
||||
|
|
@ -73,7 +73,7 @@ class CacheModule : Module() {
|
|||
Log.i("Modules cache saved: ${modulesCacheFile.absolutePath} (blacklisted: ${blacklist.size}, finds: ${finds.size})")
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("Shiggy.caches.assets.read") {
|
||||
BridgeModule.registerMethod("revenge.caches.assets.read") {
|
||||
if (::assetsCache.isInitialized) assetsCache.toMap() else AssetsCache.loadFromFileOrNull(assetsCacheFile)
|
||||
?.let {
|
||||
assetsCache = it
|
||||
|
|
@ -81,7 +81,7 @@ class CacheModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
BridgeModule.registerMethod("Shiggy.caches.assets.write") {
|
||||
BridgeModule.registerMethod("revenge.caches.assets.write") {
|
||||
val (data) = it
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
assetsCache =
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import ShiggyXposed.xposed.Module
|
|||
/**
|
||||
* Hooks [Resources.getIdentifier] to fix resource package name mismatch.
|
||||
*/
|
||||
class FixResourcesModule : Module() {
|
||||
object FixResourcesModule : Module() {
|
||||
override fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) = with(packageParam) {
|
||||
if (packageName != TARGET_PACKAGE) {
|
||||
Resources::class.java.hookMethod(
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import ShiggyXposed.xposed.Constants
|
|||
import ShiggyXposed.xposed.HookStateHolder
|
||||
import ShiggyXposed.xposed.Module
|
||||
import ShiggyXposed.xposed.Utils.Log
|
||||
import ShiggyXposed.xposed.modules.HookScriptLoaderModule.Companion.PRELOADS_DIR
|
||||
import ShiggyXposed.xposed.modules.HookScriptLoaderModule.PRELOADS_DIR
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
|
@ -24,16 +24,14 @@ import java.lang.reflect.Method
|
|||
* The main bundle should be placed in the [Constants.CACHE_DIR] directory named [Constants.MAIN_SCRIPT_FILE].
|
||||
* If the bundle file does not exist, it will attempt to load `assets://Shiggy.bundle` from the module's assets.
|
||||
*/
|
||||
class HookScriptLoaderModule : Module() {
|
||||
object HookScriptLoaderModule : Module() {
|
||||
private lateinit var preloadsDir: File
|
||||
private lateinit var mainScript: File
|
||||
|
||||
private lateinit var modulePath: String
|
||||
private lateinit var resources: XModuleResources
|
||||
|
||||
companion object {
|
||||
const val PRELOADS_DIR = "preloads"
|
||||
}
|
||||
const val PRELOADS_DIR = "preloads"
|
||||
|
||||
override fun onInit(startupParam: IXposedHookZygoteInit.StartupParam) {
|
||||
this@HookScriptLoaderModule.modulePath = startupParam.modulePath
|
||||
|
|
@ -47,26 +45,20 @@ class HookScriptLoaderModule : Module() {
|
|||
mainScript = File(cacheDir, Constants.MAIN_SCRIPT_FILE).apply { asFile() }
|
||||
|
||||
listOf(
|
||||
"com.facebook.react.runtime.ReactInstance\$loadJSBundle$1",
|
||||
"com.facebook.react.runtime.ReactInstance$1",
|
||||
// TODO: Remove once Discord fully switches to Bridgeless
|
||||
"com.facebook.react.bridge.CatalystInstanceImpl"
|
||||
).mapNotNull { classLoader.safeLoadClass(it) }
|
||||
.forEach { hook(it) }
|
||||
).mapNotNull { classLoader.safeLoadClass(it) }.forEach { hook(it) }
|
||||
}
|
||||
|
||||
private fun hook(instance: Class<*>) {
|
||||
private fun hook(instance: Class<*>) = runCatching {
|
||||
val loadScriptFromAssets = instance.method(
|
||||
"loadScriptFromAssets",
|
||||
AssetManager::class.java,
|
||||
String::class.java,
|
||||
Boolean::class.javaPrimitiveType
|
||||
"loadScriptFromAssets", AssetManager::class.java, String::class.java, Boolean::class.javaPrimitiveType
|
||||
)
|
||||
|
||||
val loadScriptFromFile = instance.method(
|
||||
"loadScriptFromFile",
|
||||
String::class.java,
|
||||
String::class.java,
|
||||
Boolean::class.javaPrimitiveType
|
||||
"loadScriptFromFile", String::class.java, String::class.java, Boolean::class.javaPrimitiveType
|
||||
)
|
||||
|
||||
loadScriptFromAssets.hook {
|
||||
|
|
@ -82,6 +74,8 @@ class HookScriptLoaderModule : Module() {
|
|||
runCustomScripts(loadScriptFromFile, loadScriptFromAssets)
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
Log.e("Failed to hook script loading methods in ${instance.name}:", it)
|
||||
}
|
||||
|
||||
private fun HookScope.runCustomScripts(loadScriptFromFile: Method, loadScriptFromAssets: Method) {
|
||||
|
|
@ -99,25 +93,20 @@ class HookScriptLoaderModule : Module() {
|
|||
Log.i("Loading script: ${file.absolutePath}")
|
||||
|
||||
XposedBridge.invokeOriginalMethod(
|
||||
loadScriptFromFile,
|
||||
thisObject,
|
||||
arrayOf(file.absolutePath, file.absolutePath, loadSynchronously)
|
||||
loadScriptFromFile, thisObject, arrayOf(file.absolutePath, file.absolutePath, loadSynchronously)
|
||||
)
|
||||
|
||||
Unit
|
||||
}
|
||||
|
||||
try {
|
||||
preloadsDir.walk()
|
||||
.filter { it.isFile }
|
||||
.forEach(runScriptFile)
|
||||
preloadsDir.walk().filter { it.isFile }.forEach(runScriptFile)
|
||||
|
||||
if (mainScript.exists()) runScriptFile(mainScript)
|
||||
else {
|
||||
Log.i("Main script does not exist, falling back")
|
||||
|
||||
if (!::resources.isInitialized) resources =
|
||||
XModuleResources.createInstance(modulePath, null)
|
||||
if (!::resources.isInitialized) resources = XModuleResources.createInstance(modulePath, null)
|
||||
|
||||
XposedBridge.invokeOriginalMethod(
|
||||
loadScriptFromAssets,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import java.net.HttpURLConnection
|
|||
import java.net.URL
|
||||
import ShiggyXposed.xposed.Utils.Companion.reloadApp
|
||||
|
||||
class LogBoxModule : Module() {
|
||||
object LogBoxModule : Module() {
|
||||
lateinit var packageParam: XC_LoadPackage.LoadPackageParam
|
||||
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import ShiggyXposed.xposed.BuildConfig
|
|||
import ShiggyXposed.xposed.Constants
|
||||
import ShiggyXposed.xposed.Module
|
||||
import ShiggyXposed.xposed.Utils.Companion.JSON
|
||||
import ShiggyXposed.xposed.modules.HookScriptLoaderModule.Companion.PRELOADS_DIR
|
||||
import ShiggyXposed.xposed.modules.HookScriptLoaderModule.PRELOADS_DIR
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
import java.io.File
|
||||
|
|
@ -28,7 +28,8 @@ class PayloadGlobalModule(private val modules: List<Module>) : Module() {
|
|||
|
||||
override fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) = with(packageParam) {
|
||||
val catalystInstance = classLoader.safeLoadClass("com.facebook.react.bridge.CatalystInstanceImpl")
|
||||
val reactInstance = classLoader.safeLoadClass("com.facebook.react.runtime.ReactInstance$1")
|
||||
val scriptLoader = classLoader.safeLoadClass("com.facebook.react.runtime.ReactInstance\$loadJSBundle$1")
|
||||
?: classLoader.safeLoadClass("com.facebook.react.runtime.ReactInstance$1")
|
||||
|
||||
val setGlobalVariable: (XC_MethodHook.MethodHookParam, String, String) -> Unit = { param, key, json ->
|
||||
runCatching {
|
||||
|
|
@ -43,7 +44,7 @@ class PayloadGlobalModule(private val modules: List<Module>) : Module() {
|
|||
writeText("this[${JSON.encodeToString(key)}]=$json")
|
||||
|
||||
XposedBridge.invokeOriginalMethod(
|
||||
reactInstance!!.method(
|
||||
scriptLoader!!.method(
|
||||
"loadScriptFromFile",
|
||||
String::class.java,
|
||||
String::class.java,
|
||||
|
|
@ -64,7 +65,7 @@ class PayloadGlobalModule(private val modules: List<Module>) : Module() {
|
|||
build()
|
||||
}
|
||||
|
||||
listOf(catalystInstance, reactInstance).forEach { if (it != null) hook(it, hook) }
|
||||
listOf(catalystInstance, scriptLoader).forEach { if (it != null) hook(it, hook) }
|
||||
}
|
||||
|
||||
private fun hook(instance: Class<*>, hook: XC_MethodHook) {
|
||||
|
|
|
|||
|
|
@ -35,12 +35,10 @@ data class FontDefinition(
|
|||
val main: Map<String, String>,
|
||||
)
|
||||
|
||||
class FontsModule : Module() {
|
||||
private companion object {
|
||||
val EXTENSIONS = arrayOf("", "_bold", "_italic", "_bold_italic")
|
||||
val FILE_EXTENSIONS = arrayOf(".ttf", ".otf")
|
||||
const val FONTS_ASSET_PATH = "fonts/"
|
||||
}
|
||||
object FontsModule : Module() {
|
||||
private val EXTENSIONS = arrayOf("", "_bold", "_italic", "_bold_italic")
|
||||
private val FILE_EXTENSIONS = arrayOf(".ttf", ".otf")
|
||||
private const val FONTS_ASSET_PATH = "fonts/"
|
||||
|
||||
private lateinit var fontsDir: File
|
||||
private lateinit var fontsDownloadsDir: File
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@ import android.os.Build
|
|||
import androidx.core.content.ContextCompat
|
||||
import ShiggyXposed.xposed.Module
|
||||
import kotlinx.serialization.json.*
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
class SysColorsModule : Module() {
|
||||
private lateinit var context: Context
|
||||
object SysColorsModule : Module() {
|
||||
private lateinit var context: WeakReference<Context>
|
||||
private fun isSupported() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
||||
|
||||
override fun buildPayload(builder: JsonObjectBuilder) {
|
||||
context = AndroidAppHelper.currentApplication()
|
||||
context = WeakReference(AndroidAppHelper.currentApplication())
|
||||
val accents = arrayOf("accent1", "accent2", "accent3", "neutral1", "neutral2")
|
||||
val shades = arrayOf(0, 10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000)
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ class SysColorsModule : Module() {
|
|||
}
|
||||
|
||||
private fun convertToColor(id: Int): String {
|
||||
val clr = if (isSupported()) ContextCompat.getColor(context, id) else 0
|
||||
val clr = if (isSupported()) ContextCompat.getColor(context.get()!!, id) else 0
|
||||
return String.format("#%06X", 0xFFFFFF and clr)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,15 +34,14 @@ data class Theme(
|
|||
val id: String, val selected: Boolean, val data: ThemeData
|
||||
)
|
||||
|
||||
class ThemesModule : Module() {
|
||||
object ThemesModule : Module() {
|
||||
private lateinit var param: XC_LoadPackage.LoadPackageParam
|
||||
|
||||
private var theme: Theme? = null
|
||||
private val rawColorMap = mutableMapOf<String, Int>()
|
||||
|
||||
private companion object {
|
||||
const val THEME_FILE = "current-theme.json"
|
||||
}
|
||||
private const val THEME_FILE = "current-theme.json"
|
||||
|
||||
|
||||
@ExperimentalSerializationApi
|
||||
override fun buildPayload(builder: JsonObjectBuilder) {
|
||||
|
|
@ -62,7 +61,7 @@ class ThemesModule : Module() {
|
|||
hookTheme()
|
||||
}
|
||||
|
||||
private fun File.isValidish(): Boolean {
|
||||
private fun File.isValidThemeFile(): Boolean {
|
||||
if (!this.exists()) return false
|
||||
|
||||
val text = this.readText()
|
||||
|
|
@ -71,7 +70,7 @@ class ThemesModule : Module() {
|
|||
|
||||
private fun getTheme(): Theme? {
|
||||
val themeFile = File(param.appInfo.dataDir, "${Constants.FILES_DIR}/${THEME_FILE}").apply { asFile() }
|
||||
if (!themeFile.isValidish()) return null
|
||||
if (!themeFile.isValidThemeFile()) return null
|
||||
|
||||
return try {
|
||||
val themeText = themeFile.readText()
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import ShiggyXposed.xposed.Module
|
|||
import ShiggyXposed.xposed.Utils
|
||||
import java.io.File
|
||||
|
||||
class AdditionalBridgeMethodsModule : Module() {
|
||||
object AdditionalBridgeMethodsModule : Module() {
|
||||
override fun onContext(context: Context) = with(context) {
|
||||
BridgeModule.registerMethod("Shiggy.fs.getConstants") {
|
||||
mapOf(
|
||||
|
|
|
|||
|
|
@ -45,43 +45,28 @@ typealias BridgeMethodArgs = ArrayList<Any>
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
class BridgeModule : Module() {
|
||||
object BridgeModule : Module() {
|
||||
private lateinit var readableMapGetString: Method
|
||||
private lateinit var readableMapToHashMap: Method
|
||||
private lateinit var argumentsMakeNative: Method
|
||||
|
||||
companion object {
|
||||
private const val CALL_DATA_KEY = "Shiggy"
|
||||
private const val METHOD_NAME_KEY = "method"
|
||||
private const val METHOD_ARGS_KEY = "args"
|
||||
private const val CALL_DATA_KEY = "Shiggy"
|
||||
private const val METHOD_NAME_KEY = "method"
|
||||
private const val METHOD_ARGS_KEY = "args"
|
||||
|
||||
private val methods: MutableMap<String, BridgeMethodCallback> = mutableMapOf("Shiggy.info" to {
|
||||
mapOf(
|
||||
"name" to Constants.LOADER_NAME, "version" to BuildConfig.VERSION_CODE
|
||||
)
|
||||
}, "Shiggy.test" to {
|
||||
mapOf(
|
||||
"string" to "string",
|
||||
"number" to 7256,
|
||||
"array" to listOf("testing", 527737, listOf(true)),
|
||||
"object" to mapOf("nested" to true),
|
||||
"boolean" to false,
|
||||
"args" to it,
|
||||
)
|
||||
})
|
||||
private val methods: MutableMap<String, BridgeMethodCallback> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* Registers a bridge method that can be called from JavaScript.
|
||||
*
|
||||
* If the method is already registered, it will be overwritten.
|
||||
*
|
||||
* @param name The name of the method to register.
|
||||
* @param callback The callback to invoke when the method is called.
|
||||
*/
|
||||
fun registerMethod(name: String, callback: BridgeMethodCallback) {
|
||||
if (methods.containsKey(name)) Log.w("Bridge method already exists and will be overridden: $name")
|
||||
methods[name] = callback
|
||||
}
|
||||
/**
|
||||
* Registers a bridge method that can be called from JavaScript.
|
||||
*
|
||||
* If the method is already registered, it will be overwritten.
|
||||
*
|
||||
* @param name The name of the method to register.
|
||||
* @param callback The callback to invoke when the method is called.
|
||||
*/
|
||||
fun registerMethod(name: String, callback: BridgeMethodCallback) {
|
||||
if (methods.containsKey(name)) Log.w("Bridge method already exists and will be overridden: $name")
|
||||
methods[name] = callback
|
||||
}
|
||||
|
||||
override fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) = with(packageParam) {
|
||||
|
|
@ -112,9 +97,32 @@ class BridgeModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
// Clear methods every package load. Plugins should re-register on each load.
|
||||
methods.clear()
|
||||
registerDefaultMethods()
|
||||
|
||||
return@with
|
||||
}
|
||||
|
||||
private fun registerDefaultMethods() {
|
||||
methods["Shiggy.info"] = {
|
||||
mapOf(
|
||||
"name" to Constants.LOADER_NAME, "version" to BuildConfig.VERSION_CODE
|
||||
)
|
||||
}
|
||||
|
||||
methods["Shiggy.test"] = {
|
||||
mapOf(
|
||||
"string" to "string",
|
||||
"number" to 7256,
|
||||
"array" to listOf("testing", 527737, listOf(true)),
|
||||
"object" to mapOf("nested" to true),
|
||||
"boolean" to false,
|
||||
"args" to it,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Any?.toNativeObject(): Any? = argumentsMakeNative.invoke(
|
||||
null, when (this) {
|
||||
Unit -> null
|
||||
|
|
|
|||
|
|
@ -9,26 +9,38 @@ import ShiggyXposed.xposed.Utils.Log
|
|||
* Hooks Discord's crash reporting to disable Sentry initialization.
|
||||
* While Discord doesn't have Sentry auto-initialization on by default, we still hook the content provider just to be safe.
|
||||
*/
|
||||
class BlockCrashReportingModule : Module() {
|
||||
object BlockCrashReportingModule : Module() {
|
||||
override fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) = with(packageParam) {
|
||||
val crashReportingClass = classLoader.safeLoadClass("com.discord.crash_reporting.CrashReporting")
|
||||
crashReportingClass?.hookMethod(
|
||||
"init", Context::class.java, String::class.java
|
||||
) {
|
||||
before {
|
||||
Log.i("Blocked CrashReporting initialization")
|
||||
result = null
|
||||
crashReportingClass?.apply {
|
||||
// Hooking this will result in a crash after a few seconds, since Discord expects initialization to complete when setting a Sentry tag.
|
||||
// So we also hook isDisabled to make sure those calls are no-ops.
|
||||
hookMethod(
|
||||
"init", Context::class.java, String::class.java
|
||||
) {
|
||||
before {
|
||||
Log.i("Blocked CrashReporting initialization")
|
||||
result = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sentryInitProviderClass = classLoader.safeLoadClass("io.sentry.android.core.SentryInitProvider")
|
||||
sentryInitProviderClass?.hookMethod("onCreate") {
|
||||
before {
|
||||
Log.i("Blocked SentryInitProvider initialization")
|
||||
result = true
|
||||
runCatching {
|
||||
hookMethod("isDisabled") {
|
||||
before {
|
||||
Log.i("Forced CrashReporting.isDisabled() to true")
|
||||
result = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return@with
|
||||
val sentryInitProviderClass = classLoader.safeLoadClass("io.sentry.android.core.SentryInitProvider")
|
||||
sentryInitProviderClass?.hookMethod("onCreate") {
|
||||
before {
|
||||
Log.i("Blocked SentryInitProvider initialization")
|
||||
result = true
|
||||
}
|
||||
}
|
||||
|
||||
return@with
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import ShiggyXposed.xposed.Utils.Log
|
|||
/**
|
||||
* Hooks Discord's deep links tracking to disable AppsFlyer initialization.
|
||||
*/
|
||||
class BlockDeepLinksTrackingModule : Module() {
|
||||
object BlockDeepLinksTrackingModule : Module() {
|
||||
override fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) = with(packageParam) {
|
||||
val deepLinksClass = classLoader.safeLoadClass("com.discord.deep_link.DeepLinks")
|
||||
deepLinksClass?.hookMethod(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue