### Write Remote Preferences with Kotlin Source: https://context7.com/libxposed/example/llms.txt Demonstrates writing configuration values to remote preferences using `XposedService.getRemotePreferences`. Changes are synchronized across processes. Requires the `XposedService` instance. ```kotlin import io.github.libxposed.service.XposedService import kotlin.random.Random import android.util.Log fun updateRemotePreferences(service: XposedService) { // Get shared preferences accessible from hooked processes val prefs = service.getRemotePreferences("test") // Read current value val oldValue = prefs.getInt("test", -1) // Write new value val newValue = Random.nextInt() prefs.edit() .putInt("test", newValue) .apply() Log.d("Xposed", "Updated preference: $oldValue -> $newValue") } ``` -------------------------------- ### Configure Gradle Dependencies with Kotlin DSL Source: https://context7.com/libxposed/example/llms.txt Sets up LibXposed dependencies in `build.gradle.kts`. The API library is `compileOnly`, and the service library is `implementation`. Includes packaging options for Xposed metadata. ```kotlin // app/build.gradle.kts plugins { alias(libs.plugins.agp.app) alias(libs.plugins.kotlin) } android { namespace = "io.github.libxposed.example" compileSdk = 34 defaultConfig { minSdk = 24 targetSdk = 34 versionCode = 1 versionName = "1.0" } packaging { resources { // Include xposed metadata files merges += "META-INF/xposed/*" excludes += "**" } } } dependencies { // API library - compile only, provided by framework at runtime compileOnly(libs.libxposed.api) // Service library - bundled with app for host-side functionality implementation(libs.libxposed.service) } ``` -------------------------------- ### Connect to XposedService Source: https://context7.com/libxposed/example/llms.txt Illustrates how to manage the lifecycle of an XposedService connection using XposedServiceHelper. It provides callbacks for service binding and disconnection to access framework metadata. ```kotlin import io.github.libxposed.service.XposedService import io.github.libxposed.service.XposedServiceHelper class MainActivity : Activity() { private var mService: XposedService? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) XposedServiceHelper.registerListener(object : XposedServiceHelper.OnServiceListener { override fun onServiceBind(service: XposedService) { mService = service // Access framework information val apiVersion = service.apiVersion val frameworkName = service.frameworkName val frameworkVersion = service.frameworkVersion val frameworkVersionCode = service.frameworkVersionCode val scope = service.scope Log.d("Xposed", "API: $apiVersion") Log.d("Xposed", "Framework: $frameworkName $frameworkVersion ($frameworkVersionCode)") Log.d("Xposed", "Scope: $scope") } override fun onServiceDied(service: XposedService) { mService = null Log.d("Xposed", "Service connection lost") } }) } } ``` -------------------------------- ### Module Configuration Files Source: https://context7.com/libxposed/example/llms.txt Defines essential configuration files for Xposed module recognition. `module.prop` sets API compatibility, `java_init.list` specifies the entry point, and `scope.list` declares target packages. ```properties # META-INF/xposed/module.prop minApiVersion=100 targetApiVersion=100 staticScope=true ``` ```text # META-INF/xposed/java_init.list io.github.libxposed.example.ModuleMain ``` ```text # META-INF/xposed/scope.list com.android.settings ``` -------------------------------- ### Initialize XposedModule in Kotlin Source: https://context7.com/libxposed/example/llms.txt Demonstrates the initialization of the `ModuleMain` class, which extends `XposedModule`. It logs the process name and stores a reference to the module instance for later use. This is the entry point for the module's logic. ```kotlin package io.github.libxposed.example import io.github.libxposed.api.XposedInterface import io.github.libxposed.api.XposedModule import io.github.libxposed.api.XposedModuleInterface.ModuleLoadedParam private lateinit var module: ModuleMain class ModuleMain(base: XposedInterface, param: ModuleLoadedParam) : XposedModule(base, param) { init { // Log initialization with process name log("ModuleMain at " + param.processName) // Store reference for use in hooker classes module = this } } ``` -------------------------------- ### Configure Gradle Dependencies with TOML Source: https://context7.com/libxposed/example/llms.txt Defines LibXposed versions and libraries in `gradle/libs.versions.toml` for use in Gradle build scripts. Specifies versions for AGP, Kotlin, and LibXposed components. ```toml # gradle/libs.versions.toml [versions] agp = "8.0.2" kotlin = "1.9.0" xposed-api = "100" xposed-service = "100-1.0.0" [libraries] libxposed-api = { group = "io.github.libxposed", name = "api", version.ref = "xposed-api" } libxposed-service = { group = "io.github.libxposed", name = "service", version.ref = "xposed-service" } ``` -------------------------------- ### Manage Dynamic Scope Requests Source: https://context7.com/libxposed/example/llms.txt Explains how to request permission to hook additional packages dynamically using requestScope. It implements OnScopeEventListener to handle various outcomes such as approval, denial, or timeout. ```kotlin import io.github.libxposed.service.XposedService import io.github.libxposed.service.XposedService.OnScopeEventListener private val scopeCallback = object : OnScopeEventListener { override fun onScopeRequestPrompted(packageName: String) { Toast.makeText(context, "Prompting for: $packageName", Toast.LENGTH_SHORT).show() } override fun onScopeRequestApproved(packageName: String) { Toast.makeText(context, "Approved: $packageName", Toast.LENGTH_SHORT).show() } override fun onScopeRequestDenied(packageName: String) { Toast.makeText(context, "Denied: $packageName", Toast.LENGTH_SHORT).show() } override fun onScopeRequestTimeout(packageName: String) { Toast.makeText(context, "Timeout: $packageName", Toast.LENGTH_SHORT).show() } override fun onScopeRequestFailed(packageName: String, message: String) { Toast.makeText(context, "Failed: $packageName - $message", Toast.LENGTH_SHORT).show() } } // Request scope for a specific package fun requestSettingsScope(service: XposedService) { service.requestScope("com.android.settings", scopeCallback) } ``` -------------------------------- ### Write Remote Files with Kotlin Source: https://context7.com/libxposed/example/llms.txt Shows how to write files that hooked processes can read using `XposedService.openRemoteFile`. This facilitates configuration file sharing between the host app and module code. Requires the `XposedService` instance. ```kotlin import io.github.libxposed.service.XposedService import java.io.FileWriter import android.util.Log fun writeRemoteFile(service: XposedService) { // Open file for writing (creates if doesn't exist) service.openRemoteFile("test.txt").use { pfd -> FileWriter(pfd.fileDescriptor).use { writer -> writer.append("Hello World!") } } Log.d("Xposed", "Remote file written successfully") } ``` -------------------------------- ### Access Remote Shared Preferences with LibXposed Source: https://context7.com/libxposed/example/llms.txt Demonstrates how to retrieve and observe shared preferences across process boundaries. It uses getRemotePreferences to read data and registerOnSharedPreferenceChangeListener to react to host app updates. ```kotlin import io.github.libxposed.api.XposedModuleInterface.PackageLoadedParam override fun onPackageLoaded(param: PackageLoadedParam) { super.onPackageLoaded(param) if (!param.isFirstPackage) return // Get remote preferences by name val prefs = getRemotePreferences("test") // Read values with defaults val currentValue = prefs.getInt("test", -1) log("remote prefs: $currentValue") // Listen for preference changes from the host app prefs.registerOnSharedPreferenceChangeListener { _, key -> val value = prefs.getInt(key, 0) log("onSharedPreferenceChanged: $key->$value") } } ``` -------------------------------- ### Read Remote Files with LibXposed Source: https://context7.com/libxposed/example/llms.txt Shows how to access files from a module's private storage using openRemoteFile. The function returns a ParcelFileDescriptor that must be closed to prevent resource leaks. ```kotlin import java.io.FileNotFoundException import java.io.FileReader override fun onPackageLoaded(param: PackageLoadedParam) { super.onPackageLoaded(param) if (!param.isFirstPackage) return try { // Open remote file and read contents val text = openRemoteFile("test.txt").use { pfd -> FileReader(pfd.fileDescriptor).readText() } log("remote file content: $text") } catch (e: FileNotFoundException) { log("remote file not found") } } ``` -------------------------------- ### Register Hooks using Package Load Callback in Kotlin Source: https://context7.com/libxposed/example/llms.txt Demonstrates how to use the `onPackageLoaded` callback to register method hooks. This callback is triggered when a target package is loaded, providing access to the package name and class loader. Hooks are registered using the `hook` method with a target method and a hooker class. ```kotlin import android.app.Application import android.content.Context import io.github.libxposed.api.XposedModuleInterface.PackageLoadedParam override fun onPackageLoaded(param: PackageLoadedParam) { super.onPackageLoaded(param) // Log package information log("onPackageLoaded: " + param.packageName) log("param classloader is " + param.classLoader) log("module apk path: " + this.applicationInfo.sourceDir) // Only proceed for the first/main package load if (!param.isFirstPackage) return // Get the method to hook using reflection val exampleMethod = Application::class.java.getDeclaredMethod( "attach", Context::class.java ) // Register the hook with the hooker class hook(exampleMethod, MyHooker::class.java) } ``` -------------------------------- ### Implement Method Hooking with @XposedHooker in Kotlin Source: https://context7.com/libxposed/example/llms.txt Shows how to use the `@XposedHooker` annotation to define classes that handle method hooking logic. It includes `@BeforeInvocation` and `@AfterInvocation` callbacks to intercept method calls before and after execution, respectively. The hooker can maintain state between callbacks. ```kotlin import io.github.libxposed.api.XposedInterface import io.github.libxposed.api.XposedInterface.AfterHookCallback import io.github.libxposed.api.XposedInterface.BeforeHookCallback import io.github.libxposed.api.annotations.AfterInvocation import io.github.libxposed.api.annotations.BeforeInvocation import io.github.libxposed.api.annotations.XposedHooker import kotlin.random.Random @XposedHooker class MyHooker(private val magic: Int) : XposedInterface.Hooker { companion object { @JvmStatic @BeforeInvocation fun beforeInvocation(callback: BeforeHookCallback): MyHooker { // Generate unique key for this invocation val key = Random.nextInt() // Access method arguments via callback.args val appContext = callback.args[0] module.log("beforeInvocation: key = $key") module.log("app context: $appContext") // Return hooker instance to pass state to afterInvocation return MyHooker(key) } @JvmStatic @AfterInvocation fun afterInvocation(callback: AfterHookCallback, context: MyHooker) { // Access state from beforeInvocation via context parameter module.log("afterInvocation: key = ${context.magic}") // Access return value: callback.result // Modify return value: callback.result = newValue } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.