Skip to content

Commit 730cafc

Browse files
committed
feat: Add patch-based settings manager
1 parent b2982a0 commit 730cafc

File tree

24 files changed

+630
-190
lines changed

24 files changed

+630
-190
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools">
44

5+
<uses-permission android:name="android.permission.INTERNET" />
6+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
7+
<uses-permission android:name="android.permission.VIBRATE" />
8+
9+
<queries>
10+
<package android:name="com.google.android.youtube" />
11+
<package android:name="com.google.android.apps.youtube.music" />
12+
<package android:name="com.reddit.frontpage" />
13+
<package android:name="com.google.android.apps.photos" />
14+
<package android:name="com.instagram.android" />
15+
<package android:name="com.instagram.barcelona" />
16+
<package android:name="com.strava" />
17+
<package android:name="com.microblink.photomath" />
18+
</queries>
19+
520
<application
621
android:icon="@mipmap/ic_launcher"
722
android:label="@string/app_name"
@@ -22,5 +37,22 @@
2237
android:name="xposedscope"
2338
android:resource="@array/scope" />
2439

40+
<activity
41+
android:name=".activity.SettingsActivity"
42+
android:exported="true"
43+
android:launchMode="singleTop"
44+
android:showForAllUsers="true"
45+
android:theme="@style/SettingsTheme">
46+
<intent-filter>
47+
<action android:name="android.intent.action.MAIN" />
48+
<category android:name="de.robv.android.xposed.category.MODULE_SETTINGS" />
49+
</intent-filter>
50+
</activity>
51+
52+
<activity
53+
android:name=".activity.AppPatchSettingsActivity"
54+
android:exported="false"
55+
android:parentActivityName=".activity.SettingsActivity"
56+
android:theme="@style/SettingsTheme" />
2557
</application>
2658
</manifest>

app/src/main/java/io/github/chsbuffer/revancedxposed/BaseHook.kt

Lines changed: 70 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import app.revanced.extension.shared.Logger
1111
import app.revanced.extension.shared.StringRef
1212
import app.revanced.extension.shared.Utils
1313
import de.robv.android.xposed.XC_MethodHook
14+
import de.robv.android.xposed.XSharedPreferences
1415
import de.robv.android.xposed.XposedBridge
1516
import de.robv.android.xposed.XposedHelpers
1617
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam
@@ -122,16 +123,23 @@ class DependedHookFailedException(
122123
) : Exception("Depended hook $subHookName failed.", exception)
123124

124125
@SuppressLint("CommitPrefEdits")
125-
abstract class BaseHook(private val app: Application, val lpparam: LoadPackageParam) : IHook {
126+
abstract class BaseHook(val appContext: Application, val lpparam: LoadPackageParam) : IHook {
126127
override val classLoader = lpparam.classLoader!!
127128

129+
/**
130+
* @see io.github.chsbuffer.revancedxposed.activity.AppPatchSettingsActivity.AppPatchSettingsFragment.onCreate
131+
* */
132+
val xpref = XSharedPreferences(
133+
BuildConfig.APPLICATION_ID, lpparam.packageName
134+
).takeIf { it.file.canRead() }
135+
128136
abstract val patches: Array<Patch>
129137
private val appliedPatches = mutableSetOf<Patch>()
130138
private val failedPatches = mutableListOf<Patch>()
131139

132140
// cache
133141
private val moduleRel = BuildConfig.COMMIT_HASH
134-
private var cache = SharedPrefCache(app)
142+
private var cache = SharedPrefCache(appContext)
135143
private var dexkit = run {
136144
System.loadLibrary("dexkit")
137145
DexKitCacheBridge.init(cache)
@@ -142,7 +150,7 @@ abstract class BaseHook(private val app: Application, val lpparam: LoadPackagePa
142150
val t = measureTimeMillis {
143151
tryLoadCache()
144152
try {
145-
applyHooks()
153+
applyPatches()
146154
handleResult()
147155
logDebugInfo()
148156
} finally {
@@ -156,7 +164,7 @@ abstract class BaseHook(private val app: Application, val lpparam: LoadPackagePa
156164
private fun tryLoadCache() {
157165
// cache by host update time + module version
158166
// also no cache if is DEBUG
159-
val packageInfo = app.packageManager.getPackageInfo(app.packageName, 0)
167+
val packageInfo = appContext.packageManager.getPackageInfo(appContext.packageName, 0)
160168

161169
val id = "${packageInfo.lastUpdateTime}-$moduleRel"
162170
val cachedId = cache.get("id", null)
@@ -173,9 +181,13 @@ abstract class BaseHook(private val app: Application, val lpparam: LoadPackagePa
173181
}
174182
}
175183

176-
private fun applyHooks() {
184+
private fun applyPatches() {
177185
patches.forEach { hook ->
178186
if (appliedPatches.contains(hook)) return@forEach
187+
/**
188+
* @see io.github.chsbuffer.revancedxposed.activity.AppPatchSettingsActivity.AppPatchSettingsFragment.onCreate
189+
* */
190+
if (xpref?.getBoolean(hook.name, true) == false) return@forEach // Pref Key
179191
runCatching { hook.run(this) }.onFailure { err ->
180192
XposedBridge.log(err)
181193
failedPatches.add(hook)
@@ -205,7 +217,7 @@ abstract class BaseHook(private val app: Application, val lpparam: LoadPackagePa
205217
}
206218

207219
private fun getAppVersion(): String {
208-
val packageInfo = app.packageManager.getPackageInfo(app.packageName, 0)
220+
val packageInfo = appContext.packageManager.getPackageInfo(appContext.packageName, 0)
209221
val versionName = packageInfo.versionName
210222
val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
211223
packageInfo.longVersionCode
@@ -226,59 +238,6 @@ abstract class BaseHook(private val app: Application, val lpparam: LoadPackagePa
226238
}
227239
}
228240

229-
val ExtensionResourceHook = patch {
230-
app.addModuleAssets()
231-
StringRef.resources = app.resources
232-
StringRef.packageName = BuildConfig.APPLICATION_ID
233-
StringRef.packageName2 = app.packageName
234-
235-
app.callMethod(
236-
"registerActivityLifecycleCallbacks",
237-
object : Application.ActivityLifecycleCallbacks {
238-
var handleWebView: Boolean = false
239-
240-
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
241-
Logger.printDebug { "onActivityCreated $activity" }
242-
if (!handleWebView) {
243-
// call only once to let webview add it's assets
244-
WebView(activity).destroy()
245-
app.addModuleAssets()
246-
StringRef.resources = app.resources
247-
StringRef.packageName = BuildConfig.APPLICATION_ID
248-
StringRef.packageName2 = app.packageName
249-
handleWebView = true
250-
}
251-
252-
activity.addModuleAssets()
253-
}
254-
255-
override fun onActivityDestroyed(activity: Activity) {
256-
Logger.printDebug { "onActivityDestroyed $activity" }
257-
}
258-
259-
override fun onActivityPaused(activity: Activity) {
260-
Logger.printDebug { "onActivityPaused $activity" }
261-
}
262-
263-
override fun onActivityResumed(activity: Activity) {
264-
Logger.printDebug { "onActivityResumed $activity" }
265-
activity.addModuleAssets()
266-
}
267-
268-
override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {
269-
Logger.printDebug { "onActivitySaveInstanceState $activity" }
270-
}
271-
272-
override fun onActivityStarted(activity: Activity) {
273-
Logger.printDebug { "onActivityStarted $activity" }
274-
}
275-
276-
override fun onActivityStopped(activity: Activity) {
277-
Logger.printDebug { "onActivityStopped $activity" }
278-
}
279-
})
280-
}
281-
282241
fun KProperty0<FindMethodFunc>.hookMethod(block: HookDsl<IHookCallback>.() -> Unit) {
283242
getDexMethod(this.name, this.get()).hookMethod(block)
284243
}
@@ -356,4 +315,55 @@ abstract class BaseHook(private val app: Application, val lpparam: LoadPackagePa
356315
key: String, crossinline findFunc: DexKitBridge.() -> List<MethodData>
357316
): List<DexMethod> = dexkit.getMethodsDirectOrEmpty(
358317
key, wrapFindList(key, findFunc) { it.descriptor })
359-
}
318+
}
319+
320+
val ExtensionResourceHook = patch {
321+
appContext.addModuleAssets()
322+
StringRef.resources = appContext.resources
323+
StringRef.packageName = BuildConfig.APPLICATION_ID
324+
StringRef.packageName2 = appContext.packageName
325+
326+
appContext.callMethod(
327+
"registerActivityLifecycleCallbacks", object : Application.ActivityLifecycleCallbacks {
328+
var handleWebView: Boolean = false
329+
330+
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
331+
Logger.printDebug { "onActivityCreated $activity" }
332+
if (!handleWebView) {
333+
WebView(activity).destroy()
334+
appContext.addModuleAssets()
335+
StringRef.resources = appContext.resources
336+
StringRef.packageName = BuildConfig.APPLICATION_ID
337+
StringRef.packageName2 = appContext.packageName
338+
handleWebView = true
339+
}
340+
341+
activity.addModuleAssets()
342+
}
343+
344+
override fun onActivityDestroyed(activity: Activity) {
345+
Logger.printDebug { "onActivityDestroyed $activity" }
346+
}
347+
348+
override fun onActivityPaused(activity: Activity) {
349+
Logger.printDebug { "onActivityPaused $activity" }
350+
}
351+
352+
override fun onActivityResumed(activity: Activity) {
353+
Logger.printDebug { "onActivityResumed $activity" }
354+
activity.addModuleAssets()
355+
}
356+
357+
override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {
358+
Logger.printDebug { "onActivitySaveInstanceState $activity" }
359+
}
360+
361+
override fun onActivityStarted(activity: Activity) {
362+
Logger.printDebug { "onActivityStarted $activity" }
363+
}
364+
365+
override fun onActivityStopped(activity: Activity) {
366+
Logger.printDebug { "onActivityStopped $activity" }
367+
}
368+
})
369+
}

app/src/main/java/io/github/chsbuffer/revancedxposed/MainHook.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class MainHook : IXposedHookLoadPackage, IXposedHookZygoteInit {
2727
"com.google.android.apps.youtube.music" to { MusicHook(app, lpparam) },
2828
"com.google.android.youtube" to { YoutubeHook(app, lpparam) },
2929
"com.reddit.frontpage" to { RedditHook(app, lpparam) },
30-
"com.google.android.apps.photos" to { GooglePhotosHook(lpparam) },
30+
"com.google.android.apps.photos" to { GooglePhotosHook(app, lpparam) },
3131
"com.instagram.android" to { MetaHook(app, lpparam) },
3232
"com.instagram.barcelona" to { MetaHook(app, lpparam) },
3333
"com.strava" to { StravaHook(app, lpparam) },
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.github.chsbuffer.revancedxposed.activity
2+
3+
import io.github.chsbuffer.revancedxposed.Patch
4+
import io.github.chsbuffer.revancedxposed.googlephotos.GooglePhotosPatches
5+
import io.github.chsbuffer.revancedxposed.meta.MetaPatches
6+
import io.github.chsbuffer.revancedxposed.music.YTMusicPatches
7+
import io.github.chsbuffer.revancedxposed.photomath.PhotomathPatches
8+
import io.github.chsbuffer.revancedxposed.reddit.RedditPatches
9+
import io.github.chsbuffer.revancedxposed.strava.StravaPatches
10+
import io.github.chsbuffer.revancedxposed.youtube.YouTubePatches
11+
12+
class AppPatchInfo(val appName: String, val packageName: String, val patches: Array<Patch>)
13+
14+
val appPatchConfigurations = listOf(
15+
AppPatchInfo("YouTube", "com.google.android.youtube", YouTubePatches),
16+
AppPatchInfo("YT Music", "com.google.android.apps.youtube.music", YTMusicPatches),
17+
AppPatchInfo("Reddit (2024.17.0)", "com.reddit.frontpage", RedditPatches),
18+
AppPatchInfo("Google Photos", "com.google.android.apps.photos", GooglePhotosPatches),
19+
AppPatchInfo("Instagram", "com.instagram.android", MetaPatches),
20+
AppPatchInfo("Threads", "com.instagram.barcelona", MetaPatches),
21+
AppPatchInfo("Strava", "com.strava", StravaPatches),
22+
AppPatchInfo("Photomath", "com.microblink.photomath", PhotomathPatches),
23+
)

0 commit comments

Comments
 (0)