Contributing — Android
How to run, test, and understand acerola-android's architecture.
No dedicated contribution guide yet
Android doesn’t have its own CONTRIBUTING.md yet like Desktop and P2P do — open an issue before sending a larger PR.
acerola/android is a native app in Kotlin + Jetpack Compose, organized into 6 Gradle modules.
Running it
# Build
./gradlew assembleDebug
./gradlew assembleRelease
./gradlew installDebug
# Clean and build
./gradlew clean buildModule architecture
flowchart TD
App[":app"] --> Data[":data"]
App --> UI[":ui"]
App --> Infra[":infra"]
UI --> Core[":core"]
UI --> Infra
Core --> Infra
Core --> Native[":native"]
Core --> Data
Data --> Infra
:infra— base layer, no internal dependencies: config, error handling, logging, shared patterns and utilities.:data— data access: adapters/gateways (Port & Adapter pattern, using Arrow’sEitherfor errors), DTOs, Room (local DAOs/entities), and remote clients (MangaDex, AniList). Depends only on:infra.:native— Kotlin/JNI bridge (viauniffi) to consumelib/p2p(Rust) — loads the native libraries underjniLibs/. Base layer, no internal dependencies.:core— business logic and orchestration: DI modules (Hilt), use cases, P2P sync, and background workers (WorkManager). Depends on:infra,:data, and:native.:ui— Jetpack Compose: Screens, ViewModels,UiStateclasses, theming (Catppuccin, Dracula, Alucard, Nord), and navigation. Depends on:coreand:infra.:app— entry point:AcerolaApplication(Hilt, WorkManager, Coil setup),MainActivity(navigation host).
Key patterns
- UDF (Unidirectional Data Flow): user interaction →
Screendispatches an action →ViewModelcalls a use case/repository → emitsUiState(StateFlow) → UI recomposes. - Port & Adapter: contracts (gateways/providers) live in
data/adapter/contract/, implementations in the rest ofdata/adapter/. - Error handling: Arrow’s
Either<Error, Success>throughout the data layer. - DI: Hilt everywhere —
@HiltViewModel,@HiltAndroidApp,@Module/@Providesmodules.
Code quality and testing
./gradlew ktlintCheck # Lint (ktlint, applied to every module)
./gradlew ktlintFormat # Auto-formats
./gradlew test # All unit tests
./gradlew :data:test # Single module
./gradlew :data:test --tests "*ClassName" # Single test class
./gradlew connectedDebugAndroidTest # Instrumented tests (device required)
./gradlew koverHtmlReport # Coverage report (Kover)Database and remote APIs
Room: comic_directory, comic_remote_info, chapter_archive, chapter_remote_info, chapter_download_source, author, genre, cover, reading_history, chapter_read.
Remote APIs: https://api.mangadex.org (REST via Retrofit/Moshi) and a GraphQL client via Apollo (AniList).
JVM target
Every module compiles for Java 21.