cunning_document_scanner
A document scanner plugin for flutter. Scan and crop automatically on iOS and Android.
3.0.1
53K downloads/mo
#1440 most downloaded on pub.dev
vicajilau/cunning_document_scanner
What this package is like to depend on
Last release 13 days ago
11 Aug 2026
Release timing varies
gaps range from 9 days to 1.1 years
Nearly every release is documented
notes for 27 of 27 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
27 releases · first in 2022
11 releases in the last 12 months
see the full history below
Release timeline
27 releases · Feb 2022 to Aug 2026Releases
latest 27-
3.0.111 Aug 2026Release notes
Open source →What's Changed
- fix(android): raise minSdk to 24, the lowest level actually reachable by @vicajilau in #164
- fix(android): make cleanCache() cover files the GMS scanner produces by @vicajilau in #165
Full Changelog: v3.0.0...v3.0.1
Release notes
Open source →Changed
- The Android
minSdkis now 24, up from the 21 previously declared. 21 was never a level a host application could reach: Flutter's Gradle plugin fails the build below API 23, andplay-services-mlkit-document-scannerdeclares 23 in its own manifest. 24 is Flutter's own defaultminSdkVersion, so a project that has not overridden it needs no change. Applications pinned to API 23 are the exception — they built and ran before and will now fail the manifest merge, and must either raise theirminSdkto 24 or stay on 3.0.0. The README documented the unreachable 21 and has been corrected everywhere it appeared.
Fixed
cleanCache()removed nothing on most Android devices. The GMS/ML Kit document scanner is the primary Android path, and it writes its page images and PDFs under its own naming scheme rather than this plugin'sDOCUMENT_SCAN_prefix, socleanCache()never matched or removed them even though the plugin had returned those exact paths to Flutter as its own output. Each file is now copied into the plugin's own prefixed storage before its path is returned.
-
3.0.011 Aug 2026Release notes
Open source →What's Changed
- chore(deps): bump cunning_document_scanner from 2.7.0 to 2.8.0 in /example by @dependabot[bot] in #155
- chore(deps): bump actions/setup-java from 5 to 5.6.0 by @dependabot[bot] in #156
- chore(deps): bump actions/setup-java from 5.6.0 to 5.7.0 by @dependabot[bot] in #159
- 3.0.0: fix cleanCache data loss, repair Android gallery import, drop permission_handler by @vicajilau in #160
- Fix result callback leaks that could lock the scanner, and cleanCache's Activity requirement by @vicajilau in #161
- Downsample images in the Android fallback scanner, and stop claiming it detects corners by @vicajilau in #162
- fix(ios): stop the Camera/Gallery action sheet from dropping the scan result by @vicajilau in #163
Full Changelog: v2.8.0...v3.0.0
Release notes
Open source →[!IMPORTANT] This release changes where scanned files are written and how cancellation is reported. Read the breaking changes below before upgrading.
Breaking changes
permission_handleris no longer a dependency. The iOS camera permission is now requested natively throughAVCaptureDevice, which is exactly the APIpermission_handlerwrapped forPermission.camera. If your app importspackage:permission_handlerwithout declaring it in your ownpubspec.yaml— relying on it arriving transitively through this plugin — add it explicitly:
Nothing else changes: permission refusals still throwflutter pub add permission_handlerCunningDocumentScannerExceptionwithcode: 'permission_denied'and the same message. Apps that already declarepermission_handlerare unaffected.- iOS output moved out of the
Documentsdirectory. Scans and generated PDFs are now written to a privateLibrary/Caches/cunning_document_scanner/subdirectory. The returned paths are still absolute and readable, but the files are no longer backed up to iCloud and may be reclaimed by the system. Copy anything you need to keep to your own storage. getPictures()now returnsnullon cancellation on every platform. Android previously returned an empty list, contradicting the documented contract. Empty native results are normalized tonull.- Native errors are reported as
CunningDocumentScannerException.getPictures()andcleanCache()no longer leakPlatformException; the platform error code is preserved inCunningDocumentScannerException.code. androidScannerModeis no longer nullable. It defaults toAndroidScannerMode.full; remove any explicitnull.IosScannerOptionsis no longer aconstconstructor. It now validatesjpgCompressionQualityand throws anArgumentErrorfor values outside 0.0 - 1.0.
Fixed
- Importing images from the gallery could fail on Android. Providers that keep images in the cloud, such as Google Photos, return a URI before the bytes are available locally. The cropper opened that stream on the main thread as soon as it started, freezing the UI for the length of the download and aborting with a decode error when the image was not ready yet. Image reading, decoding and cropping now run on a background thread with a progress indicator, and an image that genuinely cannot be read reports that it may still be downloading.
- Large images could exhaust memory in the Android fallback scanner. Photos were decoded at full resolution, and rotating one by its EXIF orientation allocated a second copy without releasing the first, so a 12 MP capture peaked at roughly 96 MB. Images are now downsampled to a longest edge of 2048 px and the intermediate bitmap is recycled. This path runs on devices without Google Play Services, which are the least able to absorb that. The gallery import was routed through the same decoder so crop coordinates stay in one coordinate space.
- The scanner could be locked out for the rest of the process on iPad. The
cameraAndGalleryaction sheet is a popover there, and dismissing it by tapping outside could leave the pending result callback stranded, after which every later call failed withALREADY_ACTIVE. The same happened when no view controller was available to present from. Dismissal by gesture is now treated as a cancellation, and a missing presenter fails immediately withNO_VIEW_CONTROLLERrather than consuming the call. cleanCache()no longer requires an attachedActivityon Android. It only ever needed aContext, so cleaning at startup — before anyActivityis attached — used to fail withNO_ACTIVITYfor no technical reason.- A
restrictedcamera authorization was ignored on iOS. Devices under parental controls or an MDM policy reportrestricted, which the Dart-side check did not treat as a refusal, so the scanner opened a camera the user could never grant access to. The native check covers it. - The camera permission was requested even for gallery-only flows.
ScannerSource.galleryuses the out-of-process system photo picker, which needs no permission; it no longer prompts for anything. cleanCache()could delete host application data. On iOS it removed every.pdf,.jpgand.pngin the app'sDocumentsdirectory; on Android it matched by file extension incacheDirand the pictures directory. Both now delete only files the plugin itself wrote, identified by theDOCUMENT_SCAN_prefix and the private storage directory.- Android gallery multi-selection was broken. The picker requested multiple selection but only read
Intent.data, so selecting more than one image reported "No image selected". Selections are now read fromclipDataand every image is cropped in sequence. - Android gallery imports ignored
noOfPages, hardcoding a single page. - Concurrent
getPictures()calls no longer orphan the first call'sFuture; the second call fails fast with anALREADY_ACTIVEerror. - Calling the plugin while detached from an
Activityreturns aNO_ACTIVITYerror instead of crashing withUninitializedPropertyAccessException. - iOS image write failures are surfaced as errors instead of returning paths to files that were never created.
- Removed the leftover Huawei
com.huawei.hms.ml.DEPENDENCYmanifest entry, which was still being merged into every host application after HMS support was dropped in 2.6.0.
Added
IosScannerOptions.defaultFilterandIosScannerOptions.showFilterBarexpose the iOS cropper filters (IosDocumentFilter.original,.color,.grayscale,.blackAndWhite) to Dart.- Kotlin unit tests for the method channel argument helpers, run in CI.
tool/check_versions.sh, run in CI, fails the build whenpubspec.yaml, the podspec,android/build.gradle.ktsand the changelog disagree on the version.- Documented how to customize the native UI. An application can override any of the plugin's text, and on Android also its colors and dimensions, by redeclaring the matching resource name —
cunning_*on Android,cunning_document_scanner_*inLocalizable.stringson iOS. This already worked, since the plugin resolves each name against the host application first, but was never written down. iOS colors remain hard-coded and are not overridable.
Changed
- Removed the unconditional debug logging from the Android plugin and the debug
printfrom the Dart layer; both leaked file paths and URIs into release logs. plugin_platform_interfacemoved todev_dependencies; it was only ever used by tests.- Added
topicsandissue_trackertopubspec.yaml. - Stricter analysis (
strict-casts,strict-raw-types,public_member_api_docs) and raised, rather than disabled, the SwiftLint size and complexity rules. - The Android fallback cropper shows a page counter while working through a batch of imported images, matching what iOS already displayed.
- Android is localized. Its strings shipped in English only while iOS carried 29 languages; both platforms now cover the same set. The shared wording is taken from the existing iOS translations so the two say the same thing.
- Added Basque (
eu) and Galician (gl) on both platforms, bringing the total to 31. Catalan was already supported. Valencian is served by the Catalan localization, and Asturian, Aragonese and Aranese are left out because iOS does not offer them as system languages. - Every Android resource is now prefixed
cunning_. A library's resources are merged into the host application's resource table and the application wins any name collision, so the plugin previously exposed 45 unprefixed names — includingblack,image_viewandactivity_image_crop— that an application could silently override, restyling or breaking the scanner.resourcePrefix = "cunning_"makes AGP flag any future lapse, and the convention is documented in the README. These are internal resources, so applications need no changes. - Removed the unused
EdgeDetectorinterface, and corrected documentation that claimed the fallback scanner detects corners automatically. It does not, and never did: the crop quad starts as a fixed inset that the user positions. Automatic detection comes from ML Kit on Android and Vision on iOS. - Documented that
noOfPagesis applied after the fact by the iOS document camera, which exposes no page limit of its own.
-
2.8.025 Jul 2026Release notes
Open source →What's Changed
- chore(deps): bump actions/setup-java from 4 to 5 by @dependabot[bot] in #152
- feat(ios): add document image filters to custom cropper (closes #153) by @vicajilau in #154
Full Changelog: v2.7.0...v2.8.0
Release notes
Open source →iOS
- Added document image filter options (Original, Color, Grayscale, B&W) to the custom document cropper (
CunningDocumentCropperViewController) when importing images from the gallery, achieving feature parity with Android ML Kit (fixes #153).
-
2.7.021 Jul 2026Release notes
Open source →What's Changed
- chore(deps): bump cunning_document_scanner from 2.5.1 to 2.6.0 in /example by @dependabot[bot] in #148
- feat(ios): implement manual cropping for gallery images by @vicajilau in #150
- Add cleanCache method and enforce iOS page limit with SwiftLint CI by @vicajilau in #151
Full Changelog: v2.6.0...v2.7.0
Release notes
Open source →General
- Added
CunningDocumentScanner.cleanCache()to clear temporary scanned images and generated PDF files from local storage. - Enforced
noOfPagespage limit validation in Dart (noOfPages > 0), throwing anArgumentErrorwhen invalid values are supplied. - Documented exception handling for
ArgumentErrorandCunningDocumentScannerExceptionin DartDoc comments andREADME.md.
iOS
- Added manual document cropper for gallery-imported images (
ScannerSource.gallery), resolving the limitation where gallery images could not be manually cropped before export. - Implemented
noOfPageslimit handling in bothPHPickerViewControllerselection limit andVNDocumentCameraViewController. - Implemented native
cleanCachesupport. - Implemented a circular
MagnifierViewprecision zoom lens centered over handles during touch dragging, providing pixel-perfect corner positioning. - Added a cancel confirmation dialog to prevent accidental data loss in multi-page scanning.
- Fixed rotate button behavior to properly map cropping coordinates 90 degrees clockwise without losing user progress.
- Optimized image loading and processing:
- Offloaded heavy image orientation fixes (
fixedOrientation()) and perspective correction filters to background threads. - Wrapped background processing calls in
autoreleasepoolblocks to force immediate memory deallocation and avoid OOM crashes. - Downscaled imported gallery images to a maximum of 2048px on load to prevent concurrent memory spikes.
- Replaced CPU-intensive rotation with instant metadata orientation changes.
- Offloaded heavy image orientation fixes (
- Added translations for the new cropper discard options across all 29 localized languages.
Android
- Implemented native
cleanCachesupport purgingDOCUMENT_SCAN_files fromcacheDirandPICTURESdirectory.
-
2.6.009 Jul 2026Release notes
Open source →What's Changed
- fix(android): make HMS ML Kit dependencies optional to resolve allowBackup conflict by @vicajilau in #145
Full Changelog: v2.5.0...v2.6.0
Release notes
Open source →Android
- Removed HMS (Huawei Mobile Services) support entirely to ensure 16 KB page-size compatibility on Android 15+ (fixes #146).
- Replaced deprecated
getParcelable(key)with type-safeandroidx.core.os.BundleCompat.getParcelablefor Android 13+ compatibility. - Migrated the legacy
androidblock to the modernconfigure<LibraryExtension>block and updated conditional Kotlin plugin application inbuild.gradle.ktsto resolve build/deprecation warnings. - Removed redundant and deprecated
sourceSetsblock, as Kotlin source directories are resolved automatically by Gradle.
-
2.5.002 Jul 2026Release notes
Open source →What's Changed
- feat(android): add HMS ML Kit document edge detection and fix GMS+HMS dual-service loop by @vicajilau in #143
Full Changelog: v2.4.0...v2.5.0
Release notes
Open source →General
- Introduced
ScannerSourceenum to specify the source of document images:camera,gallery, orcameraAndGallery. - Deprecated
isGalleryImportAllowedin favor ofscannerSource. IfscannerSourceis provided, it takes precedence andisGalleryImportAllowedis ignored.
Android
- Added automatic document edge detection for Huawei Mobile Services (HMS) devices using HMS ML Kit Document Skew Correction.
- Fixed a crash/restart loop issue on older GMS+HMS dual-service devices (such as Honor 8X and Huawei P30 Lite) by bypassing GMS and launching the fallback scanner directly on HMS-enabled devices.
- Added direct gallery selection support. When
ScannerSource.galleryis chosen, the system launches the device's image picker and routes the selected image directly to the fallback crop editor (DocumentScannerActivity) for edge adjustment and perspective correction.
iOS
- Integrated direct gallery picker navigation. When
ScannerSource.galleryis chosen, the plugin opens the native photo library (PHPickerViewController) directly, bypassing the alert/choice menu.
-
2.4.030 Jun 2026Release notes
Open source →What's Changed
- Bump cunning_document_scanner from 2.2.0 to 2.3.0 in /example by @dependabot[bot] in #138
- Feature/build in kotlin migration issue by @daniJimen in #139
- Refactor: remove redundant camera and storage permissions from Android by @vicajilau in #140
- feat: add support for PDF export in document scanning across platforms by @vicajilau in #141
- Feature: add native gallery import support on iOS by @vicajilau in #142
New Contributors
- @daniJimen made their first contribution in #139
Full Changelog: v2.3.0...v2.4.0
Release notes
Open source →General
- Added cross-platform support for native PDF export. Call
CunningDocumentScanner.getPictures(asPdf: true)to return a list containing a single path pointing to the generated PDF.
Android
- Removed redundant camera and storage permissions from
AndroidManifest.xml. - Android no longer prompts the user for camera or storage permissions at runtime since ML Kit and the fallback camera intent handle them without requiring permission in the host app.
- Integrated native PDF support in both the Google Play Services ML Kit Document Scanner and the local low-RAM fallback scanner (using built-in
PdfDocument). - Migrated to "Built-in Kotlin" support, removing manual Kotlin Gradle Plugin (KGP) application for future Flutter compatibility.
- Updated Gradle wrapper to
8.14.5. - Updated Android Gradle Plugin (AGP) to
8.13.1. - Updated Kotlin version to
2.2.21.
iOS
- Camera permission request remains active and required for iOS VisionKit.
- Integrated native PDF compilation using
PDFKit(converting VisionKit scan pages into a single PDF document). - Added native support for
isGalleryImportAllowedon iOS. Users can now choose to scan using the camera (VisionKit) or import existing documents from their photo library (PHPickerViewControlleron iOS 14+ supporting multi-selection, andUIImagePickerControlleron iOS 13). Imported images undergo the same native PDF/image conversion pipeline. - Added native localization support supporting 29 major languages for the iOS source selection Action Sheet and VisionKit interface. Included explicit color themes using KVC to guarantee text visibility across custom dark/light themes.
-
2.3.022 Jun 2026Release notes
Open source →Android
- Upgraded Gradle wrapper to version
8.14.5. - Modernized Kotlin configuration to use the new
compilerOptionsDSL instead of legacykotlinOptions. - Cleaned up legacy build script configurations, removing deprecated dependencies (
kotlin-stdlib-jdk7) and applying standard Kotlin DSL configurations.
- Upgraded Gradle wrapper to version
-
2.2.022 Jun 2026Release notes
Open source →Android
- Added support for configuring the ML Kit document scanner mode.
- Added
AndroidScannerModeenum (full,base,baseWithFilter) to choose between different scanning pipelines.
-
2.1.022 Jun 2026Release notes
Open source →What's Changed
- feat: Major update to version 2.0.0 with improved exception handling … by @vicajilau in #120
- Bump cupertino_icons from 1.0.8 to 1.0.9 in /example by @dependabot[bot] in #129
- Bump path_provider from 2.1.5 to 2.1.6 in /example by @dependabot[bot] in #133
- Migrate iOS plugin to Swift Package Manager by @olekeke999 in #134
New Contributors
- @olekeke999 made their first contribution in #134
Full Changelog: v1.4.0...v2.1.0
Release notes
Open source →General
- Bumped Dart SDK constraint to
>=3.5.0 <4.0.0. - Bumped Flutter SDK constraint to
>=3.24.0. - Upgraded
permission_handlerto^12.0.3. - Upgraded
flutter_lintsconstraint to^6.0.0. - Moved
permission_handler_platform_interfacetodev_dependencies. - Modernized Flutter code syntax.
- Added launch configurations for VS Code.
iOS
- Migrated the iOS plugin to Swift Package Manager (SPM) for modern Flutter integration.
- Reorganized the iOS directory structure under
ios/cunning_document_scanner/and addedPackage.swift. - Renamed
SwiftCunningDocumentScannerPlugintoCunningDocumentScannerPlugin.
-
1.4.001 Dec 2025Release notes
Open source →General
- Bumped
permission_handlerto12.0.1. - Updated the example app to use Kotlin
2.2.21, Android Gradle Plugin8.13.1, and Gradle8.13. - Added detailed documentation comments to the
CunningDocumentScannerclass.
Android
- Upgraded
play-services-mlkit-document-scannerto16.0.0. - Updated
compileSdkto34.
- Bumped
-
1.3.131 Jul 2025 -
1.2.320 Jun 2024 -
1.2.220 Apr 2024 -
1.2.106 Mar 2024 -
1.2.028 Feb 2024 -
1.1.521 Feb 2024Release notes
Open source →- Nmed parameters
- crop default is false
- dependencies updated
- min ios version 12 now
-
1.1.407 Nov 2023 -
1.1.303 Nov 2023Release notes
Open source →- Fixed permanently denied permission issue
- Merged crop option for android - Thanks Edwin
-
1.1.208 Nov 2022 -
1.1.108 Nov 2022 -
1.1.001 Oct 2022Release notes
Open source →- Exchanged android documentscanner with https://github.com/WebsiteBeaver/android-document-scanner
-
1.0.419 Aug 2022 -
1.0.318 Aug 2022Release notes
Open source →- Updated permission handler constraint to ^10
- Android fixed nullsafe access issues
-
1.0.208 May 2022 -
1.0.105 May 2022 -
1.0.001 Feb 2022Release notes
Open source →- Android and iOs Documentscanner based on Visionkit and AndroidDocument https://github.com/mayuce/AndroidDocumentScanner