From c85761f92e6f98a2c872b2a84636b0f0bdf6c2e7 Mon Sep 17 00:00:00 2001 From: OTKUSteyler Date: Sat, 5 Sep 2026 12:21:42 +0200 Subject: [PATCH] Add files via upload --- .../ShiggyXposed/xposed/xposed/Module.kt | 207 ++++++++++++------ .../ShiggyXposed/xposed/xposed/Utils.kt | 2 +- 2 files changed, 147 insertions(+), 62 deletions(-) diff --git a/app/src/main/kotlin/ShiggyXposed/xposed/xposed/Module.kt b/app/src/main/kotlin/ShiggyXposed/xposed/xposed/Module.kt index fb4fcc8..15c904b 100644 --- a/app/src/main/kotlin/ShiggyXposed/xposed/xposed/Module.kt +++ b/app/src/main/kotlin/ShiggyXposed/xposed/xposed/Module.kt @@ -2,75 +2,160 @@ package GoonXposed.xposed import android.app.Activity import android.content.Context -import android.hardware.Sensor -import android.hardware.SensorEvent -import android.hardware.SensorEventListener -import android.hardware.SensorManager -import de.robv.android.xposed.IXposedHookLoadPackage +import android.content.pm.PackageManager +import de.robv.android.xposed.IXposedHookZygoteInit +import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge +import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.callbacks.XC_LoadPackage -import GoonXposed.xposed.modules.appearance.FontsModule +import kotlinx.serialization.json.JsonObjectBuilder +import java.io.File +import java.lang.reflect.Method -class MainModule : IXposedHookLoadPackage { - private var lastShakeTime: Long = 0 - private val SHAKE_THRESHOLD = 15f - private val SHAKE_INTERVAL_MS = 500L +/** + * Base class for every Xposed side module. + * + * The [Main] loader forwards the various [XC_LoadPackage] lifecycle callbacks to every + * registered [Module] instance. Modules may override any subset of the hooks below. + */ +open class Module { + open fun onInit(startupParam: IXposedHookZygoteInit.StartupParam) {} - override fun handleLoadPackage(lparam: XC_LoadPackage.LoadPackageParam) { - // Load the fonts module - FontsModule.onLoad(lparam) - - XposedBridge.log("GoonXposed: FontsModule loaded for ${lparam.packageName}") + open fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) {} - // Hook into the main activity to detect shakes - try { - val activityClass = Class.forName("android.app.Activity") - val method = activityClass.getDeclaredMethod("onCreate", Bundle::class.java) - - XposedBridge.hookMethod(method, object : XC_MethodHook() { - override fun afterHookedMethod(param: MethodHookParam) { - val activity = param.thisObject as Activity - setupShakeDetection(activity) - } - }) - } catch (e: Throwable) { - XposedBridge.log("GoonXposed: Failed to hook activity: ${e.message}") + open fun onContext(context: Context) {} + + open fun onActivity(activity: Activity) {} + + @Deprecated("This method is deprecated in the parent class") + open fun buildPayload(builder: JsonObjectBuilder) {} +} + +/** + * Runtime wrapper around an [XC_MethodHook.MethodHookParam] used as the receiver of every + * `before`/`after` hook block, exposing [thisObject], [args], [result] and [param] directly. + */ +class HookScope(val param: XC_MethodHook.MethodHookParam) { + val thisObject: Any? + get() = param.thisObject + + val args: Array + get() = param.args + + var result: Any? + get() = param.result + set(value) { + param.result = value + } + + var throwable: Throwable? + get() = param.throwable + set(value) { + param.throwable = value + } +} + +/** + * DSL builder for lazily constructed [XC_MethodHook] instances. + * + * ```kotlin + * val hook = MethodHookBuilder().run { + * before { result = null } + * after { Log.i("done") } + * build() + * } + * ``` + */ +class MethodHookBuilder { + private val beforeCallbacks = mutableListOf Unit>() + private val afterCallbacks = mutableListOf Unit>() + + fun before(callback: HookScope.() -> Unit) { + beforeCallbacks += callback + } + + fun after(callback: HookScope.() -> Unit) { + afterCallbacks += callback + } + + fun build(): XC_MethodHook = object : XC_MethodHook() { + override fun beforeHookedMethod(param: MethodHookParam) { + val scope = HookScope(param) + beforeCallbacks.forEach { scope.run(it) } + } + + override fun afterHookedMethod(param: MethodHookParam) { + val scope = HookScope(param) + afterCallbacks.forEach { scope.run(it) } } } - private fun setupShakeDetection(activity: Activity) { - try { - val sensorManager = activity.getSystemService(Context.SENSOR_SERVICE) as SensorManager - val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) - - if (accelerometer != null) { - sensorManager.registerListener(object : SensorEventListener { - override fun onSensorChanged(event: SensorEvent) { - val x = event.values[0] - val y = event.values[1] - val z = event.values[2] - - val acceleration = Math.sqrt((x * x + y * y + z * z).toDouble()).toFloat() - val currentTime = System.currentTimeMillis() - - if (acceleration > SHAKE_THRESHOLD && - currentTime - lastShakeTime > SHAKE_INTERVAL_MS) { - lastShakeTime = currentTime - onShakeDetected(activity) - } - } - - override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {} - }, accelerometer, SensorManager.SENSOR_DELAY_UI) - } - } catch (e: Throwable) { - XposedBridge.log("GoonXposed: Failed to setup shake detection: ${e.message}") + companion object { + fun from(block: MethodHookBuilder.() -> Unit): XC_MethodHook = MethodHookBuilder().run { + block() + build() } } - - private fun onShakeDetected(activity: Activity) { - XposedBridge.log("GoonXposed: Shake detected!") - // You can show a toast or dialog here - // Or launch your UI - } } + +fun ClassLoader.safeLoadClass(name: String): Class<*>? = try { + loadClass(name) +} catch (e: Throwable) { + null +} + +fun Class<*>.method(name: String, vararg parameterTypes: Class<*>): Method = + XposedHelpers.findMethodExact(this, name, *parameterTypes) + +fun Method.hook(block: MethodHookBuilder.() -> Unit) { + val builder = MethodHookBuilder() + builder.block() + XposedBridge.hookMethod(this, builder.build()) +} + +fun Method.hook(hook: XC_MethodHook) { + XposedBridge.hookMethod(this, hook) +} + +fun Class<*>.hookMethod( + name: String, + vararg parameterTypes: Class<*>, + block: MethodHookBuilder.() -> Unit +): Method { + val method = method(name, *parameterTypes) + method.hook(block) + return method +} + +fun File.asDir(): File { + if (!exists() || !isDirectory) mkdirs() + return this +} + +fun File.asFile(): File { + parentFile?.mkdirs() + return this +} + +data class AppInfo( + val name: String, + val packageName: String, + val version: String, + val versionCode: Int +) + +fun Context.getAppInfo(): AppInfo { + val label = applicationInfo.loadLabel(packageManager).toString() + val packageInfo = try { + packageManager.getPackageInfo(packageName, 0) + } catch (e: PackageManager.NameNotFoundException) { + null + } + + return AppInfo( + name = label, + packageName = packageName, + version = packageInfo?.versionName ?: "", + versionCode = packageInfo?.versionCode ?: 0 + ) +} \ No newline at end of file diff --git a/app/src/main/kotlin/ShiggyXposed/xposed/xposed/Utils.kt b/app/src/main/kotlin/ShiggyXposed/xposed/xposed/Utils.kt index af27662..e3a5ac3 100644 --- a/app/src/main/kotlin/ShiggyXposed/xposed/xposed/Utils.kt +++ b/app/src/main/kotlin/ShiggyXposed/xposed/xposed/Utils.kt @@ -1,9 +1,9 @@ package GoonXposed.xposed import android.app.AlertDialog -import android.app.AndroidAppHelper import android.content.Context import android.content.Intent +import de.robv.android.xposed.AndroidAppHelper import GoonXposed.xposed.modules.UpdaterModule import kotlinx.serialization.json.Json import java.io.File