fix: resolve StackOverflowError in Module hookMethod, fix resource identifier mapping, and auto-publish release APKs in CI

This commit is contained in:
Rosie Val 2026-09-25 17:04:50 -04:00
parent 96e2755509
commit 47075c116e
4 changed files with 41 additions and 22 deletions

View file

@ -1,6 +1,13 @@
name: Build APK name: Build APK
on: [push] on:
push:
branches: [ "master" ]
tags: [ "v*", "V*" ]
workflow_dispatch:
permissions:
contents: write
jobs: jobs:
build: build:
@ -64,4 +71,24 @@ jobs:
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: app-release name: app-release
path: /tmp/ShiggyXposedbuild/apks/app-release.apk path: /tmp/ShiggyXposedbuild/apks/app-release.apk
- name: Publish APKs to GitHub Release
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/master'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
TAG_NAME="${GITHUB_REF#refs/tags/}"
else
TAG_NAME=$(gh release view --json tagName -q .tagName 2>/dev/null || echo "")
fi
if [ -n "$TAG_NAME" ]; then
echo "Uploading APKs to release $TAG_NAME..."
gh release upload "$TAG_NAME" \
/tmp/ShiggyXposedbuild/apks/app-release.apk \
/tmp/ShiggyXposedbuild/apks/app-debug.apk \
--clobber
else
echo "No release tag found to upload assets to."
fi

View file

@ -71,14 +71,16 @@ class Main : Module(), IXposedHookLoadPackage, IXposedHookZygoteInit {
override fun handleLoadPackage(param: XC_LoadPackage.LoadPackageParam) = with(param) { override fun handleLoadPackage(param: XC_LoadPackage.LoadPackageParam) = with(param) {
if (!isTargetPackage(packageName)) return if (!isTargetPackage(packageName)) return
if (processName != packageName) return if (processName.contains(":")) return
if (hooked) return if (hooked) return
val activityClassNames = listOf( val activityClassNames = listOf(
Constants.TARGET_ACTIVITY, Constants.TARGET_ACTIVITY,
"$packageName.react_activities.ReactActivity", "$packageName.react_activities.ReactActivity",
"com.discord.react_activities.ReactActivity", "com.discord.react_activities.ReactActivity",
"com.facebook.react.ReactActivity" "com.facebook.react.ReactActivity",
"com.discord.main.MainActivity",
"com.discord.main.MainDefault"
) )
var reactActivity: Class<*>? = null var reactActivity: Class<*>? = null
for (className in activityClassNames) { for (className in activityClassNames) {
@ -107,7 +109,8 @@ class Main : Module(), IXposedHookLoadPackage, IXposedHookZygoteInit {
val act = thisObject as Activity val act = thisObject as Activity
if (reactActivity == null && if (reactActivity == null &&
!act.javaClass.name.contains("ReactActivity", ignoreCase = true) && !act.javaClass.name.contains("ReactActivity", ignoreCase = true) &&
!act.javaClass.name.contains("MainActivity", ignoreCase = true) !act.javaClass.name.contains("MainActivity", ignoreCase = true) &&
!act.javaClass.name.contains("MainDefault", ignoreCase = true)
) { ) {
return@after return@after
} }

View file

@ -73,19 +73,6 @@ open class Module {
open fun onResume(activity: Activity) {} open fun onResume(activity: Activity) {}
open fun onPause(activity: Activity) {} open fun onPause(activity: Activity) {}
protected fun Context.getAppInfo(): AppInfo = (this as Context).getAppInfo()
protected fun File.asDir(): File = (this as File).asDir()
protected fun File.asFile(): File = (this as File).asFile()
protected fun ClassLoader.safeLoadClass(name: String): Class<*>? = (this as ClassLoader).safeLoadClass(name)
protected fun Class<*>.method(name: String, vararg parameterTypes: Class<*>?): Method = (this as Class<*>).method(name, *parameterTypes)
protected fun Method.hook(hook: XC_MethodHook): XC_MethodHook.Unhook = (this as Method).hook(hook)
protected fun Method.hook(block: MethodHookBuilder.() -> Unit): XC_MethodHook.Unhook = (this as Method).hook(block)
protected fun Class<*>.hookMethod(
name: String,
vararg parameterTypes: Class<*>?,
block: MethodHookBuilder.() -> Unit
): XC_MethodHook.Unhook = (this as Class<*>).hookMethod(name, *parameterTypes, block = block)
} }
/** /**
@ -183,10 +170,12 @@ fun Class<*>.hookMethod(
name: String, name: String,
vararg parameterTypes: Class<*>?, vararg parameterTypes: Class<*>?,
block: MethodHookBuilder.() -> Unit block: MethodHookBuilder.() -> Unit
): XC_MethodHook.Unhook { ): XC_MethodHook.Unhook? = runCatching {
val method = method(name, *parameterTypes) val method = method(name, *parameterTypes)
return method.hook(block) method.hook(block)
} }.onFailure {
Log.w("Failed to hook method $name on ${this.name}: ${it.message}")
}.getOrNull()
fun File.asDir(): File { fun File.asDir(): File {
if (!exists() || !isDirectory) mkdirs() if (!exists() || !isDirectory) mkdirs()

View file

@ -16,7 +16,7 @@ object FixResourcesModule : Module() {
"getIdentifier", String::class.java, String::class.java, String::class.java "getIdentifier", String::class.java, String::class.java, String::class.java
) { ) {
before { before {
if (args[2] == packageName) args[2] = TARGET_PACKAGE if (args[2] == TARGET_PACKAGE) args[2] = packageName
} }
} }
} }