Flutter文档扫描插件doc_scanner_kit的使用
Flutter文档扫描插件doc_scanner_kit的使用
概述
doc_scanner_kit
是一个用于在 Android 和 iOS 上进行文档扫描的 Flutter 插件。它基于 Google 的 ML Kit 文档扫描 API 和 VisionKit,支持实时边缘检测、自动裁剪以及高质量图像输出,非常适合构建移动扫描解决方案。
示例
您可以查看 example
文件夹中的示例 Flutter 应用来了解如何使用 doc_scanner_kit
。
截图
以下是使用 doc_scanner_kit
的界面截图:
图片 1 | 图片 2 | 图片 3 |
---|---|---|
![]() |
![]() |
![]() |
图片 4 | 图片 5 | 图片 6 |
---|---|---|
![]() |
![]() |
![]() |
特性
- 高质量用户界面:提供一致的用户界面,用于数字化物理文档。
- 精确的文档检测:通过精准的角落和边缘检测,确保最佳扫描效果。
- 灵活功能:允许用户裁剪扫描文档、应用滤镜、移除手指、去除污渍等。
- 设备端处理:保护隐私。
- 支持导出为 PDF 或 JPEG 格式:可以将数字化文件发送回您的应用程序。
- 可设置扫描页数限制:支持自定义扫描页数。
- 支持多种格式:包括 PNG、JPEG 和 PDF。
安装
要使用此插件,请将其作为依赖项添加到您的 pubspec.yaml
文件中:
dependencies:
flutter:
sdk: flutter
doc_scanner_kit: ^0.0.7
使用方法
以下是如何在 Android 和 iOS 上进行文档扫描的函数示例:
Future<void> scanDocument() async {
// 默认情况下,Android 返回 PDF,iOS 返回 PNG
dynamic scannedDocuments;
try {
scannedDocuments = await DocumentScanner().getScanDocuments(page: 3) ??
'Unknown platform documents';
} on PlatformException {
scannedDocuments = 'Failed to get scanned documents.';
}
print(scannedDocuments.toString());
}
注意:如果您只想获取 PDF 扫描文档,请调用 getScannedDocumentAsPdf()
。如果想获取图像格式的扫描文档,请使用 getScannedDocumentAsImages()
。
项目配置
Android
-
最低版本配置
确保您的应用满足在 Android 设备上运行的最低版本要求。
在android/app/build.gradle
文件中,检查minSdkVersion
是否至少为 21:android { ... defaultConfig { ... minSdkVersion 21 ... } ... }
iOS
-
最低版本配置
确保您的应用满足在 iOS 设备上运行的最低版本要求。
在ios/Podfile
文件中,确保 iOS 平台版本至少为 12.0 或更高:platform :ios, '12.0'
-
权限配置
-
添加一个字符串属性到您的应用的
Info.plist
文件中,键名为NSCameraUsageDescription
,值为相机访问的原因描述。这是 Apple 的要求,也是 App Store 审核的关键部分:<key>NSCameraUsageDescription</key> <string>Camera Permission Description</string>
-
doc_scanner_kit
使用permission_handler
依赖来控制权限。为了启用相机权限,在您的Podfile
文件中添加以下内容:post_install do |installer| installer.pods_project.targets.each do |target| ... # 这里是一些由 flutter 自动生成的配置 # 开始 permission_handler 配置 target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', ## dart: PermissionGroup.camera 'PERMISSION_CAMERA=1', ] end # 结束 permission_handler 配置 end end
-
问题与反馈
如遇到任何问题或有改进建议,请在 GitHub 仓库 中提交问题。非常感谢!
许可证
该插件采用 MIT 许可证,版权持有人为 Pallavii Sharma。
MIT License
Copyright (c) 2025 Pallavii Sharrma
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
示例代码
以下是一个完整的示例代码,展示如何使用 doc_scanner_kit
进行文档扫描并分享结果:
import 'dart:io';
import 'package:doc_scanner_kit/document_scanner.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:share_plus/share_plus.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(
MaterialApp(
home: MyApp(),
),
);
}
class MyApp extends StatefulWidget {
MyApp({Key? key}) : super(key: key);
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
dynamic _scannedDocuments;
Future<void> scanDocument() async {
dynamic scannedDocuments;
try {
scannedDocuments = await DocumentScanner().getScanDocuments(page: 4) ??
'Unknown platform documents';
} on PlatformException {
scannedDocuments = 'Failed to get scanned documents.';
}
print(scannedDocuments.toString());
if (!mounted) return;
setState(() {
_scannedDocuments = scannedDocuments;
});
// 提取并分享 PDF 文件
if (scannedDocuments is Map) {
List<String> pdfUris = [];
scannedDocuments.forEach((key, value) {
print('Key: $key, Value: $value, Type: ${value.runtimeType}');
if (key == 'pdfUri') {
pdfUris.add(value);
}
});
if (pdfUris.isNotEmpty) {
await sharePDF(pdfUris);
} else {
print('Error: No PDF URIs found in scanned documents.');
}
}
}
Future<void> sharePDF(List<String> pdfUris) async {
try {
if (pdfUris.isNotEmpty) {
String pdfUri = pdfUris.first;
String filePath = pdfUri.replaceFirst('file://', '');
File pdfFile = File(filePath);
List<int> pdfBytes = await pdfFile.readAsBytes();
Directory tempDir = await getTemporaryDirectory();
String tempPath = '${tempDir.path}/scanned_document.pdf';
File tempPdfFile = File(tempPath);
await tempPdfFile.writeAsBytes(pdfBytes);
await Share.shareXFiles([XFile(tempPdfFile.path)], text: 'Here is the scanned document!');
} else {
print('Error: No PDF URIs provided for sharing.');
}
} catch (e) {
print('Error sharing PDF: $e');
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Document Scanner Kit'),
),
body: Stack(
children: [
Center(
child: _scannedDocuments != null
? Text(_scannedDocuments.toString())
: const Text("No Documents Scanned"),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(bottom: 20),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
backgroundColor: Colors.deepOrange,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(50),
),
),
),
onPressed: scanDocument,
child: const Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(left: 4),
child: Icon(
Icons.scanner,
color: Colors.white,
),
),
SizedBox(width: 5),
Flexible(
child: FittedBox(
child: Text(
'Scan',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 14,
),
),
),
),
],
),
),
),
),
],
),
);
}
}
更多关于Flutter文档扫描插件doc_scanner_kit的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter文档扫描插件doc_scanner_kit的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
doc_scanner_kit
是一个用于在 Flutter 应用中实现文档扫描功能的插件。它允许用户通过设备的摄像头扫描文档,并生成高质量的图像。以下是使用 doc_scanner_kit
的基本步骤:
1. 添加依赖
首先,在 pubspec.yaml
文件中添加 doc_scanner_kit
依赖:
dependencies:
flutter:
sdk: flutter
doc_scanner_kit: ^1.0.0 # 请检查最新版本
然后运行 flutter pub get
以安装依赖。
2. 配置 Android 和 iOS 项目
Android
在 android/app/build.gradle
文件中,确保 minSdkVersion
至少为 21:
android {
...
defaultConfig {
...
minSdkVersion 21
...
}
...
}
iOS
在 ios/Podfile
中,确保平台设置为 iOS 11.0 或更高版本:
platform :ios, '11.0'
然后运行 pod install
以更新 iOS 依赖。
3. 使用 doc_scanner_kit
在你的 Flutter 代码中,导入 doc_scanner_kit
并调用扫描功能:
import 'package:flutter/material.dart';
import 'package:doc_scanner_kit/doc_scanner_kit.dart';
class DocumentScannerScreen extends StatefulWidget {
@override
_DocumentScannerScreenState createState() => _DocumentScannerScreenState();
}
class _DocumentScannerScreenState extends State<DocumentScannerScreen> {
String? scannedImagePath;
Future<void> startDocumentScanner() async {
try {
final String? imagePath = await DocScannerKit.startScan();
if (imagePath != null) {
setState(() {
scannedImagePath = imagePath;
});
}
} catch (e) {
print("Error: $e");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Document Scanner'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (scannedImagePath != null)
Image.file(File(scannedImagePath!))
else
Text('No document scanned yet.'),
SizedBox(height: 20),
ElevatedButton(
onPressed: startDocumentScanner,
child: Text('Scan Document'),
),
],
),
),
);
}
}
4. 运行应用
现在,你可以运行你的 Flutter 应用,并使用 doc_scanner_kit
进行文档扫描。点击“Scan Document”按钮将启动扫描界面,扫描完成后,扫描的图像将显示在应用中。
5. 处理扫描结果
扫描完成后,DocScannerKit.startScan()
将返回扫描图像的路径。你可以使用这个路径来显示图像或进行进一步的处理。
6. 自定义扫描界面(可选)
doc_scanner_kit
可能提供了一些自定义选项,比如设置扫描界面的主题、语言等。你可以查看插件的文档以了解更多高级功能。
7. 处理权限
确保你的应用已经请求了相机和存储权限,否则扫描功能可能无法正常工作。你可以使用 permission_handler
插件来处理权限请求。
dependencies:
permission_handler: ^10.0.0 # 请检查最新版本
然后请求权限:
import 'package:permission_handler/permission_handler.dart';
Future<void> requestPermissions() async {
var status = await Permission.camera.status;
if (!status.isGranted) {
await Permission.camera.request();
}
status = await Permission.storage.status;
if (!status.isGranted) {
await Permission.storage.request();
}
}