Warning
I do not support the use of my code for your job applications, as it creates unfair competition. If you copy or fork this for that purpose, you risk disqualification. Please respect the integrity of the process and create your own work.
A responsive Android sample app written in Kotlin and Jetpack Compose, supporting different navigation layout on screen sizes. The Media 3 Exoplayer is implemented on top of the single activity architecture. It is fully functional with Picture-in-Picture support.
The events under the Events tab provides video playback. The schedule under the Schedule tab refreshes automatically every 30 seconds. For both tabs, you can always do swipe-to-refresh, or tap the navigation icon to scroll to the top of the list.
If you want to try out the app without building it, check out the Releases section where you can find the APK and App Bundles for each major release.
This was a code test assignment done in October, 2021, but I am still keep on improving the codes for demonstration purpose.. The task covered common RESTApi, SQLite, RecyclerView, Constraint Layout, MVVM, plus dependency injection and testings.
The original XML View version is no longer maintained, you can access to the XML branch here.
Please note that the APIs are supplied by DAZN in 2021. They may not work at any time. There is a plan to replace them with my own APIs and contents.
Planned enhancements are now logged as issues.
- Kotlin
- MVVM & clean architecture
- Jetpack Compose - Single Activity
- Kotlin Coroutines and Flow
- Dependency Injection using Dagger Hilt
- Material 3
- Dynamic screen layout support using Windows Size Class
- Jetpack Media 3 video player
- Gradle Kotlin DSL and Version Catalog
- Baseline Profile
- Full unit test and UI (Journey) test suite
- AndroidX Core KTX - Apache 2.0 - Kotlin extensions for core Android APIs
- AndroidX Activity Compose - Apache 2.0 - Jetpack Compose integration with Activity
- Jetpack Compose - Apache 2.0 - Modern toolkit for building native UI
- AndroidX Material 3 - Apache 2.0 - Material Design 3 components for Compose
- AndroidX Material 3 Window Size Class - Apache 2.0 - Adaptive layout window size classes for Compose
- AndroidX DataStore Preferences - Apache 2.0 - Typed data storage backed by Kotlin coroutines and Flow
- AndroidX Core SplashScreen - Apache 2.0 - Splash screen API for consistent app startup
- AndroidX Legacy Support v4 - Apache 2.0 - Backwards-compatibility support libraries
- AndroidX Lifecycle - Apache 2.0 - Lifecycle-aware components including Runtime KTX, ViewModel KTX, Runtime Compose, and Extensions
- AndroidX Room - Apache 2.0 - SQLite object mapping library (Runtime, KTX, Compiler)
- AndroidX Benchmark - Apache 2.0 - Macrobenchmarking for performance testing
- AndroidX Profile Installer - Apache 2.0 - Install baseline profiles to improve app startup
- AndroidX Test - Apache 2.0 - Testing libraries including Test Core KTX, JUnit extensions, and Test Rules
- AndroidX UI Automator - Apache 2.0 - UI automation testing framework
- AndroidX Media3 - Apache 2.0 - Media components including ExoPlayer, DASH, Session, UI, and Test Utils
- JUnit - EPL 1.0 - Unit testing framework for Java
- Espresso - Apache 2.0 - Android UI testing framework
- Retrofit - Apache 2.0 - Type-safe HTTP client for Android and Java
- Moshi - Apache 2.0 - JSON library for Android and Java (Adapters, Kotlin)
- OkHttp Logging Interceptor - Apache 2.0 - HTTP request/response logging
- Coil 3 - Apache 2.0 - Image loading for Android (Compose, GIF, Network OkHttp, Test)
- Kotlinx Coroutines - Apache 2.0 - Asynchronous programming for Kotlin (Android, Test)
- Kotlinx DateTime - Apache 2.0 - Multiplatform date and time library
- Robolectric - Apache 2.0 - Unit testing framework for Android
- MockK - Apache 2.0 - Mocking library for Kotlin
- Timber - Apache 2.0 - Logging utility for Android
- Android Application Plugin - Google - Plugin for building Android applications
- Kotlin Android Plugin - JetBrains - Kotlin Android support
- Hilt Android Plugin - Google - Dependency injection with Hilt
- Compose Compiler Plugin - JetBrains - Kotlin compiler plugin for Jetpack Compose
- Kover Plugin - JetBrains - Code coverage tool for Kotlin
- KSP Plugin - Google - Kotlin Symbol Processing API
- Android Test Plugin - Google - Plugin for Android test projects
- Baseline Profile Plugin - AndroidX - Generate and package baseline profiles
- Serialization Plugin - JetBrains - Kotlin serialization compiler plugin
- Detekt Plugin - Artur Bosch - Static code analysis for Kotlin
- Kotlinter Plugin - Jeremy Mailen - Kotlin linter and formatter
By default, debug builds do not require a keystore. You can run:
./gradlew assembleDebugNo signing config is required unless you explicitly build a release variant.
Signing configuration is only triggered when:
- the task includes "Release" or "Bundle"
- or the environment variable
CI=trueis set
There are two ways to supply the keystore:
Provide the following environment variables (e.g. in GitHub Secrets):
KEYSTORE_LOCATION=./keystore.jks
CI_ANDROID_KEYSTORE_ALIAS=yourAlias
CI_ANDROID_KEYSTORE_PASSWORD=yourKeystorePassword
CI_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD=yourPrivateKeyPassword
Create a keystore.properties file at the root:
alias=yourAlias
pass=yourPrivateKeyPassword
store=path/to/keystore.jks
storePass=yourKeystorePasswordThen build:
./gradlew bundleReleaseRelease builds are timestamped using the format:
<app-name>-<buildType>-<versionName>-<yyyyMMdd-HHmmss>.apk
This applies to both APK and AAB artifacts.
The .github/workflows/tag_create_release.yml file defines the CI/CD pipeline. It performs the following:
- Checks out the code.
- Sets up JDK 17.
- Builds the APK and AAB using Gradle.
- Creates a GitHub Release.
- Uploads the outputs as release assets.
Trigger the workflow by tagging a commit with the format: release/*, e.g. release/1.2.3.
To trigger the CI pipeline:
git tag release/1.0.0
git push origin release/1.0.0GitHub Actions will build the release and publish it with assets.