This is an open-source, mobile, cross-platform application built with Kotlin Multiplatform Mobile.
iOS and Desktop clients were implemented as experimental features and can be viewed here.
Desktop and Web clients were implemented as experimental features and can be viewed here.
This repository contains a common Kotlin Multiplatform module, a Android project and an iOS project. The common module is connected with the Android project via the Gradle multi-project mechanism. For use in iOS applications, the shared module compiles into a framework that is exposed to the Xcode project via the internal integration Gradle task. This framework connects to the Xcode project that builds an iOS application.
You can achieve the same structure by creating a project with the KMM Plugin project wizard or cloning the basic sample project.
Kotlin Multiplatform Mobile is a flexible technology that allows you to share only what you want to share, from the core layer to UI layers.
This sample demonstrates sharing not only the data and domain layers of the app but also the application state:
There are two types of data sources. The network service is for getting RSS feed updates, while
local storage is for caching the feed, which makes it possible to use the application
offline. Ktor HTTP Client is used for making API
requests. Kotlinx.serialization is used to
serialize feed data and store it locally
with MultiplaformSettings. This logic is
organized in the shared module of the com.github.jetbrains.rssreader.core package.
The Redux pattern is used for managing the application state. The simplified Redux architecture is
implemented in the shared module. The Store class dispatches the actions that can be produced
either by a user or by some async work, and generates the new state. It stores the actual state
and facilitates subscription to state updates via Kotlin's StateFlow. To provide additional
information about state updates, the Store class also produces effects that, for example, can
be used to display this information via alerts. This logic is organized in the shared KMM module of
the com.github.jetbrains.rssreader.app package.
The UI layer is fully native and implemented using SwiftUI for iOS, Jetpack Compose for Android, Compose Multiplatform for Desktop and React.js for web browser.
On the iOS side, the Store from the KMM library is wrapped into the ObservableObject and
implements the state as a @Published wrapped property. This publishes changes whenever a
dispatched action produces a new state after being reduced in the shared module. The store is
injected as an Environment Object into the root view of the application, and is easily accessible
from anywhere in the application. SwiftUI performs all aspects of diffing on the render pass when
your state changes.
For subscribing to state updates, the simple wrapper is used. This wrapper allows you to provide a callback that will be called when each new value (the state in our case) is emitted.
✅ Platform-specific API usage. RSS feeds usually only support the XML format.
The kotlinx.serialization library currently doesn't support parsing XML data, but there is no need
to implement your own parser. Instead, platform libraries (XmlPullParser for
Android and NSXMLParser for iOS) are used. The common FeedParser interface
is declared in the commonMain source set. Platform implementations are placed in the
corresponding iOSMain and AndroidMain source sets. They are injected into the
RSSReader class (the KMM module entry point) via the create factory method, which is declared in
the RSSReader class companion object.
The project is tested with modern Android/Kotlin toolchains. Use JDK 21 for Gradle builds.
- Git
- JDK 21 (set as default for this repository)
- Android Studio (latest stable) with:
- Android SDK Platform 36
- Android Build-Tools 36.x (or latest installed by Android Studio)
- Android SDK Platform-Tools
- Xcode 15+ (for iOS build and simulator run)
Check Java version:
java -versionIf your default JDK is too new/unsupported for local Gradle plugins, run Gradle with JDK 21 explicitly:
# using mise
mise exec java@21 -- ./gradlew --version
# or export JAVA_HOME manually (example path)
export JAVA_HOME=/path/to/jdk-21
export PATH="$JAVA_HOME/bin:$PATH"Generate local properties (if Android Studio has not created it yet):
# local.properties
sdk.dir=/absolute/path/to/Android/SdkBuild Android debug APK:
./gradlew :composeApp:assembleDebugInstall/run from Android Studio using the composeApp Android configuration.
Build shared iOS framework from Gradle:
./gradlew :shared:linkDebugFrameworkIosSimulatorArm64Open iOS project:
open iosApp/iosApp.xcodeprojThen select an iOS Simulator and run the iosApp scheme in Xcode.
IllegalArgumentException: 25.0.1(or similar Java version parse issue)
Switch to JDK 21 for Gradle commands.- Gradle cannot resolve Android plugins/dependencies
Check network/proxy and ensure access togoogle(),mavenCentral(), and Gradle Plugin Portal. xcodebuildnot found
Install Xcode and command line tools:xcode-select --install





