Strategic Plan: AnkiDroid for iOS (KMP Migration)
This plan outlines the necessary steps to transform the AnkiDroid codebase so that it runs on both Android and Apple devices (iOS/macOS). Instead of a complete rewrite, the project utilizes Kotlin Multiplatform (KMP) to share the app’s core (logic, database, networking).
1. Strategic Approach
To minimize risk, the “Strangler Fig Pattern” is applied. This means the migration occurs incrementally, module by module, while the existing Android app remains stable.
2. Migration Phases
Phase 1: PoC & Infrastructure (Current Status)
- Creation of the
:sharedmodule. - Integration of SQLDelight for cross-platform database access.
- Configuration of iOS targets (Arm64, Simulator) within the build system.
- Validation of integration within the existing Android app.
Phase 2: Logic Decoupling (“Clean libanki”)
This is the most significant hurdle, as Java and Android dependencies must be removed from the business logic.
- Replacing
org.jsonwithkotlinx.serialization. - Replacing
java.util.Datewithkotlinx-datetime. - Abstracting logs using the Kermit library.
- Moving logic from
libankitoshared/commonMain.
Phase 3: Shared Infrastructure Layer
- Database: Migrating the entire schema to SQLDelight.
- Networking: Implementing Ktor instead of OkHttp for synchronization with AnkiWeb.
- Settings: Utilizing
MultiplatformSettingsinstead of Android’s SharedPreferences.
Phase 4: iOS App Setup & UI
- Creation of a new Xcode project within the repository that consumes the
:sharedframework. - UI Options: Either a native implementation using SwiftUI (for the best Apple look-and-feel) or a shared solution using Compose Multiplatform.
3. Critical Challenges
- Rust Backend Integration: Since Anki’s core is written in Rust, JNI/C interoperability for iOS must be ensured via Kotlin/Native (utilizing the
rsdroidlibrary). - WebView Complexity: Since cards are rendered in WebViews, the communication logic for iOS (WKWebView) must be re-implemented.
- Media Handling: Audio and image files require a platform-independent abstraction, as they are currently handled in a way that is heavily Android-centric.
4. Current Progress & Next Steps
The project is currently in a POC (Proof of Concept) stage at the end of Phase 1. The basic framework is in place, and simple operations like the DeckRepository are already functional within the :shared module.
The next steps include:
- Continuing the migration of utility classes (e.g., Time-Suite).
- Fully defining the Anki database in SQLDelight.
- Creating a SwiftUI prototype that displays initial data from the shared module.
What do you think about this plan?
Greatings Martin