Flutter文档扫描与识别插件credio_reader的使用
Flutter 文档扫描与识别插件 credio_reader 的使用
简介
Credio Reader
插件是一个专门为 Flutter 设计的包,旨在简化将 Credio 支付终端集成到你的移动应用中的过程。它提供了一个可自定义的按钮来管理与 Credio 读卡器的连接并发起支付交易。
安装
在你的 pubspec.yaml
文件中添加以下依赖项:
dependencies:
credio_reader: ^latest_version
然后,在终端中运行以下命令以安装该包:
flutter pub get
配置
Credio Reader
插件使用 CredioConfig
类进行配置。以下是设置方法的示例:
final GetIt locator = GetIt.instance;
void setupLocator() {
locator.registerLazySingleton(() => NavigationService());
}
final apiKey = 'your_api_key'; // 示例:tracker_cred_8f3X9pLm2qRt7vYw4hNk6bJc
final webHookUrl = 'your_webHook_url';
final CredioConfig config = CredioConfig(
apiKey,
'2070FLRX',
webHookUrl,
locator<NavigationService>().navigatorKey,
initializerButton: Text("Custom Initializer Button"),
buttonConfiguration: ButtonConfiguration(
buttonStyle: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
),
),
),
amount: 100, // 预定义金额
amountInputDecoration: InputDecoration(
labelText: 'Enter withdrawal amount',
prefixIcon: Icon(Icons.attach_money),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
accountTypes: [
SelectionData(selection: 0, title: "个人账户"),
SelectionData(selection: 1, title: "企业账户"),
],
customSelectionSheet: (BuildContext context, List<SelectionData> data, Function(SelectionData) onSelect) {
// 自定义账户类型选择实现
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('选择账户类型'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: data
.map(
(item) => ElevatedButton(
child: Text(item.title!),
onPressed: () {
onSelect(item);
Navigator.of(context).pop();
},
),
)
.toList(),
),
);
},
);
},
customPinEntry: (BuildContext context, Function(String) onCompleted) {
// 自定义 PIN 输入实现
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 48.0),
child: TextFormField(
autofocus: true,
obscureText: true,
keyboardType: TextInputType.number,
maxLength: 4,
decoration: InputDecoration(
labelText: '输入 PIN',
border: OutlineInputBorder(),
),
onChanged: (value) {
if (value.length == 4) {
onCompleted(value);
}
},
),
);
},
customLoader: <T>({
required BuildContext context,
required Future<T> future,
required String prompt,
required String errorMessage,
String? successMessage,
VoidCallback? action,
required Function(String) onError,
}) async {
try {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
CircularProgressIndicator(),
SizedBox(height: 20),
Text(prompt),
],
),
);
},
);
final result = await future;
Navigator.of(context).pop();
if (successMessage != null) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('成功'),
content: Text(successMessage),
actions: <Widget>[
TextButton(
child: Text('确定'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
return result;
} catch (error) {
Navigator.of(context).pop();
// 调用 onError 处理错误
onError(errorMessage);
return null;
}
},
);
注意:对于这些新定制选项的详细使用,请参阅包存储库中的示例应用。
权限
在应用中使用 ReaderButton
之前,确保已经请求并获得必要的权限。Credio Reader
插件需要以下权限:
- 蓝牙
- 互联网
- 位置(仅限 Android)
平台特定设置
为了确保应用可以请求这些权限,请在应用的配置文件中添加以下内容:
Android
在 AndroidManifest.xml
中添加以下内容:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 对于 Android 12 及以上版本 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
iOS
在 Info.plist
中添加以下内容:
<key>NSBluetoothPeripheralUsageDescription</key>
<string>我们需要访问蓝牙以连接到 Credio 读卡器,并为您提供 POS 支付功能。</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Credio 希望访问您的位置,以向您提供相关且个性化的服务。您的位置信息仅在您使用应用时才会被使用。</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Credio 需要蓝牙访问权限,以便安全地连接到 Credio 读卡器,并促进支付处理和设备配置的无缝通信。</string>
你应该在初始化 ReaderButton
之前请求这些权限。以下是一个简单的示例:
import 'package:permission_handler/permission_handler.dart';
Future<bool> requestCredioPermissions() async {
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetooth,
Permission.location,
].request();
return statuses[Permission.bluetooth]!.isGranted &&
statuses[Permission.location]!.isGranted;
}
// 在应用中使用
void initializeCredioReader() async {
if (await requestCredioPermissions()) {
// 权限已授予,现在可以使用 ReaderButton
// 例如:
// ReaderButton(_config)
} else {
// 处理权限未授予的情况
// 你可能想要显示一个对话框解释为什么需要这些权限
}
}
使用
按照上述配置部分创建 CredioConfig
实例后,你可以通过在应用的 UI 中添加 ReaderButton
小部件来使用 Credio Reader
:
ReaderButton(config)
交易处理
当用户按下自定义的 Credio
按钮时,交易过程将被启动。插件会管理与 Credio
读卡器的交互并在后台处理交易。完成后,回调函数会被触发,提供交易的结果。
- 成功的交易:回调函数将返回一个包含交易详情的成功消息,如金额、时间戳和响应码。如果响应码为“00”,则认为交易成功。
- 失败的交易:如果发生错误或失败,回调函数将包含错误详情,允许应用通知用户并采取适当的措施。
错误处理
错误处理对于提供无缝的用户体验至关重要。插件提供了内置的错误消息,但开发者也可以在回调函数中自定义错误处理方式。常见的错误包括:
- 无效的
terminalId
或apiKey
- 与
Credio
读卡器的连接问题 - 用户取消交易
部署
确保在部署应用之前正确设置了所有必需的配置(如 terminalId
和 apiKey
)。credio_reader
插件应在测试环境中进行彻底测试,以确保其与 Credio
读卡器正确交互并按预期处理交易。
示例代码
import 'package:credio_reader/components/app_selection_sheet.dart';
import 'package:credio_reader/configuration/button_configuration.dart';
import 'package:credio_reader/configuration/configuration.dart';
import 'package:credio_reader/credio_reader.dart';
import 'package:credio_reader_example/nav.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
final GetIt locator = GetIt.instance;
void setupLocator() {
locator.registerLazySingleton(() => NavigationService());
}
void main() async {
setupLocator();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late final CredioConfig _config;
final apiKey = 'your_api_key'; // 示例:tracker_cred_8f3X9pLm2qRt7vYw4hNk6bJc
final webHookUrl = 'your_webHook_url';
[@override](/user/override)
void initState() {
super.initState();
_config = CredioConfig(
apiKey,
'2070FLRX',
webHookUrl,
locator<NavigationService>().navigatorKey,
initializerButton: Text("I can use a single Text"),
buttonConfiguration: ButtonConfiguration(
buttonStyle: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0),
),
),
),
),
amount: 100,
amountInputDecoration: InputDecoration(
labelText: 'Enter withdrawal amount',
prefixIcon: const Icon(Icons.attach_money),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
accountTypes: [
SelectionData(selection: 0, title: "个人账户"),
SelectionData(selection: 1, title: "企业账户"),
],
customSelectionSheet: (BuildContext context, List<SelectionData> data, Function(SelectionData) onSelect) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('选择账户类型'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: data
.map(
(item) => ElevatedButton(
child: Text(item.title!),
onPressed: () {
onSelect(item);
Navigator.of(context).pop();
},
),
)
.toList(),
),
);
},
);
},
customPinEntry: (BuildContext context, Function(String) onCompleted) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 48.0),
child: TextFormField(
autofocus: true,
obscureText: true,
keyboardType: TextInputType.number,
maxLength: 4,
decoration: InputDecoration(
labelText: '输入 PIN',
border: OutlineInputBorder(),
),
onChanged: (value) {
if (value.length == 4) {
onCompleted(value);
}
},
),
);
},
customLoader: <T>({
required BuildContext context,
required Future<T> future,
required String prompt,
required String errorMessage,
String? successMessage,
VoidCallback? action,
required Function(String) onError,
}) async {
try {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
CircularProgressIndicator(),
SizedBox(height: 20),
Text(prompt),
],
),
);
},
);
final result = await future;
Navigator.of(context).pop();
if (successMessage != null) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('成功'),
content: Text(successMessage),
actions: <Widget>[
TextButton(
child: Text('确定'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
return result;
} catch (error) {
Navigator.of(context).pop();
// 调用 onError 处理错误
onError(errorMessage);
return null;
}
},
);
if (mounted) {
setState(() {});
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.purple),
navigatorKey: locator<NavigationService>().navigatorKey,
home: Scaffold(
appBar: AppBar(
title: const Text('Credio Reader 示例应用'),
),
body: Center(
child: Builder(
builder: (context) {
return ReaderButton(_config);
},
),
),
),
);
}
}
更多关于Flutter文档扫描与识别插件credio_reader的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter文档扫描与识别插件credio_reader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
credio_reader
是一个用于在 Flutter 应用中实现文档扫描和文本识别的插件。它基于 OCR(光学字符识别)技术,能够从图像中提取文本。以下是如何在 Flutter 项目中使用 credio_reader
的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 credio_reader
插件的依赖:
dependencies:
flutter:
sdk: flutter
credio_reader: ^1.0.0 # 请检查最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入插件
在你的 Dart 文件中导入 credio_reader
插件:
import 'package:credio_reader/credio_reader.dart';
3. 初始化扫描器
在使用插件之前,通常需要初始化扫描器。你可以使用 CredioReader.initialize()
方法来完成初始化:
void initializeScanner() async {
bool isInitialized = await CredioReader.initialize();
if (isInitialized) {
print("Scanner initialized successfully");
} else {
print("Failed to initialize scanner");
}
}
4. 启动文档扫描
你可以使用 CredioReader.scanDocument()
方法来启动文档扫描。该方法会返回扫描后的图像路径:
void scanDocument() async {
String? imagePath = await CredioReader.scanDocument();
if (imagePath != null) {
print("Document scanned successfully: $imagePath");
// 你可以在这里处理扫描后的图像,例如显示在UI中或进行OCR识别
} else {
print("Document scanning failed or was canceled");
}
}
5. 执行OCR识别
如果你需要从扫描的图像中提取文本,可以使用 CredioReader.recognizeText()
方法:
void recognizeText(String imagePath) async {
String? recognizedText = await CredioReader.recognizeText(imagePath);
if (recognizedText != null) {
print("Recognized text: $recognizedText");
// 你可以在这里处理识别出的文本,例如显示在UI中或保存到数据库
} else {
print("Text recognition failed");
}
}
6. 结合使用
你可以将扫描和识别的步骤结合起来,例如在扫描完成后立即进行OCR识别:
void scanAndRecognize() async {
String? imagePath = await CredioReader.scanDocument();
if (imagePath != null) {
print("Document scanned successfully: $imagePath");
String? recognizedText = await CredioReader.recognizeText(imagePath);
if (recognizedText != null) {
print("Recognized text: $recognizedText");
} else {
print("Text recognition failed");
}
} else {
print("Document scanning failed or was canceled");
}
}
7. 处理权限
在使用相机和存储功能时,确保你已经处理了相关的权限请求。你可以在 AndroidManifest.xml
和 Info.plist
中添加必要的权限,并在运行时请求用户授权。
8. 错误处理
在实际应用中,建议添加适当的错误处理机制,以应对可能出现的异常情况。
9. 示例代码
以下是一个完整的示例代码,展示了如何使用 credio_reader
插件进行文档扫描和文本识别:
import 'package:flutter/material.dart';
import 'package:credio_reader/credio_reader.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: ScannerScreen(),
);
}
}
class ScannerScreen extends StatefulWidget {
[@override](/user/override)
_ScannerScreenState createState() => _ScannerScreenState();
}
class _ScannerScreenState extends State<ScannerScreen> {
String? _scannedImagePath;
String? _recognizedText;
void initializeScanner() async {
bool isInitialized = await CredioReader.initialize();
if (isInitialized) {
print("Scanner initialized successfully");
} else {
print("Failed to initialize scanner");
}
}
void scanAndRecognize() async {
String? imagePath = await CredioReader.scanDocument();
if (imagePath != null) {
setState(() {
_scannedImagePath = imagePath;
});
String? recognizedText = await CredioReader.recognizeText(imagePath);
if (recognizedText != null) {
setState(() {
_recognizedText = recognizedText;
});
} else {
print("Text recognition failed");
}
} else {
print("Document scanning failed or was canceled");
}
}
[@override](/user/override)
void initState() {
super.initState();
initializeScanner();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Document Scanner & OCR"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_scannedImagePath != null)
Image.file(
File(_scannedImagePath!),
height: 200,
),
if (_recognizedText != null)
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(_recognizedText!),
),
ElevatedButton(
onPressed: scanAndRecognize,
child: Text("Scan Document"),
),
],
),
),
);
}
}