diff --git a/app/build.gradle b/app/build.gradle index 1ab56b38..cd2289d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -52,4 +52,7 @@ dependencies { //AndroidX Core implementation 'androidx.core:core-ktx:1.8.0' + + // OkHttp + implementation 'com.squareup.okhttp3:okhttp:4.9.0' } \ No newline at end of file diff --git a/app/src/main/java/com/grindrplus/Hooker.kt b/app/src/main/java/com/grindrplus/Hooker.kt index fe512ee2..77e12d92 100644 --- a/app/src/main/java/com/grindrplus/Hooker.kt +++ b/app/src/main/java/com/grindrplus/Hooker.kt @@ -25,6 +25,7 @@ class Hooker : IXposedHookLoadPackage { pkgParam = lpparam try { + Logger.xLog("About to hook App Updates") Hooks.hookAppUpdates() } catch (e: Exception) { e.message?.let { Logger.xLog(it) } diff --git a/app/src/main/java/com/grindrplus/Hooks.kt b/app/src/main/java/com/grindrplus/Hooks.kt index 50fad86a..d161e412 100644 --- a/app/src/main/java/com/grindrplus/Hooks.kt +++ b/app/src/main/java/com/grindrplus/Hooks.kt @@ -3,6 +3,7 @@ package com.grindrplus import android.R.attr.classLoader import android.os.Build import android.os.Bundle +import android.util.Log import android.util.TypedValue import android.view.Gravity import android.view.View @@ -25,6 +26,12 @@ import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers.* +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Call +import okhttp3.Callback +import okhttp3.Response +import java.io.IOException import java.io.File import java.lang.reflect.Proxy import java.util.* @@ -1066,6 +1073,41 @@ object Hooks { * and spoof the app version. Inspired by @Tebbe's idea. */ fun hookAppUpdates() { + val client = OkHttpClient() + val request = Request.Builder() + .url("https://apkpure.com/grindr-gay-chat-for-android/com.grindrapp.android/download") + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0") + .build() + + client.newCall(request).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + Logger.log("Fetch failed: ${e.message}") + } + + override fun onResponse(call: Call, response: Response) { + response.use { + if (!response.isSuccessful) + return Logger.xLog("Received unexpected response code: ${response.code}") + + val responseBody = response.body?.string() ?: + return Logger.xLog("Unable to get body from response!") + val versionName = """"versionName":"(.*?)",""".toRegex() + .find(responseBody)?.groups?.get(1)?.value + val versionCode = """"versionCode":(\d+),""".toRegex() + .find(responseBody)?.groups?.get(1)?.value + + // If both are valid, spoof the app version to prevent the update dialog + // from showing up. This should be enough to disable forced updates. + if (versionName != null && versionCode != null) { + hookUpdateInfo(versionName, versionCode.toInt()) + } + } + } + }) + } + + fun hookUpdateInfo(versionName: String, versionCode: Int) { + Logger.xLog("Hooking update info with version $versionName ($versionCode)") findAndHookMethod( "com.google.android.play.core.appupdate.AppUpdateInfo", Hooker.pkgParam.classLoader, @@ -1084,9 +1126,9 @@ object Hooks { findClass("com.grindrapp.android.base.config.AppConfiguration.a", Hooker.pkgParam.classLoader), object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { - setObjectField(param.thisObject, "a", "9.17.4") - setObjectField(param.thisObject, "b", 118992) - setObjectField(param.thisObject, "u", "9.17.4.118992") + setObjectField(param.thisObject, "a", versionName) + setObjectField(param.thisObject, "b", versionCode) + setObjectField(param.thisObject, "u", "$versionName.$versionCode") } } )