NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #1428 most downloaded on pub.dev
A document scanner plugin for flutter. Scan and crop automatically on iOS and Android.
Last release 25 days ago
13 Sep 2026
Ships unpredictably
gaps range from 9 days to 1.1 years
Nearly every release is documented
notes for 29 of 29 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
29 releases · first in 2022
chore(deps): bump actions/setup-java from 6.0.0 to 6.0.1 by @dependabot [bot] in #172
Full Changelog: v3.0.2...v3.0.3
getExternalFilesDir(DIRECTORY_PICTURES), where every Android scan is written, is included in Android Auto Backup by default, so a host application without its own backup rules had its users' scanned documents uploaded to their Google Drive backup with nothing in the plugin or its documentation saying so. Reported in #171. The plugin now declares android:dataExtractionRules and android:fullBackupContent in its own manifest to exclude that directory, which applies to a host application automatically through the manifest merger. An application that already declares its own backup rules will see the manifest merger fail; the README explains the tools:replace needed to resolve it.One column per quarter.
chore(deps): bump actions/setup-java from 5.7.0 to 6.0.0 by @dependabot [bot] in #167
Full Changelog: v3.0.1...v3.0.2
DOCUMENT_SCAN_-prefixed storage and returned that path, but never removed the file ML Kit had written. That original is unreachable: its URI never crosses into Dart, and cleanCache() matches only the plugin's own prefix, so no application could delete it and two copies of every scanned document sat in the cache until the system chose to reclaim it. Reported in #166. The scanner output is now moved rather than copied: a local file is renamed, which also removes the window in which both copies exist, and anything that cannot be renamed is streamed out and its source deleted. Deletion is best-effort, so a source the plugin is not allowed to remove no longer fails an otherwise successful scan.fix(android): raise minSdk to 24, the lowest level actually reachable by @vicajilau in #164
Full Changelog: v3.0.0...v3.0.1
minSdk is 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, and play-services-mlkit-document-scanner declares 23 in its own manifest. 24 is Flutter's own default minSdkVersion, 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 their minSdk to 24 or stay on 3.0.0. The README documented the unreachable 21 and has been corrected everywhere it appeared.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's DOCUMENT_SCAN_ prefix, so cleanCache() 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.chore(deps): bump cunning_document_scanner from 2.7.0 to 2.8.0 in /example by @dependabot [bot] in #155
Full Changelog: v2.8.0...v3.0.0
[!IMPORTANT] This release changes where scanned files are written and how cancellation is reported. Read the breaking changes below before upgrading.
permission_handler is no longer a dependency. The iOS camera permission is now requested natively through AVCaptureDevice, which is exactly the API permission_handler wrapped for Permission.camera. If your app imports package:permission_handler without declaring it in your own pubspec.yaml — relying on it arriving transitively through this plugin — add it explicitly:flutter pub add permission_handler
Nothing else changes: permission refusals still throw CunningDocumentScannerException with code: 'permission_denied' and the same message. Apps that already declare permission_handler are unaffected.Documents directory. Scans and generated PDFs are now written to a private Library/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 returns null on cancellation on every platform. Android previously returned an empty list, contradicting the documented contract. Empty native results are normalized to null.CunningDocumentScannerException. getPictures() and cleanCache() no longer leak PlatformException; the platform error code is preserved in CunningDocumentScannerException.code.androidScannerMode is no longer nullable. It defaults to AndroidScannerMode.full; remove any explicit null.IosScannerOptions is no longer a const constructor. It now validates jpgCompressionQuality and throws an ArgumentError for values outside 0.0 - 1.0.cameraAndGallery action sheet is a popover there, and dismissing it by tapping outside could leave the pending result callback stranded, after which every later call failed with ALREADY_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 with NO_VIEW_CONTROLLER rather than consuming the call.cleanCache() no longer requires an attached Activity on Android. It only ever needed a Context, so cleaning at startup — before any Activity is attached — used to fail with NO_ACTIVITY for no technical reason.restricted camera authorization was ignored on iOS. Devices under parental controls or an MDM policy report restricted, 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.ScannerSource.gallery uses 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, .jpg and .png in the app's Documents directory; on Android it matched by file extension in cacheDir and the pictures directory. Both now delete only files the plugin itself wrote, identified by the DOCUMENT_SCAN_ prefix and the private storage directory.Intent.data, so selecting more than one image reported "No image selected". Selections are now read from clipData and every image is cropped in sequence.noOfPages, hardcoding a single page.getPictures() calls no longer orphan the first call's Future; the second call fails fast with an ALREADY_ACTIVE error.Activity returns a NO_ACTIVITY error instead of crashing with UninitializedPropertyAccessException.com.huawei.hms.ml.DEPENDENCY manifest entry, which was still being merged into every host application after HMS support was dropped in 2.6.0.IosScannerOptions.defaultFilter and IosScannerOptions.showFilterBar expose the iOS cropper filters (IosDocumentFilter.original, .color, .grayscale, .blackAndWhite) to Dart.tool/check_versions.sh, run in CI, fails the build when pubspec.yaml, the podspec, android/build.gradle.kts and the changelog disagree on the version.cunning_* on Android, cunning_document_scanner_* in Localizable.strings on 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.print from the Dart layer; both leaked file paths and URIs into release logs.plugin_platform_interface moved to dev_dependencies; it was only ever used by tests.topics and issue_tracker to pubspec.yaml.strict-casts, strict-raw-types, public_member_api_docs) and raised, rather than disabled, the SwiftLint size and complexity rules.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.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 — including black, image_view and activity_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.EdgeDetector interface, 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.noOfPages is applied after the fact by the iOS document camera, which exposes no page limit of its own.chore(deps): bump actions/setup-java from 4 to 5 by @dependabot [bot] in #152
Full Changelog: v2.7.0...v2.8.0
CunningDocumentCropperViewController) when importing images from the gallery, achieving feature parity with Android ML Kit (fixes #153).chore(deps): bump cunning_document_scanner from 2.5.1 to 2.6.0 in /example by @dependabot [bot] in #148
Full Changelog: v2.6.0...v2.7.0
CunningDocumentScanner.cleanCache() to clear temporary scanned images and generated PDF files from local storage.noOfPages page limit validation in Dart (noOfPages > 0), throwing an ArgumentError when invalid values are supplied.ArgumentError and CunningDocumentScannerException in DartDoc comments and README.md.ScannerSource.gallery), resolving the limitation where gallery images could not be manually cropped before export.noOfPages limit handling in both PHPickerViewController selection limit and VNDocumentCameraViewController.cleanCache support.MagnifierView precision zoom lens centered over handles during touch dragging, providing pixel-perfect corner positioning.fixedOrientation()) and perspective correction filters to background threads.autoreleasepool blocks to force immediate memory deallocation and avoid OOM crashes.cleanCache support purging DOCUMENT_SCAN_ files from cacheDir and PICTURES directory.fix(android): make HMS ML Kit dependencies optional to resolve allowBackup conflict by @vicajilau in #145
Full Changelog: v2.5.0...v2.6.0
getParcelable(key) with type-safe androidx.core.os.BundleCompat.getParcelable for Android 13+ compatibility.android block to the modern configure<LibraryExtension> block and updated conditional Kotlin plugin application in build.gradle.kts to resolve build/deprecation warnings.sourceSets block, as Kotlin source directories are resolved automatically by Gradle.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
ScannerSource enum to specify the source of document images: camera, gallery, or cameraAndGallery.isGalleryImportAllowed in favor of scannerSource. If scannerSource is provided, it takes precedence and isGalleryImportAllowed is ignored.ScannerSource.gallery is 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.ScannerSource.gallery is chosen, the plugin opens the native photo library (PHPickerViewController) directly, bypassing the alert/choice menu.Bump cunning_document_scanner from 2.2.0 to 2.3.0 in /example by @dependabot [bot] in #138
Full Changelog: v2.3.0...v2.4.0
CunningDocumentScanner.getPictures(asPdf: true) to return a list containing a single path pointing to the generated PDF.AndroidManifest.xml.PdfDocument).8.14.5.8.13.1.2.2.21.PDFKit (converting VisionKit scan pages into a single PDF document).isGalleryImportAllowed on iOS. Users can now choose to scan using the camera (VisionKit) or import existing documents from their photo library (PHPickerViewController on iOS 14+ supporting multi-selection, and UIImagePickerController on iOS 13). Imported images undergo the same native PDF/image conversion pipeline.Full Changelog : v2.2.0...v2.3.0
Full Changelog: v2.2.0...v2.3.0
8.14.5.compilerOptions DSL instead of legacy kotlinOptions.kotlin-stdlib-jdk7) and applying standard Kotlin DSL configurations.Feature/android scanner mode by @MazterGD in #130
AndroidScannerMode enum (full, base, baseWithFilter) to choose between different scanning pipelines.feat: Major update to version 2.0.0 with improved exception handling … by @vicajilau in #120
Full Changelog: v1.4.0...v2.1.0
>=3.5.0 <4.0.0.>=3.24.0.permission_handler to ^12.0.3.flutter_lints constraint to ^6.0.0.permission_handler_platform_interface to dev_dependencies.ios/cunning_document_scanner/ and added Package.swift.SwiftCunningDocumentScannerPlugin to CunningDocumentScannerPlugin.Bumped permission_handler to 12.0.1.
permission_handler to 12.0.1.2.2.21, Android Gradle Plugin 8.13.1, and Gradle 8.13.CunningDocumentScanner class.play-services-mlkit-document-scanner to 16.0.0.compileSdk to 34.* Upgraded dependencies.
Fix iOS crash where Documentscanner is not available
Fix bitmap exception crash on Android (thanks to rosenberg_ptr)
Add fallback for Android devices < 1.7GB RAM
* Use ML kit on Android * dropped nocrop support * image quality dropped
* Nmed parameters * crop default is false * dependencies updated * min ios version 12 now
Fixed iOS permission issue in example
Fixed permanently denied permission issue
* iOS return unique filenames
Updated android documentscanner library
Exchanged android documentscanner with https://github.com/WebsiteBeaver/android-document-scanner
Fixed conflicting requestcodes issue
Updated permission handler constraint to ^10
Cleanup code - added images to README.md
Fixed Playstore issue exported activity. Added documentation.
Android and iOs Documentscanner based on Visionkit and AndroidDocument https://github.com/mayuce/AndroidDocumentScanner
Your coding agent can read these notes before it upgrades. Set up the MCP server →