A modern Android task management app built with Kotlin, Jetpack Compose, and a clean architecture approach. It demonstrates best practices around state-driven UIs, Kotlin coroutines and flows, Room persistence, and dependency injection with Koin.
- Create, update, and delete tasks
- Mark tasks as completed
- View task details and edit existing tasks
- Material 3 UI built with Jetpack Compose
- Reactive state management using
StateFlow - Local persistence via Room database
- Dependency injection with Koin
- Unit tests for ViewModels, use cases, and repository layer
Language & Runtime
- Kotlin
- Coroutines & Flows
Android & Jetpack
- Jetpack Compose UI
- Navigation-Compose
- ViewModel / Lifecycle
- Room for local data storage
Architecture
- Clean-ish layered architecture:
core/domain: use cases and domain modelscore/data: repositories and Room entities/DAOscore/ui: shared UI components, theme, and helper functionsfeature/*: UI + ViewModels per feature (home, task details, new task, update task)- Unidirectional data flow using Model-View-Intent (MVI):
Event -> ViewModel -> State/Effect -> UI
Dependency Injection & Tools
- Koin (with KSP for DI code generation)
- JUnit 5
- MockK
- JaCoCo for test coverage
At a high level:
My-Tasks/
├── app/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/dev/alimansour/mytasks/
│ │ │ │ ├── core/
│ │ │ │ │ ├── data/...
│ │ │ │ │ ├── domain/...
│ │ │ │ │ └── ui/...
│ │ │ │ └── feature/
│ │ │ │ ├── home/...
│ │ │ │ ├── task/add/...
│ │ │ │ ├── task/details/...
│ │ │ │ └── task/update/...
│ │ │ └── res/...
│ │ └── test/java/dev/alimansour/mytasks/...
│ └── build.gradle.kts
├── build.gradle.kts
└── gradle/libs.versions.toml
- Java JDK 21 (recommended)
- Android Studio Giraffe or newer
- Gradle wrapper (provided in the repo)
Note: Newer Java versions (e.g., 25) may not be fully supported by the Kotlin/Gradle toolchain used here. If you see errors like
java.lang.IllegalArgumentException: 25.0.1, run Gradle with JDK
If you want to contribute or set up your own version with CI/CD:
- Click the Fork button at the top right of this repository
- Clone your forked repository:
git clone https://github.com/YOUR_USERNAME/My-Tasks.git
cd My-TasksTo enable the automated workflows (Pull Request checks and Google Play deployment), you need to configure the following secrets in your repository settings:
- Go to your forked repository on GitHub
- Navigate to Settings → Secrets and variables → Actions
- Click New repository secret and add each of the following:
Required Secrets for Release Workflow:
| Secret Name | Description | How to Get It |
|---|---|---|
KEYSTORE_PASSWORD |
Password for your Android keystore | The password you set when creating your keystore |
KEY_ALIAS |
Alias name for your signing key | The alias you used when creating your key |
KEY_PASSWORD |
Password for your signing key | The password you set for your signing key |
ANDROID_KEYSTORE |
Base64-encoded keystore file | Run: base64 -w 0 your-keystore.jks |
GOOGLE_PLAY_AUTH_JSON |
Google Play service account JSON | Download from Google Play Console → API access |
Creating an Android Keystore (if you don't have one):
keytool -genkey -v -keystore release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias your-key-aliasEncoding the Keystore for GitHub Secrets:
base64 -w 0 release-key.jks > keystore-base64.txt
# Copy the content of keystore-base64.txt and paste it as ANDROID_KEYSTORE secretSetting up Google Play Service Account:
- Follow this tutorial to create a Google Play service account
- Download the JSON key file
- Copy the entire JSON content and paste it as
GOOGLE_PLAY_AUTH_JSONsecret
Note: The release workflow will only trigger when you push a tag (e.g.,
v1.0.0). The pull request workflow runs automatically on PRs tomainordevelopbranches.
If you just want to build and run the app locally without CI/CD:
git clone https://github.com/dev-ali-mansour/My-Tasks.git
cd My-TasksOn Linux, if you have JDK 21 installed at /usr/lib/jvm/java-21-openjdk:
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
export PATH="$JAVA_HOME/bin:$PATH"
java -versionYou should see a Java 21 version.
File→Open...- Select the
My-Tasksfolder. - Let Gradle sync and KSP/Room code generation complete.
From Android Studio:
- Select a device or emulator.
- Click Run on the
appconfiguration.
From the command line:
./gradlew :app:assembleDebugThe resulting APK will be in app/build/outputs/apk/debug/.
Unit tests (JVM):
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
export PATH="$JAVA_HOME/bin:$PATH"
./gradlew :app:testDebugUnitTest
./gradlew :app:testReleaseUnitTestThis runs unit tests for core use cases, repository implementations, and feature ViewModels like:
HomeViewModelTestNewTaskViewModelTestUpdateTaskViewModelTestTaskDetailsViewModelTest
To generate a global JaCoCo coverage report:
./gradlew jacocoTestReportOpen the HTML report:
app/build/reports/jacoco/jacocoTestReport/html/index.html
For per-package and per-class coverage, see the HTML tree under:
app/build/reports/jacoco/html/...
- Kotlin official code style
- GIVEN / WHEN / THEN comments in tests to clarify test stages
- Use of sealed classes for events and effects where appropriate
- Nullability handled explicitly via Kotlin types and
UiTextwrappers
The project uses Gradle version catalogs (gradle/libs.versions.toml) to manage versions of:
- Android Gradle Plugin (AGP)
- Kotlin and coroutines
- Compose BOM and related artifacts
- Koin, Room, MockK, JUnit, etc.
To update a dependency, adjust its version in gradle/libs.versions.toml and sync.
Koin modules and ViewModels are wired using the Koin KSP compiler. Generated artifacts live under:
app/build/generated/ksp/...
If you see Koin warnings like no module found, ensure:
- KSP is enabled in
build.gradle.ktsfor the relevant source sets. - Koin modules are correctly annotated / registered.
A clean rebuild can often resolve stale generated code:
./gradlew clean :app:assembleDebugThis project is provided as-is for learning and demonstration purposes. Adapt licensing as needed for your use case.



