This document provides essential information for AI agents working on the Iconify project.
Iconify is a free and open-source Android customization application designed for rooted Pixel and AOSP-based devices. It allows users to modify various aspects of the system UI (colors, shapes, icons, status bar, etc.) using a combination of Android Overlays (RRO) and Xposed Hooks.
The project is a single-module Android application (app/) with three main runtime surfaces:
- Compose UI (
features/**): The frontend built with Jetpack Compose. It uses a customPreferenceScreenDSL for building settings pages. - Root/Service Glue (
services/**,core/utils/**): Logic that interacts with the system usinglibsufor root shell access and AIDL services for cross-process communication. - Xposed Hooks (
xposed/**): Runtime hooks that target theandroid(framework) andcom.android.systemuipackages.
MainActivity: Boots alibsuroot shell and sets upAppProviders.AppProviders: WiresCompositionLocals (NavController, Settings, ColorScheme, Haptics, Density, etc.) consumed by screens.- Preference System: Managed by
PreferenceController(core/preferences/). Keys are enums (data/keys/) implementing theKeyinterface. - Remote Preferences:
RemotePrefProviderallows the Xposed process (SystemUI/Framework) to read preferences from the app's device-protected storage. - Xposed Registry:
EntryList.ktis the authoritative list of all active Xposed mod packs.
- Environment: Requires JDK 21 and Android SDK (Compile SDK 36).
- Root Requirement: Testing requires a rooted device (Magisk/KernelSU/APatch) or an emulator with root.
- Signing: Create a
keystore.propertiesin the root directory (seeapp/build.gradle.ktsfor expected fields:keyAlias,keyPassword,storeFile,storePassword). - Dependencies: Uses Hilt for DI, Room for database, and KSP for annotation processing.
- Build Debug:
.\gradlew.bat assembleDebug(Appends.debugto application ID). - Build Release:
.\gradlew.bat assembleRelease. - Rename APKs:
.\gradlew.bat renameApks(Renames build outputs to a standardized format). - Clean Project:
.\gradlew.bat clean.
- Automated Tests: There are currently no unit or instrumentation tests checked into the repository.
- Validation: Must be performed manually by:
- Successful build (
assembleDebug). - Installing on a rooted device.
- Granting root permissions.
- Enabling Xposed module (if testing hooks).
- Tracing logs via
logcat(look forIconifyorXposedtags).
- Successful build (
- UI State: Prefer reading state from
LocalSettings,LocalColorScheme, orLocalPreferenceControllerrather than passing parameters down through multiple levels. - DI: Use Hilt for all dependency injection. ViewModels should be
HiltViewModel. - Preferences:
- All preference keys must be added to the appropriate enum in
data/keys/. - Color preferences must be stored as hex strings (e.g.,
"#8a51f5"), not integers.
- All preference keys must be added to the appropriate enum in
- Xposed Hooks:
- Extend
ModPack(xposed/ModPack.kt). - Register new hooks in
EntryList.kt. - Always check
HookEntry.isChildProcessto avoid hooking child processes if not needed.
- Extend
RemotePrefProviderandXPrefslogic: These are critical for cross-process communication between the app and Xposed.- Package ID logic in
customize.sh: The Magisk module depends on specific package naming conventions. - Child Process Checks: Do not remove
!HookEntry.isChildProcesschecks inEntryListunless you specifically intend to hook child processes (high risk of performance issues).
- Adding new UI screens or components using the
PreferenceScreenDSL. - Adding new preference keys to existing enums.
- Improving styling and micro-animations in the Compose UI.
- Xposed Hooks: Incorrect hooks in
androidorcom.android.systemuican cause bootloops. Always verify hook logic carefully. - Root Commands: Be extremely careful with
Shell.cmd(...)as it runs with elevated privileges.
- ProGuard/R8: Preference key enums (
data/keys/) must be protected from obfuscation to ensure stored values remain accessible. Checkproguard-rules.proif adding new key classes. - SDK 36: The project targets Android 16 (SDK 36). Some APIs might be unstable or require specific platform signatures.
- Magisk Module: The app generates a ROM-specific Magisk module. Changes to the directory structure in
ModuleBase/must be reflected in the generation logic. - Hex Colors: Storing colors as hex strings is a legacy choice; parsing them incorrectly (e.g., as
Int) will fail. UseColor.parseColor()ortoLong().