Conversation
There was a problem hiding this comment.
Pull request overview
This PR refines the public LibXposed API toward a “final stable” shape by introducing an explicit module-load callback, restructuring hook handle types around Executable, and raising the Android minSdk accordingly.
Changes:
- Add
onModuleLoaded(ModuleLoadedParam)callback to separate “module attached” from instantiation timing. - Redesign hooking APIs: replace
Member/MethodUnhookerwithExecutable-based generics and new hook handle types. - Raise
apimoduleminSdkfrom 24 → 26 to supportjava.lang.reflect.Executablein the public surface.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| api/src/main/java/io/github/libxposed/api/XposedModuleInterface.java | Adds onModuleLoaded callback and related Javadoc. |
| api/src/main/java/io/github/libxposed/api/XposedModule.java | Removes constructor-based initialization and updates guidance to use onModuleLoaded. |
| api/src/main/java/io/github/libxposed/api/XposedInterfaceWrapper.java | Switches to late attachment (attachFramework) and updates wrapper methods to new hook APIs. |
| api/src/main/java/io/github/libxposed/api/XposedInterface.java | Updates core API types to Executable, introduces hook handle interfaces, and adjusts invocation/deoptimize APIs. |
| api/build.gradle.kts | Bumps minSdk to 26 to match new Executable usage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
api/src/main/java/io/github/libxposed/api/XposedInterfaceWrapper.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
I see that #15 has been closed but it does not look to me like it was implemented in this pull request. Have the plans to implement it been scrapped? |
The side effects of individual hooker class are too severe while introducing minimum advantage. Because dsl and lambda becomes impossible, every module would implement its own hook dispatchers, making cooperation impossible and destroy hook dump readability.
|
Hi, |
Resource hooks are removed in new API because of already low compatibility with new Android versions. We may offer a more modern resource hook solution in the future, but it is not currently part of the API 100 initiative. |
|
Some time ago, when I tried to use the new API, I got confused because some methods are available both on |
FabricatedOverlay is Android 14 based SDK implementation, what about Android 8+ ? |
|
|
I later figured out which Rovo's old API had it cleanly separated: I implement the XposedModule Interface and all the other info would be passed in via objects. This was intuitive. Maybe passing the XposedInterface object via constructor parameter would retain that and would make it easier to pick the right method. |
I think it's better to stick with the new one, saying |
|
11 |
…edge condition with null
This reverts commit 585f281.
After the merge, the release will be prepared for MavenCentral, and no further breaking changes are permitted.
Key changes
API Version
APIconstant (value100) has been removed. Use the newgetApiVersion()method instead, which returns101for now.Hook Model — Complete Redesign
The hook model has been completely redesigned from an AOP-style (before/after callbacks) to an OkHttp-style interceptor chain.
Old Model (Removed)
BeforeHookCallbackandAfterHookCallbackinterfaces — removed entirely.Hookerwas a marker interface; modules provided staticbefore(BeforeHookCallback)andafter(AfterHookCallback)methods.New Model
Modules now implement typed hooker interfaces with an
intercept()method:Hooker<T>—Object intercept(Chain<T> chain) throws ThrowableThe chain objects provide access to the method,
thispointer, arguments, and aproceed()method to continue the chain — replacing the old before/after split.Hooking Methods Now Return Builders
hook(Method, Class<? extends Hooker>)→MethodUnhooker<Method>hook(Method)→HookBuilder<Method>hook(Method, int, Class<? extends Hooker>)HookBuilder.setPriority(int)hook(Constructor<T>, ...)→MethodUnhooker<Constructor<T>>hook(Constructor<T>)→HookBuilder<Constructor<T>>hookClassInitializer(Class<T>, ...)→MethodUnhooker<Constructor<T>>hookClassInitializer(Class<?>)→HookBuilder<Method>All overloads that accepted
priorityas a separate parameter have been removed. Priority is now configured through the builder.MethodUnhooker → HookHandle
MethodUnhooker<T>has been removed.HookHandle<T>.getOrigin()renamed togetExecutable().unhook()is now explicitly idempotent (safe to call multiple times).Invoking Original / Special Methods
All direct invoke methods on
XposedInterfacehave been removed:invokeOrigin(Method, ...)— removedinvokeOrigin(Constructor<T>, ...)— removedinvokeSpecial(Method, ...)— removedinvokeSpecial(Constructor<T>, ...)— removednewInstanceOrigin(Constructor<T>, ...)— removednewInstanceSpecial(Constructor<T>, Class<U>, ...)— removedThey are replaced by an Invoker system, obtained through two new methods:
getInvoker(Method)→Invoker<?, Method>getInvoker(Constructor<T>)→CtorInvoker<T>The invoker's behavior is controlled by an
Invoker.Type:Type.ORIGIN— calls the original method, skipping all hooks.Type.Chain(maxPriority)— calls through the hook chain starting from a specific priority.Type.Chain.FULL— calls with the full hook chain.invokeSpecial()andnewInstanceSpecial()are now methods on the invoker objects themselves.Deoptimize
The two overloads
deoptimize(Method)anddeoptimize(Constructor<T>)have been merged into a single method:Framework Privilege → Properties
getFrameworkPrivilege()and its associated constants have been removed:FRAMEWORK_PRIVILEGE_ROOT— removedFRAMEWORK_PRIVILEGE_CONTAINER— removedFRAMEWORK_PRIVILEGE_APP— removedFRAMEWORK_PRIVILEGE_EMBEDDED— removedReplaced by
getFrameworkProperties()which returns a bitmask:PROP_CAP_SYSTEM1LPROP_CAP_REMOTE1L << 1PROP_RT_API_PROTECTION1L << 2Priority Constants
PRIORITY_LOWEST-10000Integer.MIN_VALUEPRIORITY_HIGHEST10000Integer.MAX_VALUELogging
log(String)andlog(String, Throwable)have been removed (were already@Deprecated).Throwablehas been added:log(int priority, String tag, String msg).DexParser
The
DexParserutility class andparseDex(ByteBuffer, boolean)method have been removed entirely. Consider using DexKit as an alternative.Module Lifecycle
Constructor Change
XposedModuleno longer receivesXposedInterfaceandModuleLoadedParamin its constructor. The framework now callsattachFramework(XposedInterface)on the wrapper automatically. Modules should not perform initialization beforeonModuleLoaded()is called.Callback Renames and Splits
onSystemServerLoaded(SystemServerLoadedParam)onSystemServerStarting(SystemServerStartingParam)onPackageLoaded(PackageLoadedParam)The package loading lifecycle is now split into two phases:
onPackageLoaded(PackageLoadedParam)— Called when the default classloader is ready, beforeAppComponentFactoryinstantiation. Requires API 29+.onPackageReady(PackageReadyParam)— Called afterAppComponentFactoryhas created the app classloader. ProvidesgetClassLoader()andgetAppComponentFactory().Note:
getClassLoader()has been moved fromPackageLoadedParamtoPackageReadyParam.