Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:
- README.md
- ROADMAP.md
- TODO.md
- app/src/main/java/com/musagenius/ocrapp/MainActivity.kt
- app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt
- app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt
- app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt
- app/src/test/java/com/musagenius/ocrapp/data/repository/ScanRepositoryImplTest.kt
- app/src/test/java/com/musagenius/ocrapp/data/mapper/ScanMapperTest.kt
This document provides a technical overview of the architecture for the Material Expressive Android OCR App. The application is designed to be a modern, offline-first tool for text extraction, built with a focus on maintainability, testability, and a clean user interface.
The architecture follows the principles of MVVM (Model-View-ViewModel) combined with Clean Architecture. This layered approach separates concerns, ensuring that the business logic is independent of the UI and data sources. The core technologies include Jetpack Compose for the UI, Tesseract for offline OCR, Room for local storage, Hilt for dependency injection, and Kotlin Coroutines for asynchronous operations.
Sources: README.md:13-17, ROADMAP.md:38-46
High-Level Architecture
The application is structured into three primary layers: Presentation, Domain, and Data. This separation decouples the components, making the system easier to develop, test, and maintain.
Sources: README.md:27-33
This diagram illustrates the layered architecture and the flow of control and data between layers.
Architecture Layers
| Layer | Responsibility | Key Components |
|---|---|---|
| Presentation | Handles all UI and user interaction. Displays data from the ViewModel and sends user events to it. | Jetpack Compose Screens (CameraScreen, OCRResultScreen), ViewModel (OCRViewModel), Navigation (NavHost). |
| Domain | Contains the core business logic and rules of the application. It is independent of any other layer. | Use Cases (ProcessImageUseCase), Domain Models (ScanResult, OCRConfig), Repository Interfaces. |
| Data | Manages all data operations. It implements the repository interfaces defined in the domain layer and provides data from various sources (local database, OCR engine). | Repository Implementations (ScanRepositoryImpl), Data Sources (OCRServiceImpl, Room ScanDao), Mappers. |
Sources: README.md:27-39, ROADMAP.md:54-82
Presentation Layer
The Presentation layer is built entirely with Jetpack Compose and Material 3, providing a modern and reactive UI. It follows the MVVM pattern, where ViewModels expose state to the UI and handle user events.
Sources: README.md:15, app/src/main/java/com/musagenius/ocrapp/MainActivity.kt
UI and Navigation
The UI is composed of several composable screens managed by Jetpack Navigation Compose. The main entry point is MainActivity, which sets up the NavHost.
Key screens defined in the navigation graph include:
CameraScreen: Captures images or selects them from the gallery.ImageEditorScreen: Allows cropping and rotation before OCR.OCRResultScreen: Displays the extracted text and provides actions like copy, share, and save.HistoryScreen&SettingsScreen: Placeholder screens for future implementation.
Sources: app/src/main/java/com/musagenius/ocrapp/MainActivity.kt:29-106
The navigation flow for a new scan is as follows:
This diagram shows the primary navigation paths for processing an image.
Sources: app/src/main/java/com/musagenius/ocrapp/MainActivity.kt:41-106
ViewModel and State Management
The OCRViewModel is responsible for the logic of the OCR results screen. It manages the UI state using a StateFlow<OCRUiState> and processes user actions via an onEvent function.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt:24-27
The interaction between the UI, ViewModel, and Domain layer is depicted below:
This sequence diagram shows how a user action to process an image flows through the ViewModel to the use case and back to the UI as state updates.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt:53-112
Domain Layer
The Domain layer is the core of the application, containing business logic and models. It is completely independent of the Android framework.
Sources: README.md:30-31, ROADMAP.md:104-113
Domain Models
The primary models define the data structures for OCR configuration and results.
This class diagram shows the key domain models and their properties.
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt, app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt
OCRConfig
This data class holds all settings for an OCR operation.
| Field | Type | Default Value | Description |
|---|---|---|---|
language | String | "eng" | The language for text recognition (e.g., "eng", "fra"). |
pageSegmentationMode | PageSegMode | AUTO | Tesseract's page segmentation mode. |
engineMode | EngineMode | DEFAULT | Tesseract's OCR engine mode. |
preprocessImage | Boolean | true | Whether to apply preprocessing steps to the image. |
maxImageDimension | Int | 2000 | The maximum width/height for image scaling before OCR. |
enableAutoRotation | Boolean | false | Whether to enable auto-rotation. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt:6-13
Use Cases
Use cases encapsulate specific business logic. For example, ProcessImageUseCase is injected into OCRViewModel to handle the entire OCR workflow for a given image URI and configuration. This isolates the logic from the ViewModel.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt:20, 80-82
Data Layer
The Data layer is responsible for providing data to the domain layer. It contains repository implementations and data sources.
Sources: README.md:32-33, ROADMAP.md:54-82
Repository Pattern
The repository pattern is used to abstract data sources. ScanRepositoryImpl is the implementation that interacts with the local Room database via a ScanDao. It handles mapping between the data-layer ScanEntity and the domain-layer ScanResult.
Sources: app/src/test/java/com/musagenius/ocrapp/data/repository/ScanRepositoryImplTest.kt:26, app/src/test/java/com/musagenius/ocrapp/data/mapper/ScanMapperTest.kt
OCR Service (OCRServiceImpl)
OCRServiceImpl is a critical component that wraps the tess-two Tesseract library. It is a thread-safe singleton that manages the lifecycle of the TessBaseAPI.
Key responsibilities include:
- Thread Safety: Uses a
Mutexto serialize all access to theTessBaseAPI, preventing race conditions from concurrent OCR requests. - Initialization: Initializes Tesseract, sets the language, and configures the page segmentation mode.
- Tessdata Management: On first use for a language, it copies the required
.traineddatafile from the app's assets to the device storage where Tesseract can access it. - Image Preprocessing: Utilizes an
ImagePreprocessorto enhance the image quality before sending it to Tesseract. - Text Recognition: Exposes
recognizeTextandrecognizeTextWithProgressmethods to perform OCR on aBitmap. - Resource Management: Provides
stop()andcleanup()methods to manage the native Tesseract resources.
Sources: app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:22, 25, 41-45, 101, 122
The OCR processing flow within the service is as follows:
This flowchart details the steps inside OCRServiceImpl to process an image.
Sources: app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:92-132
Local Storage (Room)
The application is planned to use the Room persistence library to save scan history. A ScanEntity will represent the table structure, and a ScanDao will define the CRUD operations. The ScanRepositoryImpl will use this DAO to persist and retrieve scan data.
The planned schema for a scan is based on the ScanResult domain model:
This ER diagram shows the planned scans table structure.
Sources: TODO.md:12-16, app/src/main/java/com/musagenius/ocrapp/domain/model/ScanResult.kt:9-20, app/src/test/java/com/musagenius/ocrapp/data/mapper/ScanMapperTest.kt:48-64
Conclusion
The architecture of the OCR Android App is a well-defined, layered system based on modern Android development practices. By combining MVVM with Clean Architecture, the application achieves a strong separation of concerns, which enhances testability, scalability, and maintainability. The use of Jetpack Compose, Hilt, Coroutines, and Room provides a robust foundation for building an offline-first, high-performance application. The core OCR functionality is encapsulated within a thread-safe service, abstracting the complexities of the native Tesseract engine from the rest of the app.