cordova-plugin-mlkit-suite 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +526 -3
  4. package/docs/mlkit-logo.svg +17 -0
  5. package/docs/screenshots/barcode-scanning.png +0 -0
  6. package/docs/screenshots/document-scanning.jpg +0 -0
  7. package/docs/screenshots/face-capture.png +0 -0
  8. package/docs/screenshots/ios-text-recognition.jpg +0 -0
  9. package/package.json +66 -6
  10. package/plugin.xml +149 -0
  11. package/src/android/java/BarcodeConfirmationTracker.java +38 -0
  12. package/src/android/java/BarcodeFrameAnalyzer.java +115 -0
  13. package/src/android/java/BarcodeIconDrawable.java +67 -0
  14. package/src/android/java/BarcodeOverlayView.java +208 -0
  15. package/src/android/java/BarcodeScanActivity.java +396 -0
  16. package/src/android/java/BarcodeScanConfig.java +195 -0
  17. package/src/android/java/BarcodeScanRegion.java +51 -0
  18. package/src/android/java/DocumentScanActivity.java +202 -0
  19. package/src/android/java/DocumentScanConfig.java +142 -0
  20. package/src/android/java/DocumentScannerModuleInstaller.java +138 -0
  21. package/src/android/java/FaceCaptureActivity.java +367 -0
  22. package/src/android/java/FaceCaptureConfig.java +174 -0
  23. package/src/android/java/FaceCaptureModels.java +85 -0
  24. package/src/android/java/FaceFrameAnalyzer.java +185 -0
  25. package/src/android/java/FaceOverlayView.java +122 -0
  26. package/src/android/java/FaceStillProcessor.java +237 -0
  27. package/src/android/java/MlKitLoadingDialog.java +73 -0
  28. package/src/android/java/MlKitLocalization.java +80 -0
  29. package/src/android/java/MlKitModelsModuleInstaller.java +234 -0
  30. package/src/android/java/MlKitSuitePlugin.java +1008 -0
  31. package/src/android/java/SelfieSegmentationProcessor.java +215 -0
  32. package/src/android/java/StaticImageProcessor.java +208 -0
  33. package/src/android/java/SubjectSegmentationModuleInstaller.java +154 -0
  34. package/src/android/java/SubjectSegmentationProcessor.java +189 -0
  35. package/src/android/mlkit-suite.gradle +217 -0
  36. package/src/android/res/values/mlkit_suite_strings.xml +81 -0
  37. package/src/android/res/values/mlkit_suite_styles.xml +15 -0
  38. package/src/android/res/values-es/mlkit_suite_strings.xml +81 -0
  39. package/src/ios/BarcodeOverlayView.swift +193 -0
  40. package/src/ios/BarcodeScanTypes.swift +166 -0
  41. package/src/ios/BarcodeScanViewController.swift +507 -0
  42. package/src/ios/FaceCaptureTypes.swift +189 -0
  43. package/src/ios/FaceCaptureViewController.swift +437 -0
  44. package/src/ios/FaceOverlayView.swift +170 -0
  45. package/src/ios/FaceStillProcessor.swift +143 -0
  46. package/src/ios/MlKitLocalization.swift +62 -0
  47. package/src/ios/MlKitSuitePlugin.swift +803 -0
  48. package/src/ios/MlKitSuitePrivacy.bundle/PrivacyInfo.xcprivacy +15 -0
  49. package/src/ios/MlKitSuiteResources.bundle/Info.plist +14 -0
  50. package/src/ios/MlKitSuiteResources.bundle/en.lproj/Localizable.strings +74 -0
  51. package/src/ios/MlKitSuiteResources.bundle/es.lproj/Localizable.strings +74 -0
  52. package/src/ios/SelfieSegmentationProcessor.swift +105 -0
  53. package/src/ios/TextRecognitionProcessor.swift +99 -0
  54. package/tests/ios-face-capture.test.js +43 -0
  55. package/tests/ios-image-labeling.test.js +17 -0
  56. package/tests/ios-live-barcode.test.js +59 -0
  57. package/tests/ios-selfie-segmentation.test.js +24 -0
  58. package/tests/ios-static-text.test.js +21 -0
  59. package/tests/java/BarcodeConfirmationTrackerTest.java +29 -0
  60. package/tests/java/BarcodeScanRegionTest.java +38 -0
  61. package/tests/java-confirmation.test.js +41 -0
  62. package/tests/js-api.test.js +176 -0
  63. package/tests/localization.test.js +49 -0
  64. package/www/MlKit.js +306 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ## 0.2.0 - 2026-10-26
6
+
7
+ - Added default-model Image Labeling on Android and iOS, including configurable Android model delivery.
8
+ - Added bundled Selfie Segmentation on Android and iOS with transparent PNG output.
9
+ - Added unbundled Subject Segmentation on Android with transparent PNG output.
10
+ - Added frozen-frame barcode success feedback that animates the guide onto the detected code on Android and iOS.
11
+ - Added the optional `beepEnabled` barcode confirmation sound, enabled by default on Android and iOS.
12
+ - Fixed iOS live barcode geometry and explicit camera mirroring configuration.
13
+ - Fixed guided face capture on iOS by producing the final JPEG from the same portrait video frame accepted by ML Kit, avoiding a second EXIF-dependent detection pass.
14
+ - Added per-check colors to the iOS face capture debug overlay.
15
+ - Improved iOS static text recognition for rotated gallery images by evaluating all four cardinal orientations.
16
+
17
+ ## 0.1.0
18
+
19
+ - Initial Android and iOS release; requires Android 7/API 24 with `cordova-android` 12–15, or iOS 15.5 with `cordova-ios` 8.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andres Zs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,526 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ ![npm downloads](https://img.shields.io/npm/dt/cordova-plugin-mlkit-suite) ![npm version](https://img.shields.io/npm/v/cordova-plugin-mlkit-suite) ![GitHub package.json version](https://img.shields.io/github/package-json/v/andreszs/cordova-plugin-mlkit-suite?color=FF6D00&label=main&logo=github) [![Android and iOS demo](https://img.shields.io/badge/demo-Android%20%7C%20iOS-2ea44f?logo=apachecordova&logoColor=white)](https://github.com/andreszs/cordova-plugin-demos/tree/main/com.andreszs.mlkit.suite.demo) ![GitHub license](https://img.shields.io/github/license/andreszs/cordova-plugin-mlkit-suite)
2
+
3
+ <img src="docs/mlkit-logo.svg" alt="ML Kit logo" width="64" align="right">
4
+
5
+ # cordova-plugin-mlkit-suite
6
+
7
+ Extensible [Google ML Kit](https://developers.google.com/ml-kit) integration for Cordova on Android and iOS. It provides guided face capture, live and still-image barcode scanning, image labeling, selfie and subject segmentation, Latin text recognition, and the native Android document scanner.
8
+
9
+ > [!WARNING]
10
+ > This plugin is in active development. Its API, defaults, quality thresholds, and native behavior may change before a stable release. Validate every required workflow on representative physical devices before using it in production.
11
+
12
+ ## Table of contents
13
+
14
+ - [Overview](#overview)
15
+ - [Screenshots](#screenshots)
16
+ - [Compatibility](#compatibility)
17
+ - [Quick start](#quick-start)
18
+ - [Android model delivery](#android-model-delivery)
19
+ - [Localization](#localization)
20
+ - [API](#api)
21
+ - [Cancellation and errors](#cancellation-and-errors)
22
+ - [Privacy and limitations](#privacy-and-limitations)
23
+ - [Tests](#tests)
24
+
25
+ ## Overview
26
+
27
+ - **Guided face capture** on Android and iOS, with a front-camera overlay, configurable quality checks, automatic capture, and a local JPEG result.
28
+ - **Barcode scanning** from the live camera or an existing image on Android and iOS, supporting all available barcode formats, configurable format filters, scan-region enforcement, consecutive-frame confirmation, animated success feedback, and an optional confirmation beep.
29
+ - **Text recognition v2** for extracting Latin-script text from local images on Android and iOS.
30
+ - **Document scanning** on Android, with page limits, scanner modes, gallery import, JPEG pages, and optional PDF output.
31
+ - **Image labeling** for classifying local images with ML Kit's general-purpose default model on Android and iOS.
32
+ - **Selfie segmentation** for separating people from the background and producing a transparent PNG on Android and iOS.
33
+ - **Subject segmentation** for separating foreground people, pets, and objects from the background on Android.
34
+
35
+ | Module | Android | iOS |
36
+ | --- | --- | --- |
37
+ | [Barcode scanning](#barcode-scanning) | ✅ Live camera and still images | ✅ Live camera and still images |
38
+ | [Document scanner](#document-scanning) | ✅ Available | ❌ Not available |
39
+ | [Face detection](#face-capture) | ✅ Guided face capture | ✅ Guided face capture |
40
+ | [Image labeling](#image-labeling) | ✅ Default model | ✅ Default model |
41
+ | [Selfie segmentation](#selfie-segmentation) | ✅ Transparent PNG | ✅ Transparent PNG |
42
+ | [Subject segmentation](#subject-segmentation) | ✅ Transparent PNG | ❌ Not available |
43
+ | [Text recognition v2](#text-recognition-v2) | ✅ Latin script | ✅ Latin script |
44
+
45
+ Android model delivery is configurable per module. Native plugin UI and errors support automatic, English, and Spanish localization.
46
+
47
+ ## Screenshots
48
+
49
+ <table>
50
+ <tr>
51
+ <th>Face capture<br><sub>Android shown</sub></th>
52
+ <th>Live barcode<br><sub>Android shown</sub></th>
53
+ <th>Document scanner<br><sub>Android only</sub></th>
54
+ <th>Text recognition<br><sub>iOS shown</sub></th>
55
+ </tr>
56
+ <tr>
57
+ <td><img src="docs/screenshots/face-capture.png" alt="Guided face capture on Android" width="205"></td>
58
+ <td><img src="docs/screenshots/barcode-scanning.png" alt="Live barcode scanning on Android" width="205"></td>
59
+ <td><img src="docs/screenshots/document-scanning.jpg" alt="Native document scanner result on Android" width="205"></td>
60
+ <td><img src="docs/screenshots/ios-text-recognition.jpg" alt="Text recognition from a rotated gallery image on iOS" width="205"></td>
61
+ </tr>
62
+ </table>
63
+
64
+ ## Compatibility
65
+
66
+ The plugin requires Cordova 11 or newer.
67
+
68
+ | Platform | Supported Cordova platform | Minimum OS |
69
+ | --- | --- | --- |
70
+ | Android | `cordova-android` 12.x–15.x | Android 7.0 / API 24 |
71
+ | iOS | `cordova-ios` 8.x | iOS 15.5 |
72
+
73
+ ### Android compatibility notes
74
+
75
+ Document Scanner on Android additionally requires Google Play services and at least 1.7 GB of total RAM.
76
+
77
+ The Android implementation selects a tested CameraX version for each supported `cordova-android` major:
78
+
79
+ | cordova-android | CameraX | Reference toolchain |
80
+ | --- | --- | --- |
81
+ | 12.x | 1.2.3 | compileSdk 33 / AGP 7.4.2 / JDK 11 |
82
+ | 13.x | 1.4.2 | compileSdk 34 / AGP 8.3.0 / JDK 17 |
83
+ | 14.x | 1.5.2 | compileSdk 35 / AGP 8.7.3 / JDK 17 |
84
+ | 15.x | 1.6.0 | compileSdk 36 / AGP 8.10.1 / JDK 17 |
85
+
86
+ Unknown `cordova-android` majors fail at build time instead of silently selecting untested dependencies. On an unsupported Android device, `MlKit.scanDocument()` rejects with `UNSUPPORTED_DEVICE` without affecting the other modules.
87
+
88
+ Model packaging and download behavior are documented separately under [Android model delivery](#android-model-delivery).
89
+
90
+ ## Quick start
91
+
92
+ Install the plugin from the Cordova application root:
93
+
94
+ ```bash
95
+ cordova plugin add cordova-plugin-mlkit-suite
96
+ ```
97
+
98
+ All methods return Promises. For example, open the native barcode scanner and inspect the result:
99
+
100
+ ```javascript
101
+ const result = await MlKit.barcode.scan({
102
+ formats: ["QR_CODE", "PDF_417"]
103
+ });
104
+
105
+ if (result.status === "success") {
106
+ console.log(result.text, result.format);
107
+ }
108
+ ```
109
+
110
+ On Android, Face Detection, Barcode Scanning, Image Labeling, OCR, and Subject Segmentation default to the smaller Google Play services `install-time` strategy. Selfie Segmentation is always bundled by ML Kit. See [Android model delivery](#android-model-delivery) to bundle configurable models or defer supported downloads.
111
+
112
+ ### iOS setup
113
+
114
+ On iOS, configure the deployment target and a camera-purpose string in the host application's `config.xml`:
115
+
116
+ ```xml
117
+ <platform name="ios">
118
+ <preference name="deployment-target" value="15.5" />
119
+ <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
120
+ <string>Use the camera to capture a photo.</string>
121
+ </edit-config>
122
+ </platform>
123
+ ```
124
+
125
+ The plugin requests camera access. Generated images are written to the application's private cache, so no storage or Photo Library permission is required.
126
+
127
+ ## Android model delivery
128
+
129
+ Face Detection, Barcode Scanning, Image Labeling, and Latin Text Recognition can independently use the official ML Kit [bundled or unbundled installation paths](https://developers.google.com/ml-kit/tips/installation-paths). Subject Segmentation is always unbundled through Google Play services but can use `install-time` or `first-use`. Document Scanner is always delivered dynamically by Google Play services. Selfie Segmentation only supports ML Kit's bundled installation path.
130
+
131
+ | Mode | Implementation | Download timing | Best fit |
132
+ | --- | --- | --- | --- |
133
+ | `install-time` (**default**) | Unbundled | Requested after installation from Google Play; completion is best effort. | Small app with proactive delivery for normal Play Store installs. |
134
+ | `first-use` | Unbundled | Downloaded when the app first calls that module, unless prepared earlier. | Small app where unused modules should never download. |
135
+ | `bundled` | Bundled | Included in the APK/AAB; no model download. | Immediate offline availability is more important than package size. |
136
+
137
+ Apply one mode as the global fallback during installation:
138
+
139
+ ```bash
140
+ cordova plugin add cordova-plugin-mlkit-suite \
141
+ --variable ANDROID_MLKIT_MODEL_DELIVERY=bundled
142
+ ```
143
+
144
+ Module-specific variables override the global value; `inherit` uses the global setting:
145
+
146
+ | Module | Installation variable | Valid values |
147
+ | --- | --- | --- |
148
+ | Global fallback | `ANDROID_MLKIT_MODEL_DELIVERY` | `bundled`, `install-time`, `first-use`, `play-services` |
149
+ | Face Detection | `ANDROID_MLKIT_FACE_MODE` | `inherit`, `bundled`, `install-time`, `first-use`, `play-services` |
150
+ | Barcode Scanning | `ANDROID_MLKIT_BARCODE_MODE` | `inherit`, `bundled`, `install-time`, `first-use`, `play-services` |
151
+ | Image Labeling | `ANDROID_MLKIT_IMAGE_LABELING_MODE` | `inherit`, `bundled`, `install-time`, `first-use`, `play-services` |
152
+ | Latin Text Recognition | `ANDROID_MLKIT_OCR_MODE` | `inherit`, `bundled`, `install-time`, `first-use`, `play-services` |
153
+ | Selfie Segmentation | None | `bundled` only |
154
+ | Subject Segmentation | `ANDROID_MLKIT_SUBJECT_SEGMENTATION_MODE` | `inherit`, `install-time`, `first-use`, `play-services` |
155
+ | Document Scanner | None | Google Play services only |
156
+
157
+ The global fallback defaults to `install-time`; module variables default to `inherit`. `play-services` aliases `install-time`. Subject Segmentation resolves inherited `bundled` to `install-time`.
158
+
159
+ These are build-time settings, so remove and re-add the plugin to change them. Do not edit generated Gradle, manifest, `plugins/`, or `platforms/android/` files.
160
+
161
+ When an unbundled module is missing, the plugin shows a native spinner, waits for the download, and then continues the requested operation. Its default text follows the resolved plugin locale; set `moduleLoadingMessage` to custom text, or to an empty string for a spinner without a label:
162
+
163
+ ```javascript
164
+ await MlKit.recognizeText(imagePath, {
165
+ moduleLoadingMessage: "Downloading text recognition…"
166
+ });
167
+ ```
168
+
169
+ Use `prepareModels()` to download selected modules proactively:
170
+
171
+ ```javascript
172
+ await MlKit.prepareModels(["barcode", "image-labeling", "ocr"], {
173
+ moduleLoadingMessage: "Preparing ML Kit models…"
174
+ });
175
+ ```
176
+
177
+ Preparation resolves with `{ "status": "ready", "alreadyAvailable": true }`; `alreadyAvailable` is `false` when the call completed a download. `getCapabilities()` reports configured modes and readiness without starting one.
178
+
179
+ ## Localization
180
+
181
+ Plugin-owned camera instructions, accessibility labels, loading text, and user-facing native errors are available in English and Spanish. Every options object accepts an optional `locale`:
182
+
183
+ ```javascript
184
+ await MlKit.face.capture({ locale: "es-AR" });
185
+ await MlKit.barcode.scan({ locale: "auto" });
186
+ ```
187
+
188
+ `auto` is the default and uses the application/device language resolved natively at runtime. `en`, `es`, and BCP-47 tags such as `en-US` or `es-AR` are accepted; unsupported languages safely fall back to English. Explicit `instructionText` and `moduleLoadingMessage` values always take precedence, including an empty string.
189
+
190
+ Android translations live in `src/android/res/values*/mlkit_suite_strings.xml`; iOS translations live in `src/ios/MlKitSuiteResources.bundle/*.lproj/Localizable.strings`. Add the same keys in a new platform locale directory to extend the plugin. Stable result values and error codes are never translated.
191
+
192
+ The Google Document Scanner UI is owned by Google Play services and follows the locale selected by that component. Its public API has no locale override, so `locale` controls the plugin's loading and error messages around the flow but cannot force the language of Google's scanner screens.
193
+
194
+ ## API
195
+
196
+ | Method | Android | iOS | Purpose |
197
+ | --- | --- | --- | --- |
198
+ | `MlKit.getCapabilities()` | ✅ | ✅ | Describes modules available on the current platform and device. |
199
+ | `MlKit.prepareModels(modules?, options?)` | ✅ | ✅ | Ensures all or selected Face, Barcode, Image Labeling, Latin OCR, and Subject Segmentation modules are ready; bundled modules resolve immediately. |
200
+ | `MlKit.prepareDocumentScanner(options?)` | ✅ | ❌ | Checks and installs the on-demand Google Play services scanner component. |
201
+ | `MlKit.scanDocument(options?)` | ✅ | ❌ | Opens Google's native document capture, crop, filter, and cleanup UI. |
202
+ | `MlKit.labelImage(imagePath, options?)` | ✅ | ✅ | Returns labels from ML Kit's default image-labeling model. |
203
+ | `MlKit.segmentSelfie(imagePath, options?)` | ✅ | ✅ | Creates a transparent PNG containing the people found in a local image. |
204
+ | `MlKit.segmentSubjects(imagePath, options?)` | ✅ | ❌ | Creates a transparent PNG containing foreground subjects from a local image. |
205
+ | `MlKit.recognizeText(imagePath, options?)` | ✅ | ✅ | Returns plain Latin-script text from a local image. |
206
+ | `MlKit.scanBarcodes(imagePath, options?)` | ✅ | ✅ | Returns every matching barcode detected in a local image. |
207
+ | `MlKit.barcode.scan(options?)` | ✅ | ✅ | Opens a high-resolution rear-camera barcode scanner. |
208
+ | `MlKit.face.capture(options?)` | ✅ | ✅ | Opens guided front-camera face capture with automatic capture. |
209
+
210
+ Document Scanner requires at least 1.7 GB of total device RAM.
211
+
212
+ All methods return Promises. The plugin processes content locally and does not interpret, validate, upload, or transform decoded payloads for a particular country or document type.
213
+
214
+ ### Capabilities
215
+
216
+ Use `getCapabilities()` to discover platform and device support:
217
+
218
+ ```javascript
219
+ const capabilities = await MlKit.getCapabilities();
220
+
221
+ if (capabilities.document.scan && capabilities.document.deviceSupported) {
222
+ // The native document flow can be requested on this device.
223
+ }
224
+ ```
225
+
226
+ The result contains `platform`, localization details, and `face`, `barcode`, `document`, `imageLabeling`, `selfieSegmentation`, `subjectSegmentation`, and `text` capability objects. Each module reports its configured `mode`, `ready` state, and `modelStatus` without starting a download. Android can report `mixed` when configurable module modes differ. Selfie Segmentation is bundled on both platforms; Subject Segmentation is an unbundled Android module. On iOS, Subject Segmentation and Document Scanner report `unsupported`.
227
+
228
+ ### Document scanning
229
+
230
+ `MlKit.scanDocument(options?)` opens the [Google ML Kit Document Scanner](https://developers.google.com/ml-kit/vision/doc-scanner) on Android. The native flow handles capture, automatic edge detection, crop adjustment, rotation, cleanup, filters, and optional gallery import.
231
+
232
+ The scanner UI, logic, and models are an on-demand Google Play services component. `scanDocument()` now prepares that component automatically and shows the native loading indicator only when a download is required. Call `prepareDocumentScanner()` earlier only when proactive preparation better suits the application flow:
233
+
234
+ ```javascript
235
+ await MlKit.prepareDocumentScanner({
236
+ moduleLoadingMessage: "Preparing document scanner…"
237
+ });
238
+ ```
239
+
240
+ ```javascript
241
+ const result = await MlKit.scanDocument({
242
+ pageLimit: 4,
243
+ galleryImportAllowed: true,
244
+ resultFormats: ["JPEG", "PDF"],
245
+ scannerMode: "FULL",
246
+ moduleLoadingMessage: "Preparing document scanner…"
247
+ });
248
+
249
+ if (result.status === "success") {
250
+ document.querySelector("img").src = result.pages[0].imageUri;
251
+ console.log(result.pdf && result.pdf.path);
252
+ }
253
+ ```
254
+
255
+ The method performs device checks before requesting the Google scanner. Android versions below API 24 and devices with less than 1.7 GB of total RAM reject with `UNSUPPORTED_DEVICE` instead of opening native scanner code.
256
+
257
+ #### Document options
258
+
259
+ | Option | Type | Default | Description |
260
+ | --- | --- | --- | --- |
261
+ | `pageLimit` | integer `1–100` | `1` | Maximum number of pages in one scan. |
262
+ | `galleryImportAllowed` | `boolean` | `true` | Allows importing document images from the gallery. |
263
+ | `resultFormats` | `string[] \| string \| null` | `["JPEG", "PDF"]` | Requests JPEG pages, a PDF, or both. A comma-separated string is accepted. `null` uses the default; `JPG` aliases `JPEG`. |
264
+ | `scannerMode` | `"BASE" \| "BASE_WITH_FILTER" \| "FULL" \| null` | `"FULL"` | Selects the native editing feature set. `null` uses the default. `BASE` still includes crop, rotation, page removal, and page reordering. |
265
+ | `moduleLoadingMessage` | `string \| null` | localized | Android text shown only while downloading the scanner component. Empty string shows only the spinner. |
266
+ | `locale` | `string` | `"auto"` | Plugin loading/error locale. Google's scanner UI resolves its own locale. |
267
+
268
+ Unknown options, invalid types, empty result formats, and out-of-range values reject with `INVALID_ARGUMENT`.
269
+
270
+ #### Document result
271
+
272
+ Successful results contain `status`, a `pages` array, and an optional `pdf` object. Each page reports `imagePath`, WebView-safe `imageUri`, MIME type, byte size, width, and height. The PDF reports its native `path`, WebView-safe `uri`, MIME type, byte size, and page count.
273
+
274
+ `pages` is empty when JPEG was not requested and `pdf` is `null` when PDF was not requested. Use `imageUri` inside the Cordova WebView and native paths with APIs such as `recognizeText()`, `scanBarcodes()`, `labelImage()`, `segmentSelfie()`, and `segmentSubjects()`.
275
+
276
+ ### Image labeling
277
+
278
+ `MlKit.labelImage(imagePath, options?)` uses [ML Kit Image Labeling](https://developers.google.com/ml-kit/vision/image-labeling) to classify one local image with the general-purpose default model. It resolves to an array of labels ordered by the native SDK; an image with no matching labels resolves to `[]`.
279
+
280
+ ```javascript
281
+ const labels = await MlKit.labelImage(imagePath, {
282
+ confidenceThreshold: 0.6,
283
+ moduleLoadingMessage: "Loading image labeling…"
284
+ });
285
+
286
+ for (const label of labels) {
287
+ console.log(label.text, label.confidence, label.index);
288
+ }
289
+ ```
290
+
291
+ ```json
292
+ [
293
+ { "text": "Food", "confidence": 0.93, "index": 12 }
294
+ ]
295
+ ```
296
+
297
+ `confidenceThreshold` is an optional number from `0` to `1`; ML Kit's native default is used when omitted. Each result contains `text`, `confidence`, and the default model's `index`. Android follows the configured delivery mode; iOS bundles the model.
298
+
299
+ ### Selfie segmentation
300
+
301
+ `MlKit.segmentSelfie(imagePath, options?)` uses [ML Kit Selfie Segmentation](https://developers.google.com/ml-kit/vision/selfie-segmentation) in single-image mode. It separates every person from the background and writes a temporary PNG whose alpha channel contains ML Kit's foreground-confidence mask.
302
+
303
+ ```javascript
304
+ const result = await MlKit.segmentSelfie(imagePath, {
305
+ maxDimension: 2048
306
+ });
307
+
308
+ document.querySelector("img").src = result.imageUri;
309
+ console.log(result.imagePath, result.width, result.height, result.bytes);
310
+ ```
311
+
312
+ The successful result contains `status`, WebView-safe `imageUri`, native `imagePath`, `width`, `height`, `mimeType: "image/png"`, and `bytes`. `maxDimension` accepts an integer from `256` to `4096` and defaults to `2048`; larger inputs are proportionally reduced before processing. The model is bundled on Android and iOS, so this method never triggers a Play services download.
313
+
314
+ ### Subject segmentation
315
+
316
+ `MlKit.segmentSubjects(imagePath, options?)` uses [ML Kit Subject Segmentation](https://developers.google.com/ml-kit/vision/subject-segmentation) on Android to isolate the combined foreground from people, animals, or objects and save it as a transparent PNG.
317
+
318
+ ```javascript
319
+ const result = await MlKit.segmentSubjects(imagePath, {
320
+ maxDimension: 2048,
321
+ moduleLoadingMessage: "Loading subject segmentation…"
322
+ });
323
+
324
+ document.querySelector("img").src = result.imageUri;
325
+ ```
326
+
327
+ The result shape and `maxDimension` rules match `segmentSelfie()`. The API is Android-only and unbundled: the plugin checks the Google Play services module, shows its localized loading spinner only when required, waits for installation, and then performs inference. Use `prepareModels("subject-segmentation")` to prepare it earlier without processing an image.
328
+
329
+ ### Text recognition v2
330
+
331
+ `MlKit.recognizeText(imagePath, options?)` runs [ML Kit Text Recognition v2](https://developers.google.com/ml-kit/vision/text-recognition/v2) for the Latin script against a local image and resolves to one plain string. Android uses the selected delivery mode; iOS always bundles the recognizer. An image containing no recognized text resolves to `""`.
332
+
333
+ ```javascript
334
+ const text = await MlKit.recognizeText(result.pages[0].imagePath, {
335
+ moduleLoadingMessage: "Loading text recognition…"
336
+ });
337
+ console.log(text);
338
+ ```
339
+
340
+ `imagePath` can be an absolute native file path, a `file:` URI, an Android `content:` URI, or an `imageUri` previously returned by this plugin. Remote HTTP images are not fetched.
341
+
342
+ ### Barcode scanning
343
+
344
+ Both barcode APIs use [ML Kit Barcode Scanning](https://developers.google.com/ml-kit/vision/barcode-scanning). Use still-image detection for existing local files or the native camera flow for interactive scanning.
345
+
346
+ #### Barcode detection in an image
347
+
348
+ `MlKit.scanBarcodes(imagePath, options?)` uses [ML Kit Barcode Scanning](https://developers.google.com/ml-kit/vision/barcode-scanning) to analyze one existing local image and resolves to an array. It does not require the camera UI or two-frame confirmation.
349
+
350
+ ```javascript
351
+ const barcodes = await MlKit.scanBarcodes(imagePath, {
352
+ formats: ["PDF_417", "QR_CODE"],
353
+ moduleLoadingMessage: "Loading barcode detector…"
354
+ });
355
+
356
+ for (const barcode of barcodes) {
357
+ console.log(barcode.text, barcode.format);
358
+ }
359
+ ```
360
+
361
+ Omit `formats` to enable every supported format. `moduleLoadingMessage` follows the common native-indicator rules above. Each detected value includes `text`, `format`, numeric `valueType`, `boundingBox`, and `cornerPoints`. An image containing no matching barcode resolves to `[]`.
362
+
363
+ ```json
364
+ { "text": "https://example.com", "format": "QR_CODE", "valueType": 8 }
365
+ ```
366
+
367
+ `boundingBox` can be `null`; `cornerPoints` can be empty. Coordinates use the source image's pixel coordinate system. `valueType` is the platform ML Kit enum value, and `format` is one of the names below or `UNKNOWN` if the native SDK reports an unrecognized value.
368
+
369
+ #### Camera barcode scanning
370
+
371
+ `MlKit.barcode.scan(options?)` combines [ML Kit Barcode Scanning](https://developers.google.com/ml-kit/vision/barcode-scanning) with the plugin's own full-screen rear-camera UI on Android and iOS:
372
+
373
+ ```javascript
374
+ const result = await MlKit.barcode.scan({
375
+ formats: ["PDF_417", "QR_CODE"],
376
+ timeoutMs: 45000
377
+ });
378
+
379
+ if (result.status === "success") {
380
+ console.log(result.text, result.format);
381
+ }
382
+ ```
383
+
384
+ ```json
385
+ { "status": "success", "text": "https://example.com", "format": "QR_CODE" }
386
+ ```
387
+
388
+ Android requests `1920×1080` analysis frames from CameraX; iOS requests the equivalent AVFoundation `hd1920x1080` preset. Each platform falls back to the closest suitable high-resolution stream supported by the camera. The four-color corner guide is the active scan region: codes outside it or crossing its edges are ignored. A result is returned only after two consecutive analyzed frames contain exactly the same non-empty text and format while fully inside the guide. A missing, outside, or different value resets confirmation. On success, the scanner freezes the confirmed camera frame and animates the guide onto the detected code before returning the result.
389
+
390
+ ##### Barcode formats
391
+
392
+ Both barcode methods support `AZTEC`, `CODABAR`, `CODE_39`, `CODE_93`, `CODE_128`, `DATA_MATRIX`, `EAN_8`, `EAN_13`, `ITF`, `PDF_417`, `QR_CODE`, `UPC_A`, and `UPC_E`. `PDF417` aliases `PDF_417`; comma-separated strings are accepted in addition to arrays.
393
+
394
+ ##### Camera barcode options
395
+
396
+ | Option | Type | Default | Description |
397
+ | --- | --- | --- | --- |
398
+ | `formats` | `string[] \| string \| null` | all formats | Formats to detect. Restricting formats generally improves speed. |
399
+ | `showCloseButton` | `boolean` | `true` | Shows the native close button. Android Back still cancels when hidden. |
400
+ | `showTorchButton` | `boolean` | `true` | Shows a torch toggle when the rear camera has flash hardware. |
401
+ | `beepEnabled` | `boolean` | `true` | Plays a short synthesized confirmation beep after a successful scan. Device silent mode is respected. |
402
+ | `instructionText` | `string \| null` | `"Place a barcode inside the frame"` | Text shown above the guide. An empty string hides it. |
403
+ | `guideColor` | `string \| null` | `null` | Optional `#RRGGBB` color for all four guide corners. When omitted, the default blue, yellow, green, and red corners are used. A detected in-guide barcode always changes them to green. |
404
+ | `moduleLoadingMessage` | `string \| null` | localized | Android text shown only while downloading Barcode Scanning. Empty string shows only the spinner. |
405
+ | `locale` | `string` | `"auto"` | Plugin UI/error locale (`en`, `es`, or BCP-47). |
406
+ | `timeoutMs` | integer `0–600000` | `0` | Session timeout in milliseconds. `0` disables it. |
407
+
408
+ ### Face capture
409
+
410
+ `MlKit.face.capture(options?)` combines [ML Kit Face Detection](https://developers.google.com/ml-kit/vision/face-detection) with a full-screen native front-camera guide and resolves after a valid JPEG is captured:
411
+
412
+ ```javascript
413
+ const result = await MlKit.face.capture({
414
+ outputWidth: 600,
415
+ outputHeight: 720,
416
+ debugMode: false,
417
+ timeoutMs: 45000
418
+ });
419
+ ```
420
+
421
+ All checks are enabled by default. Capture starts automatically only after they remain acceptable for a short stability window.
422
+
423
+ #### Face options
424
+
425
+ | Option | Type | Default | Description |
426
+ | --- | --- | --- | --- |
427
+ | `outputWidth` | integer `320–2048` | `600` | Exact JPEG width in pixels. |
428
+ | `outputHeight` | integer `320–2048` | `720` | Exact JPEG height in pixels and crop aspect ratio. |
429
+ | `jpegQuality` | integer `50–100` | `95` | JPEG encoding quality. |
430
+ | `showCloseButton` | `boolean` | `true` | Shows the native close button. |
431
+ | `debugMode` | `boolean` | `false` | Shows face bounds and live quality values without weakening validation. |
432
+ | `instructionText` | `string \| null` | `"Place your face inside the oval"` | Text shown above the guide. An empty string hides it. |
433
+ | `moduleLoadingMessage` | `string \| null` | localized | Android text shown only while downloading Face Detection. Empty string shows only the spinner. |
434
+ | `locale` | `string` | `"auto"` | Plugin UI/error locale (`en`, `es`, or BCP-47). |
435
+ | `checks` | `object \| null` | all enabled | Enables or disables individual capture gates. |
436
+ | `timeoutMs` | integer `0–600000` | `0` | Session timeout in milliseconds. `0` disables it. |
437
+
438
+ #### Optional face checks
439
+
440
+ | Check | Default | Purpose |
441
+ | --- | --- | --- |
442
+ | `singleFace` | `true` | Requires exactly one detected face. |
443
+ | `faceSize` | `true` | Rejects faces that are too small or too close. |
444
+ | `centering` | `true` | Requires the face near the guide center. |
445
+ | `pose` | `true` | Limits head yaw, pitch, and roll. |
446
+ | `eyesOpen` | `true` | Requires both eye-open probabilities to pass the internal threshold. |
447
+ | `neutralExpression` | `true` | Rejects a high smiling probability. |
448
+ | `stability` | `true` | Requires a stable face position before capture. |
449
+ | `sharpness` | `true` | Rejects low-detail frames and final images. |
450
+ | `brightness` | `true` | Rejects images that are too dark or too bright. |
451
+
452
+ #### Face result
453
+
454
+ Successful results include the JPEG's `imagePath`, WebView-safe `imageUri`, dimensions, MIME type, byte size, and capture time. The `quality` object contains brightness and sharpness; `face` contains yaw, pitch, roll, eye-open probabilities, and smiling probability; `appliedChecks` records the checks used for capture.
455
+
456
+ Cache files are temporary. Eye-open and smiling probabilities can be `null` when ML Kit does not provide them.
457
+
458
+ ## Cancellation and errors
459
+
460
+ User cancellation of an interactive native UI resolves rather than rejects:
461
+
462
+ ```javascript
463
+ { "status": "cancelled", "reason": "user" }
464
+ ```
465
+
466
+ Other failures reject with a stable shape:
467
+
468
+ ```json
469
+ {
470
+ "code": "UNSUPPORTED_DEVICE",
471
+ "message": "ML Kit Document Scanner requires Android 7.0 or newer and at least 1.7 GB of total RAM.",
472
+ "recoverable": false
473
+ }
474
+ ```
475
+
476
+ | Code | Meaning |
477
+ | --- | --- |
478
+ | `INVALID_ARGUMENT` | An argument, option, or check is invalid. |
479
+ | `INVALID_IMAGE` | The supplied local image cannot be opened or decoded. |
480
+ | `BUSY` | Another interactive native session is active. |
481
+ | `CAMERA_PERMISSION_DENIED` | Camera permission is unavailable. |
482
+ | `CAMERA_UNAVAILABLE` | The requested camera or pipeline could not be opened. |
483
+ | `CAPTURE_FAILED` | No acceptable final face photo was obtained. |
484
+ | `PROCESSING_FAILED` | ML Kit or output persistence could not complete. |
485
+ | `SCANNER_UNAVAILABLE` | The document scanner could not be downloaded, initialized, or opened. |
486
+ | `MODULE_DOWNLOAD_CANCELLED` | Google Play services cancelled a requested model or scanner-component installation. |
487
+ | `MODULE_DOWNLOAD_FAILED` | Google Play services could not check or install the requested modules. |
488
+ | `UNSUPPORTED_DEVICE` | The current Android version, memory, or Google implementation does not support the document scanner. |
489
+ | `UNSUPPORTED_PLATFORM` | The requested module is not implemented on the current platform. |
490
+ | `TIMEOUT` | The configured interactive-session timeout elapsed. |
491
+ | `UNKNOWN` | The JavaScript bridge received an unstructured or otherwise unknown native error. |
492
+
493
+ ## Privacy and limitations
494
+
495
+ ### Dependencies and licenses
496
+
497
+ The plugin uses Google ML Kit, [AndroidX CameraX](https://developer.android.com/media/camera/camerax), and Apple system frameworks including AVFoundation. Plugin source is licensed under the MIT License; platform dependencies retain their own licenses and terms.
498
+
499
+ ### Privacy
500
+
501
+ The plugin requests camera permission and processes camera frames and selected local images. It does not include analytics, advertising, network upload code, face recognition, or persistent biometric storage. Document Scanner and Subject Segmentation are provided through Google Play services; Selfie Segmentation is statically bundled. The host application controls returned files and is responsible for privacy disclosures, consent, retention, transport security, and regulatory compliance.
502
+
503
+ The included Apple privacy manifest declares no tracking, collected data, or required-reason API use by the plugin itself. Host applications and transitive SDKs must provide their own accurate manifests.
504
+
505
+ ### Known limitations
506
+
507
+ - The Google Document Scanner always allows basic page editing, including crop and rotation; its native UI cannot be configured as an immutable front/back capture flow.
508
+ - Image labeling currently uses ML Kit's general-purpose default model; custom models are not yet supported.
509
+ - Selfie Segmentation is a beta ML Kit API. Hair, motion blur, occlusion, and low foreground/background contrast can produce imperfect edges.
510
+ - Subject Segmentation is a beta, Android-only ML Kit API and requires its Google Play services module before first inference.
511
+ - Text recognition currently includes only the Latin script recognizer.
512
+ - Face detection is not face recognition, identity verification, liveness detection, or presentation-attack detection.
513
+ - Face quality thresholds are heuristics and require calibration across devices, skin tones, lighting, optics, and accessibility needs.
514
+ - The face oval is a visual guide; the returned JPEG is rectangular.
515
+ - Cache URLs are session-local and are not durable storage.
516
+ - Camera and document-scanner behavior must be validated on representative physical devices.
517
+
518
+ ## Tests
519
+
520
+ Run the JavaScript, Java confirmation, iOS source-contract, and localization-resource tests:
521
+
522
+ ```bash
523
+ npm test
524
+ ```
525
+
526
+ Before release, validate installation and a debug build with each supported Cordova Android major. Build iOS with `cordova-ios` 8.x on macOS, then test the native flows on physical devices.
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 304 223">
2
+ <g fill="none" stroke-linecap="round" stroke-width="31">
3
+ <path stroke="#4285F4" d="M16 207 106 17"/>
4
+ <path stroke="#A8C7FA" d="M106 17v190"/>
5
+ <path stroke="#4285F4" d="m106 207 91-190"/>
6
+ <path stroke="#A8C7FA" d="M197 17v190"/>
7
+ <path stroke="#4285F4" d="M197 207h91"/>
8
+ </g>
9
+ <g fill="#174EA6">
10
+ <circle cx="16" cy="207" r="16"/>
11
+ <circle cx="106" cy="17" r="16"/>
12
+ <circle cx="106" cy="207" r="16"/>
13
+ <circle cx="197" cy="17" r="16"/>
14
+ <circle cx="197" cy="207" r="16"/>
15
+ <circle cx="288" cy="207" r="16"/>
16
+ </g>
17
+ </svg>