From 1cd313bf217594be29317534d53c2cee57e532a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duy=20Ph=E1=BA=A1m?= Date: Wed, 18 Dec 2024 15:20:51 +0700 Subject: [PATCH 1/3] Add code docs --- .../datasource/W3WMLKitImageDataSource.kt | 9 ++ .../components/extensions/MLKitExtensions.kt | 2 +- .../ocr/components/ui/OcrScanComposable.kt | 131 ++++++++++-------- .../ocr/components/ui/OcrScanManager.kt | 4 + .../ocr/components/ui/OcrScannerState.kt | 24 +++- 5 files changed, 110 insertions(+), 60 deletions(-) diff --git a/lib/src/main/java/com/what3words/ocr/components/datasource/W3WMLKitImageDataSource.kt b/lib/src/main/java/com/what3words/ocr/components/datasource/W3WMLKitImageDataSource.kt index 00f8e75..b0e30e3 100644 --- a/lib/src/main/java/com/what3words/ocr/components/datasource/W3WMLKitImageDataSource.kt +++ b/lib/src/main/java/com/what3words/ocr/components/datasource/W3WMLKitImageDataSource.kt @@ -6,6 +6,7 @@ import com.google.android.gms.common.moduleinstall.ModuleInstall import com.google.android.gms.common.moduleinstall.ModuleInstallClient import com.google.mlkit.vision.text.TextRecognition import com.google.mlkit.vision.text.TextRecognizer +import com.google.mlkit.vision.text.TextRecognizerOptionsInterface import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions import com.google.mlkit.vision.text.devanagari.DevanagariTextRecognizerOptions import com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions @@ -122,6 +123,14 @@ class W3WMLKitImageDataSource internal constructor( } companion object { + /** + * Creates a new instance of [W3WMLKitImageDataSource]. + * + * @param context The context of the application. + * @param recognizerOptions The options [TextRecognizerOptionsInterface] for configuring the text recognizer. + * + * @return A new instance of W3WMLKitImageDataSource. + */ @JvmStatic fun create( context: Context, diff --git a/lib/src/main/java/com/what3words/ocr/components/extensions/MLKitExtensions.kt b/lib/src/main/java/com/what3words/ocr/components/extensions/MLKitExtensions.kt index f9c499e..d957873 100644 --- a/lib/src/main/java/com/what3words/ocr/components/extensions/MLKitExtensions.kt +++ b/lib/src/main/java/com/what3words/ocr/components/extensions/MLKitExtensions.kt @@ -15,7 +15,7 @@ import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine /** - * Scan [image] [Bitmap] for one or more what3words addresses using MLKit. + * Scan [image] [Bitmap] for one or more possible what3words addresses using MLKit. * * @param image the [Bitmap] that the scanner should use to find possible what3words addresses. * @param onScanning the callback when it starts to scan image for text. diff --git a/lib/src/main/java/com/what3words/ocr/components/ui/OcrScanComposable.kt b/lib/src/main/java/com/what3words/ocr/components/ui/OcrScanComposable.kt index 7ae323a..bba5a9b 100644 --- a/lib/src/main/java/com/what3words/ocr/components/ui/OcrScanComposable.kt +++ b/lib/src/main/java/com/what3words/ocr/components/ui/OcrScanComposable.kt @@ -82,7 +82,14 @@ import kotlin.math.roundToInt private const val ANIMATION_DURATION = 500 //ms private const val SHEET_PEEK_HEIGHT = 90 //dp +/** + * Contains the default values used by W3WOcrScanner. + */ object W3WOcrScannerDefaults { + + /** + * The default colors used by W3WOcrScanner. + */ data class Colors( val bottomDrawerBackground: Color, val overlayBackground: Color, @@ -95,11 +102,17 @@ object W3WOcrScannerDefaults { val shutterActiveColor: Color ) + /** + * The default text styles used by W3WOcrScanner. + */ data class TextStyles( val stateTextStyle: TextStyle, val listHeaderTextStyle: TextStyle ) + /** + * The default strings used by W3WOcrScanner. + */ data class Strings( val scanStateScanningTitle: String, val scanStateDetectedTitle: String, @@ -200,46 +213,41 @@ object W3WOcrScannerDefaults { } } - /** - * A composable that implements an OCR scanner interface for detecting and processing what3words addresses. - * The scanner includes a camera preview, status display, and a list of detected addresses. - * - * The scanner provides real-time visual feedback of the scanning process and allows users to select - * from detected three-word addresses. It supports customization of appearance, text styles, and localization. + * A composable that provides an OCR scanner interface for detecting and processing what3words addresses. + * This version allows fine-grained control by using an external [OcrScannerState] parameter, making it + * suitable for integration into existing architectures. * - * @param modifier Modifier to be applied to the root BottomSheetScaffold + * This version is ideal for applications requiring high customization and tight integration with + * existing state management systems. * - * @param ocrScannerState Controls the scanner's display state and behavior + * This component includes: + * - Camera preview. + * - Status display. + * - List of detected addresses. * - * @param displayUnits Determines how distances are displayed: - * - DisplayUnits.SYSTEM (default): Uses system locale to choose Imperial/Metric - * - DisplayUnits.IMPERIAL: Forces Imperial units - * - DisplayUnits.METRIC: Forces Metric units + * @param modifier Modifier to be applied to the root BottomSheetScaffold. + * @param ocrScannerState An external state object that controls the scanner's behavior and lifecycle. + * This allows the client to manage the scanner state independently. + * @param displayUnits The unit system for displaying distances: + * - `DisplayUnits.SYSTEM` (default): Uses the system locale (Imperial/Metric). + * - `DisplayUnits.IMPERIAL`: Forces Imperial units. + * - `DisplayUnits.METRIC`: Forces Metric units. + * @param scannerColors Customizable color scheme for the scanner's interface. + * @param scannerTextStyles Customizable text styles for UI elements. + * @param scannerStrings Localized strings for scanner UI and accessibility. + * @param suggestionTextStyles Text styles for the list of detected what3words addresses. + * @param suggestionColors Color scheme for the list of detected addresses. + * @param suggestionNearestPlacePrefix A prefix for displaying the nearest place, e.g., "near". + * @param onFrameCaptured Callback triggered when a camera frame is captured for processing. + * - Params: `W3WImage` - The captured image frame. + * - Returns: `CompletableDeferred` - Signals when processing is complete. + * @param onSuggestionSelected Callback triggered when a user selects a three-word address. + * - Params: `W3WSuggestion` - The selected address. + * @param onError Callback triggered when an error occurs. + * - Params: `W3WError` - The error details. + * @param onDismiss Callback triggered when the scanner is manually dismissed by the user. * - * @param scannerColors Defines the scanner's color scheme - * - * @param scannerTextStyles Defines text styling for scanner UI elements - * - * @param scannerStrings Provides localized strings for UI elements and accessibility - * - * @param suggestionTextStyles Defines text styling for the address list items - * - * @param suggestionColors Defines colors for the address list items - * - * @param suggestionNearestPlacePrefix Prefix text for nearest place display - * - * @param onFrameCaptured Callback for processing captured camera frames - * Params: W3WImage - The captured frame - * Returns: CompletableDeferred to signal processing completion and the internal image analyzer should capture a new image for processing - * - * @param onSuggestionSelected Callback when user selects an address suggestion - * Params: W3WSuggestion - The selected address - * - * @param onError Callback for error handling - * Params: W3WError - The error that occurred - * - * @param onDismiss Callback when user manually closes the scanner */ @OptIn(ExperimentalPermissionsApi::class) @Composable @@ -296,30 +304,37 @@ fun W3WOcrScanner( } /** - * Creates a new [W3WOcrScanner] Composable to utilize CameraX and a [OcrScanManager] for scanning what3words addresses using text recognition. - * This component integrates camera functionality with OCR (Optical Character Recognition) to detect and validate three-word addresses in real-time. + * A composable that provides an OCR scanner interface for detecting and processing what3words addresses. + * This version simplifies integration by internally managing the scanner's state with [OcrScanManager], + * making it easy to use in projects without the need for external state management. + * + * This version is ideal for projects requiring quick and easy integration without extensive + * customization or state management. + * + * This component includes: + * - Camera preview. + * - Status display. + * - List of detected addresses. * - * @param modifier An optional [Modifier] for customizing the appearance and layout of the root [BottomSheetScaffold]. - * @param ocrScanManager The [OcrScanManager] instance that manages the OCR scanning process. - * @param displayUnits The unit system ([DisplayUnits]) for displaying distances. Defaults to [DisplayUnits.SYSTEM], - * which uses the system's locale to determine whether to use the Imperial or Metric system. - * @param scannerColors The color scheme ([W3WOcrScannerDefaults.Colors]) applied to the [W3WOcrScanner]. - * Defaults are provided by [W3WOcrScannerDefaults.defaultColors] and can be overridden. - * @param scannerTextStyles The text styles ([W3WOcrScannerDefaults.TextStyles]) applied to the [W3WOcrScanner]. - * Defaults are provided by [W3WOcrScannerDefaults.defaultTextStyles] and can be overridden. - * @param scannerStrings Localized strings ([W3WOcrScannerDefaults.Strings]) used in the [W3WOcrScanner] for customization - * and accessibility. Defaults are provided by [W3WOcrScannerDefaults.defaultStrings] and can be overridden. - * @param suggestionTextStyles Text styles ([What3wordsAddressListItemDefaults.TextStyles]) applied to the list of scanned - * three-word addresses. Defaults are set by [What3wordsAddressListItemDefaults.defaultTextStyles] - * and can be overridden. - * @param suggestionColors Color scheme ([What3wordsAddressListItemDefaults.Colors]) applied to the list of scanned - * three-word addresses. Defaults are set by [What3wordsAddressListItemDefaults.defaultColors] - * and can be overridden. - * @param suggestionNearestPlacePrefix The prefix for displaying the nearest place in [What3wordsAddressListItem]. Defaults to the resource string [com.what3words.design.library.R.string.near]. - * @param onSuggestionFound Callback invoked when a [W3WSuggestion] is found in the [OcrScanManager]. - * @param onSuggestionSelected Callback invoked when a [W3WSuggestion] is selected from the [SuggestionPicker] - * @param onError Callback invoked when an error occurs within this composable, providing a [W3WError]. - * @param onDismiss Callback invoked when this composable is closed using the close button, indicating a user dismissal without an error or a selected suggestion. + * @param modifier Modifier to be applied to the root BottomSheetScaffold. + * @param ocrScanManager A manager object that handles the scanner's state and processing automatically. + * @param displayUnits The unit system for displaying distances: + * - `DisplayUnits.SYSTEM` (default): Uses the system locale (Imperial/Metric). + * - `DisplayUnits.IMPERIAL`: Forces Imperial units. + * - `DisplayUnits.METRIC`: Forces Metric units. + * @param scannerColors Customizable color scheme for the scanner's interface. + * @param scannerTextStyles Customizable text styles for UI elements. + * @param scannerStrings Localized strings for scanner UI and accessibility. + * @param suggestionTextStyles Text styles for the list of detected three-word addresses. + * @param suggestionColors Color scheme for the list of detected addresses. + * @param suggestionNearestPlacePrefix A prefix for displaying the nearest place, e.g., "near". + * @param onSuggestionSelected Callback triggered when a user selects a three-word address. + * - Params: `W3WSuggestion` - The selected address. + * @param onSuggestionFound (Optional) Callback triggered when a suggestion is detected in real-time. + * - Params: `W3WSuggestion` - The detected suggestion. + * @param onError Callback triggered when an error occurs. + * - Params: `W3WError` - The error details. + * @param onDismiss Callback triggered when the scanner is manually dismissed by the user. */ @OptIn(ExperimentalPermissionsApi::class) @Composable diff --git a/lib/src/main/java/com/what3words/ocr/components/ui/OcrScanManager.kt b/lib/src/main/java/com/what3words/ocr/components/ui/OcrScanManager.kt index 392a54b..c10cb39 100644 --- a/lib/src/main/java/com/what3words/ocr/components/ui/OcrScanManager.kt +++ b/lib/src/main/java/com/what3words/ocr/components/ui/OcrScanManager.kt @@ -42,6 +42,10 @@ class OcrScanManager( */ private val _ocrScannerState = MutableStateFlow(OcrScannerState()) val ocrScannerState: StateFlow = _ocrScannerState.asStateFlow() + + /** + * Flag to indicate if the OCR scanner is currently stopping. It don't accept new images for processing. + */ private var isStopping: Boolean = false /** diff --git a/lib/src/main/java/com/what3words/ocr/components/ui/OcrScannerState.kt b/lib/src/main/java/com/what3words/ocr/components/ui/OcrScannerState.kt index 0b557fe..73e980d 100644 --- a/lib/src/main/java/com/what3words/ocr/components/ui/OcrScannerState.kt +++ b/lib/src/main/java/com/what3words/ocr/components/ui/OcrScannerState.kt @@ -4,14 +4,36 @@ import androidx.compose.runtime.Stable import com.what3words.core.types.domain.W3WSuggestion /** - * A state object that can be hoisted to control the [W3WOcrScanner]. + * Represents the state of an [W3WOcrScanner], including detected what3words suggestions + * and the current operational state of the scanner. + * + * @property foundItems A list of `W3WSuggestion` objects representing the detected what3words + * addresses. Defaults to an empty list. + * @property state The current operational state of the OCR scanner, represented by the nested + * `State` enum. Defaults to `State.Idle`. */ @Stable data class OcrScannerState( + /** + * List of detected what3words addresses. + */ val foundItems: List = listOf(), + + /** + * Current operational state of the OCR scanner. + */ val state: State = State.Idle ) { + /** + * Represents the operational states of the OCR scanner. + * + * - `Idle`: The scanner is not currently active. + * - `Scanning`: The scanner is actively capturing frames and searching for what3words addresses. + * - `Detected`: Potential what3words addresses have been detected but are not yet validated. + * - `Validating`: The detected addresses are being validated for accuracy. + * - `Found`: One or more valid what3words addresses have been successfully detected. + */ enum class State { Idle, Scanning, From 70801692201f1e47467b656e4934e4682d7ac2da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duy=20Ph=E1=BA=A1m?= Date: Wed, 18 Dec 2024 15:21:01 +0700 Subject: [PATCH 2/3] Update README --- README.md | 203 +++++++++++++++++++++++++----------------------------- 1 file changed, 92 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index 745bfb4..fe66621 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,9 @@ [![Maven Central](https://img.shields.io/maven-central/v/com.what3words/w3w-android-ocr-components.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.what3words%22%20AND%20a:%22w3w-android-ocr-components%22) -### Android minumum SDK support +### Android minimum SDK support [![Generic badge](https://img.shields.io/badge/minSdk-24-green.svg)](https://developer.android.com/about/versions/marshmallow/android-7.0/) - An Android library to scan what3words address using [MLKit V2](https://developers.google.com/ml-kit/vision/text-recognition/v2/android). @@ -18,148 +17,130 @@ To obtain an API key, please visit [https://what3words.com/select-plan](https:// implementation 'com.what3words:w3w-android-ocr-components:$latest' ``` -## Sample using w3w-android-wrapper library +## Sample app -[ocr-sample](https://github.com/what3words/w3w-android-samples/tree/main/ocr-sample) +This repository includes a [sample app](https://github.com/what3words/w3w-android-samples/tree/main/ocr-sample) demonstrating the usage of the what3words OCR component. -## Usage +## Usages -There are two ways to use our MLKit OCR Component: +Adding a `W3WOcrScanner` to your app looks like the following: -1. As an Activity, **MLKitOcrScanActivity**, that should be used as an activity for result, which have minimum setup but doesn't allow style customisation. Our library handles all lifecycle and scan flow and will return the selected scanned three word address. Custom localisation and accessibility are available. +```kotlin +W3WOcrScanner( + ocrScanManager = ocrScanManager, + onDismiss = {}, + onSuggestionSelected = {}, + onError = {}, + onSuggestionFound = {} +) +``` +
+ Creating a OcrScanManager -2. Using our Jetpack Compose Composable **W3WOcrScanner**, will allow all the above, but the results are returned as a callback (selection and errors) and will enable styling customisation, allowing to override all styles used on our composable with just a couple of extra steps to setup. +### Creating a OcrScanManager -### Using MLKitOcrScanActivity (#1) +OcrScanManager encapsulates the scanner’s state and logic within it. It uses the `W3WImageDataSource` to scan images for possible what3words addresses, and the `W3WTextDataSource` to validate detected addresses. -```Kotlin -class MainActivity : AppCompatActivity() { +```kotlin +val w3WImageDataSource = W3WMLKitImageDataSource.create( + context = context, + recognizerOptions = TextRecognizerOptionsInterface.LATIN +) + +val w3WTextDataSource = W3WApiTextDataSource.create(context, W3W_API_KEY) + +val ocrScanManager = rememberOcrScanManager( + w3wImageDataSource = w3WImageDataSource, + w3wTextDataSource = w3WTextDataSource, +) - private val resultLauncher = - registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - when { - //registerForActivityResult success with result - result.resultCode == Activity.RESULT_OK && result.data?.hasExtra(BaseOcrScanActivity.SUCCESS_RESULT_ID) == true -> { - val suggestion = - result.data!!.serializable(BaseOcrScanActivity.SUCCESS_RESULT_ID) - //TODO: Handle suggestion scanned - } - //registerForActivityResult canceled with error - result.resultCode == Activity.RESULT_CANCELED && result.data?.hasExtra( - BaseOcrScanActivity.ERROR_RESULT_ID - ) == true -> { - val error = - result.data!!.getStringExtra(BaseOcrScanActivity.ERROR_RESULT_ID) - //TODO: Handle error - } - //registerForActivityResult canceled by user. - else -> { - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - ... - //Options to filter the OCR scanning or like this example providing current location for more accurate results/distances to three word addresses. - val options = AutosuggestOptions().apply { - this.focus = Coordinates(51.23, 0.1) - } - - //Per default the scanned three word address will not return coordinate information, if you set returnCoordinates to true when instanciating a new MLKitOcrScanActivity, it will return coordinates and this might results in charge against your API Key. - val returnCoordinates = true - - //MLKitOcrScanActivity.newInstanceWithApi allows to provide all strings to be used internally for localisation and accessibility propuses. This should be used on a click actions, i.e: button click. - val intent = MLKitOcrScanActivity.newInstanceWithApi( - context = this, - mlKitLibrary = com.google.mlkit.vision.text.TextRecognizerOptionsInterface.LATIN, - apiKey = "YOUR_API_KEY_HERE", - options = options, - returnCoordinates = returnCoordinates, - scanStateFoundTitle = "Custom found title" - ) - try { - resultLauncher.launch(intent) - } catch (e: ExceptionInInitializerError) { - //TODO: Handle Error - } - } -} ``` -### Using W3WOcrScanner Composable (#2) +
-```Kotlin -class MainActivity : ComponentActivity() { - private lateinit var ocrWrapper: W3WOcrWrapper +
+ Using OcrScannerState - override fun onDestroy() { - super.onDestroy() - if (::ocrWrapper.isInitialized) ocrWrapper.stop() - } - - override fun onCreate(savedInstanceState: Bundle?) { - //This example uses Latin MLKit library, check MLKit documentation of how to instanciate other libraries like Korean, Japanese, Devanagari or Chinese. - val textRecognizer = com.google.mlkit.vision.text.TextRecognizerOptionsInterface.LATIN +### Using OcrScannerState - //Options to filter the OCR scanning or like this example providing current location for more accurate results/distances to three word addresses. - val options = AutosuggestOptions().apply { - this.focus = Coordinates(51.23, 0.1) - } +If you prefer more control over the scanner's state, you can use `OcrScannerState` directly instead of using `OcrScanManager`. This allows you to manage the state externally and integrate the component into your existing architecture. - //Per default the scanned three word address will not return coordinate information, if you set returnCoordinates to true when instanciating a new MLKitOcrScanActivity, it will return coordinates and this might results in charge against your API Key. - val returnCoordinates = true - - val dataProvider = What3WordsV3("YOUR_API_KEY_HERE", this) - ocrWrapper = W3WOcrMLKitWrapper(this, textRecognizer) - - setContent { - YourTheme { - W3WOcrScanner( - ocrWrapper, - dataProvider = dataProvider, - modifier = Modifier.fillMaxSize(), - options = options, - returnCoordinates = returnCoordinates, - onError = { error -> - //TODO: Handle error - }, - onDismiss = { - //TODO: Dismissed by user, hide W3WOcrScanner using AnimatedVisibility or finish activity. - }, - onSuggestionSelected = { scannedSuggestion -> - //TODO: Use scanned three word address info, hide W3WOcrScanner using AnimatedVisibility or finish activity. - } - ) - } +#### Example Usage +```kotlin +val ocrScannerState = remember { OcrScannerState() } + +W3WOcrScanner( + ocrScannerState = ocrScannerState, + onError = { error -> + // Handle the error + }, + onDismiss = { + // Handle scanner dismissal + }, + onFrameCaptured = { image -> + // Scanner has captured a frame, you will need to implement your own functions to detect the what3words addresses in the frame and then update the ocrScannerState + + CompletableDeferred().apply { + // Signal completion when processing is done + complete(Unit) } - } -} + }, + onSuggestionSelected = { suggestion -> + // Handle address selection + }, +) ``` -### Styling W3WOcrScanner (#2) +#### Comparison Between using OcrScanManager and OcrScannerState directly +| Feature/Aspect | **OcrScanManager** | **OcrScannerState** | +|-------------------------------|-----------------------------------------------------------------|----------------------------------------------------------| +| **Ease of Use** | Encapsulates scanner state and logic, easier to use out of the box. | Provides more granular control but requires extra setup. | +| **State Management** | Internal state management, ideal for simple integrations. | External state management, better for complex apps. | +| **Customizability** | Limited to predefined functionalities. | High, allows deep customization and integration. | +| **Use Case** | Quick implementation without managing internal details. | Advanced use cases needing dynamic or external control. | +| **Flexibility** | Limited flexibility. -```Kotlin +
+ +
+ Styling W3WOcrScanner + +### Styling W3WOcrScanner + +You can customize the appearance of the `W3WOcrScanner` by providing parameters for strings, colors, and text styles. + +```kotlin W3WOcrScanner( ... - //optional if you want to override any string of the scanner composable, to allow localisation and accessibility. scannerStrings = W3WOcrScannerDefaults.defaultStrings( scanStateFoundTitle = stringResource(id = R.string.scan_state_found), ), - //optional if you want to override any colors of the scanner composable. scannerColors = W3WOcrScannerDefaults.defaultColors( bottomDrawerBackground = W3WTheme.colors.background ), - //optional if you want to override any text styles. scannerTextStyles = W3WOcrScannerDefaults.defaultTextStyles( stateTextStyle = W3WTheme.typography.headline ), - //optional if you want to override any colors of the scanned list item composable. suggestionColors = SuggestionWhat3wordsDefaults.defaultColors( background = W3WTheme.colors.background ), - //optional if you want to override any text styles of the scanned list item composable. suggestionTextStyles = SuggestionWhat3wordsDefaults.defaultTextStyles( wordsTextStyle = W3WTheme.typography.headline ) -) +) ``` + +
+ +
+ Camera Permission + +### Camera Permission + +The OCR component requires camera permission to function. Add the following permission to your app’s `AndroidManifest.xml` file: + +```xml + +``` + +
From e4b727ca064b86ca8c05179318ecd2634c1294c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duy=20Ph=E1=BA=A1m?= Date: Thu, 19 Dec 2024 13:39:36 +0700 Subject: [PATCH 3/3] Update README --- README.md | 141 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index fe66621..54f40df 100644 --- a/README.md +++ b/README.md @@ -2,44 +2,48 @@ [![Maven Central](https://img.shields.io/maven-central/v/com.what3words/w3w-android-ocr-components.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.what3words%22%20AND%20a:%22w3w-android-ocr-components%22) -### Android minimum SDK support -[![Generic badge](https://img.shields.io/badge/minSdk-24-green.svg)](https://developer.android.com/about/versions/marshmallow/android-7.0/) - An Android library to scan what3words address using [MLKit V2](https://developers.google.com/ml-kit/vision/text-recognition/v2/android). -To obtain an API key, please visit [https://what3words.com/select-plan](https://what3words.com/select-plan) and sign up for an account. +To obtain an API key, please [sign up here](https://what3words.com/select-plan). -### Gradle +### Android minimum SDK support +[![Generic badge](https://img.shields.io/badge/minSdk-24-green.svg)](https://developer.android.com/about/versions/marshmallow/android-7.0/) +### Gradle Dependency ``` implementation 'com.what3words:w3w-android-ocr-components:$latest' ``` -## Sample app +## Sample App This repository includes a [sample app](https://github.com/what3words/w3w-android-samples/tree/main/ocr-sample) demonstrating the usage of the what3words OCR component. -## Usages +## Usage -Adding a `W3WOcrScanner` to your app looks like the following: +Adding a `W3WOcrScanner` to your app: ```kotlin W3WOcrScanner( ocrScanManager = ocrScanManager, - onDismiss = {}, - onSuggestionSelected = {}, - onError = {}, - onSuggestionFound = {} + onDismiss = { + // Handle scanner dismissal + }, + onSuggestionSelected = { suggestion -> + // Handle address selection + }, + onError = { error -> + // Handle the error + }, ) ``` -
- Creating a OcrScanManager -### Creating a OcrScanManager -OcrScanManager encapsulates the scanner’s state and logic within it. It uses the `W3WImageDataSource` to scan images for possible what3words addresses, and the `W3WTextDataSource` to validate detected addresses. +
+ Creating an OcrScanManager + +OcrScanManager encapsulates the scanner’s state and logic leveraging `W3WImageDataSource` and `W3WTextDataSource` for scanning and validating addresses. ```kotlin val w3WImageDataSource = W3WMLKitImageDataSource.create( @@ -55,15 +59,19 @@ val ocrScanManager = rememberOcrScanManager( ) ``` +**Setup Options** +One of the significant enhancements in v2.0 is the flexibility to choose and configure different data sources for the OCR component. + +- **Online Setup**: Use MLKit for scanning and W3WApiTextDataSource for online validation. +- **Offline Setup**: Replace W3WMLKitImageDataSource with W3WTesseractImageDataSource for offline scanning and W3WSdkTextDataSource for offline validation. +> (Offline setup requires additional licensing; contact us for details.)
Using OcrScannerState -### Using OcrScannerState - -If you prefer more control over the scanner's state, you can use `OcrScannerState` directly instead of using `OcrScanManager`. This allows you to manage the state externally and integrate the component into your existing architecture. +If you prefer more control over the scanner's state, you can use `OcrScannerState` directly, instead of using `OcrScanManager`. This allows you to manage the state externally and integrate the component into your existing architecture. #### Example Usage ```kotlin @@ -78,7 +86,7 @@ W3WOcrScanner( // Handle scanner dismissal }, onFrameCaptured = { image -> - // Scanner has captured a frame, you will need to implement your own functions to detect the what3words addresses in the frame and then update the ocrScannerState + // Scanner has captured a frame, you will need to implement your functions to detect the what3words addresses in the frame and then update the ocrScannerState CompletableDeferred().apply { // Signal completion when processing is done @@ -91,11 +99,11 @@ W3WOcrScanner( ) ``` -#### Comparison Between using OcrScanManager and OcrScannerState directly +#### Feature Comparison: OcrScanManager vs. OcrScannerState | Feature/Aspect | **OcrScanManager** | **OcrScannerState** | |-------------------------------|-----------------------------------------------------------------|----------------------------------------------------------| -| **Ease of Use** | Encapsulates scanner state and logic, easier to use out of the box. | Provides more granular control but requires extra setup. | -| **State Management** | Internal state management, ideal for simple integrations. | External state management, better for complex apps. | +| **Ease of Use** | Encapsulates scanner state and logic easier to use out of the box. | Provides more granular control but requires extra setup. | +| **State Management** | Internal state management is ideal for simple integrations. | External state management is better for complex apps. | | **Customizability** | Limited to predefined functionalities. | High, allows deep customization and integration. | | **Use Case** | Quick implementation without managing internal details. | Advanced use cases needing dynamic or external control. | | **Flexibility** | Limited flexibility. @@ -105,9 +113,7 @@ W3WOcrScanner(
Styling W3WOcrScanner -### Styling W3WOcrScanner - -You can customize the appearance of the `W3WOcrScanner` by providing parameters for strings, colors, and text styles. +You can customise the appearance of the `W3WOcrScanner` by providing parameters for strings, colours, and text styles. ```kotlin W3WOcrScanner( @@ -135,8 +141,6 @@ W3WOcrScanner(
Camera Permission -### Camera Permission - The OCR component requires camera permission to function. Add the following permission to your app’s `AndroidManifest.xml` file: ```xml @@ -144,3 +148,84 @@ The OCR component requires camera permission to function. Add the following perm ```
+ +## Migrating to v2.0 + +For guidance on upgrading from v1.x to v2.0, see the migration steps below: + +--- + +### Introduction to the Core Library + +The [Core Library](https://github.com/what3words/w3w-core-library) introduces essential models and interfaces that ensure consistency across various what3words libraries. In v2.0 of the OCR component, many existing models have been replaced by those from the Core Library. For more details on the new models, please refer to this [README](https://github.com/what3words/w3w-android-wrapper?tab=readme-ov-file#introduce-of-the-core-library). + +--- + +### Migration steps + +
+ Step 1: Update Dependencies + +Update your app's dependencies to use the latest version of the what3words OCR components: + +```gradle +implementation 'com.what3words:w3w-android-ocr-components:$latest' +``` + +Ensure your build file is synced and the dependencies are updated to avoid conflicts. + +
+ +
+ Step 2: Replace Deprecated Models + +In v2.0, many models from v1.x have been deprecated in favour of the new models provided by the Core Library. Unfortunately, there is no automated process for this migration. You'll need to manually replace the old models with their counterparts from the Core Library. + +
+ +
+ Step 3: Replace W3WOcrMLKitWrapper with OcrScanManager + +In v1.x, you may have used the following setup: + +```kotlin +val dataProvider = What3WordsV3(W3W_API_KEY, context) +ocrWrapper = W3WOcrMLKitWrapper(context, textRecognizer) + +W3WOcrScanner( + ocrWrapper, + dataProvider = dataProvider, + .... +) +``` + +In v2.0, this has been simplified with the introduction of OcrScanManager. Here’s the updated implementation: + +```kotlin +val w3WImageDataSource = W3WMLKitImageDataSource.create( + context = context, + recognizerOptions = TextRecognizerOptionsInterface.LATIN +) + +val w3WTextDataSource = W3WApiTextDataSource.create(context, W3W_API_KEY) + +val ocrScanManager = rememberOcrScanManager( + w3wImageDataSource = w3WImageDataSource, + w3wTextDataSource = w3WTextDataSource, +) + +W3WOcrScanner( + ocrScanManager = ocrScanManager, + ... +) +``` + +The OcrScanManager encapsulates scanning logic and state management, providing a more streamlined API. + +
+ +
+ Step 4: Removal of MLKitOcrScanActivity + +MLKitOcrScanActivity has been deprecated. For standalone activity support, leverage Jetpack Compose interoperability. Learn more in [this tutorial](https://developer.android.com/develop/ui/compose/migrate/interoperability-apis/compose-in-views). +
\ No newline at end of file