Flutter屏幕捕获插件capture的使用
Flutter屏幕捕获插件capture的使用
© Everial
这是一份使用Everial屏幕捕获插件Capture的最小化示例项目。该插件提供了官方文档识别功能和数据提取功能。它支持所有捕获功能。
关于功能工作的说明
该插件设计用于在移动设备上进行处理。然而,它必须定期访问某些web服务:
- 应用程序首次使用时
- 使用情况收集
- 模型识别更新
- 配置更新
- 生命证明测试
- 对于性能较弱的手机,访问额外的web服务
连接状态检测是自动且透明的。
安装前的准备
请求标识符
SDK初始化需要由Everial提供的用户名和密码。该用户名与嵌入SDK的应用程序包名(iOS、Android)相关联。例如:com.yourcompany.yourapp
测试应用程序已预配置您的标识符。请参阅文件 “home.html”
版本
iOS
插件必须使用Swift版本5进行编译。最低iOS版本为13。
Android
插件支持从SDK版本24开始的Android。
测试应用程序的安装
解压后,在根目录执行以下命令:
flutter pub get
这将导入依赖项。
iOS
- 在项目目录./example中构建:
flutter build ios --no-codesign
- 在./ios/App中打开 “App.xcworkspace”。
- 指定开发签名和证书。
- 在项目的设置信息选项卡中,添加一个条目:“Privacy - Camera Usage Description” 并为用户相机使用提供文本描述。
- 运行
Android
-
打开目录./android在Android Studio中。
-
在应用的 “build.gradle” 文件中,添加Everial Maven仓库和JitPack:
repositories { ... maven { url 'https://pkgs.dev.azure.com/Everial/Doclab/_packaging/plugins/maven/v1' name 'Main_Feed' } maven { url 'https://jitpack.io' } }
-
在variables.gradle中,将minSDK版本提高到24以兼容CameraX:
ext { minSdkVersion = 24 compileSdkVersion = 29 ... }
使用方法
该插件在Flutter/Dart中名为 ‘capture’:
import 'package:capture/capture.dart';
它需要添加到 ‘pubspec.yaml’ 文件中:
dependencies:
flutter:
sdk: flutter
git:
url: [Azure Git地址]
初始化(登录、密码)
SDK必须通过调用 initialize
函数进行初始化(登录、密码)。
第一次使用时,SDK会连接到认证服务器并获取授权应用包名。除非完成此初始验证,否则SDK无法使用。
返回对象
无论哪种情况,都会返回一个JSON痕迹。JSON是一个RTRLogs对象:
{
RTRLogs :[RTRLog],
Severity : int
}
RTRLog
{
type : case info=0,warning=1,error=2,fatal=3
caller:String,
shortDescription: String,
longDescription: String
}
日志是累积性的,需要检查 severity
字段以了解最严重的错误。
错误类型分类:
- 0: 信息:用于跟踪处理过程
- 1: 警告:遇到异常但不影响分析流程。主要是应用程序离线模式
- 2: 错误:在处理分析过程中发生错误(捕获、OCR、验证)。这不会影响后续分析或捕获继续
- 3: 致命:阻止错误。SDK无法运行。主要由于身份验证失败或初始化分析不可行
任何类型的3(致命)错误使分析无法使用。RTRLog表是信息性的。
示例:
try {
final res = await Capture().onInitialize(login, password);
if (res != null) {
// 处理结果
}
} on PlatformException catch (err) {
// 处理错误
}
当初始化成功时:
{
"RTRLogs":[
{
"caller":"<EverialRT.ConfigurationManager: 0x102f129c0>",
"longDescription":"remote config loaded for: bundle",
"type":0,
"shortDescription":"remote config loaded"
},
{
"caller":"<EverialRT.ConfigurationManager: 0x102f129c0>",
"longDescription":"remote config loaded for: schema",
"type":0,
"shortDescription":"remote config loaded"
}
],
"severityFlag":0
}
断网示例:
{
"RTRLogs":[
{
"caller":"<EverialRT.ConfigurationManager: 0x1056052c0>",
"longDescription":"Error while authenticating: Optional(Error Domain=NSURLErrorDomain Code=-1009 \"The Internet connection appears to be offline.\" UserInfo={NSUnderlyingError=0x282b57870 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 \"(null)\" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, NSErrorFailingURLStringKey=https:\/\/auth.devlab.everial.com\/auth\/realms\/quota\/protocol\/openid-connect\/token, NSErrorFailingURLKey=https:\/\/auth.devlab.everial.com\/auth\/realms\/quota\/protocol\/openid-connect\/token, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=50, NSLocalizedDescription=The Internet connection appears to be offline.})",
"type":2,
"shortDescription":"Error while authenticating"
}
],
"severityFlag":2
}
第一次使用时,如果没有启用互联网连接,初始化可能会返回这种响应:
{
"caller":"<EverialRT.RTR: 0x133e03af0>:processHiRes",
"longDescription":"User or SDK not granted for this application",
"type":3,
"shortDescription":"User or SDK not granted"
}
process({}, success, error)
该函数在父视图中实例化一个捕获视图并启动扫描。可以触摸视图来中断分析。
分析可以在不重新初始化的情况下重新启动。当捕获完成(匹配或中断)时,视图将从父视图中删除。
示例:
dynamic result = await Capture().onProcess();
result 包含数据:SUCCESS: JSON: 提取的文档数据 result 包含错误 / try-catch: ERROR: 错误消息
响应
响应的 content-type 为:application/json; charset=utf-8 响应结构如下:
subscriber
-> 相当于文档间的级别,即文件夹概念- 一个文档数组 -> 一个文档: CNI, JUDO
- 每个文档包含一个页面数组 -> 文档的页面,例如正反面
每个级别都有结构:
result -> "errors", "descriptions", "value" + "fields" at the page level
如果失败,错误日志将返回图像:
{
"caller":"analyse",
"longDescription":"base64 image url encoded",
"type":0,
"shortDescription":"Document"
}
使用响应进行操作
响应形式为:
{value:"JSON_DOC_STRING"}
因此,需要这样处理:
try {
dynamic result = await Capture().onProcess();
// 等效于:json.decode(docToFormat)['value'];
dynamic resValue = _getDocValue(result);
if (resValue != '') {
// 处理数据
} else {
throw Exception("Nothing to add.");
}
} on PlatformException catch (err) {
// 处理错误
}
consolidate({array of json documents}, success, error)
该方法允许对多个文档进行一致性检查。
await Capture().onConsolidate({ documents: docs })
iOS
如果提供的数组为空,应用程序将比较已分析的文档,即根据先前分析列表。列表构成方式为LIFO:相同类型的每个文档都会覆盖之前的文档。 然而,在客户端应用程序管理文档的情况下,可以在应用程序客户端存储已分析的文档,然后请求验证并重新提供适当的文档。 在这种情况下,文档的json需要提供在一个数组中。
注意:在这种情况下,分析引擎的列表将被提供的列表替换。
Android
应用程序负责管理已分析的文档。插件不保留任何先前分析的痕迹。 已分析的文档需要在应用程序客户端存储,并可以请求验证那些认为合适的文档。这些文档应在接收分析并存储在数组中的JSON字符串中重新提供。
响应
响应的 content-type 为:application/json; charset=utf-8
验证字段的结构与 process
的相同,但在 <strong>subscriber</strong>
键中有额外的控制。
analyze({ fileuri: file }, success, error)
该方法可以在不调用捕获函数的情况下实现文档分析。在这种情况下,假设应用程序支持文件收集。需要提供文件在设备上的路径。响应与 process
相同。
接受的类型为 image/* 和 application/pdf。
对于PDF,只分析第一页。
await Capture().onAnalyze({ fileuri: file })
Android
预期的字符串类型为Uri (android.net.Uri: Uri.toString())
iOS:
预期的字符串类型为URL (url.absolutestring())
selfie({ baseimage: extractedPhoto }, success, error)
await Capture().onSelfie({ baseimage: extractedPhoto })
该方法执行两个检查:
- 将提供的参数 “imgBase” (base64图像) 与用户的面部进行比较
- 生命证明测试
调用此功能时,摄像头会被触发,用户被要求将脸部放在框内几秒钟。 在iOS上,体验略有不同,会显示地标。 分析只需几秒钟,无需任何用户场景。
响应类型为json,只有一个键:
{"valid": "true" | "false"}
注意:应用程序记录所有与之前注册的文档相关的照片。
SSL Pinning
插件可以执行“中间人”检查。 为此,Everial会在您的用户级别激活此参数。
{"RTRContext" : "2.3.0:capsule-dev", "caller" : "com.everial.rtr.Configuration", "longDescription" : "SSL pinning enabled", "shortDescription" : "SSL pinning enabled", "type" : 0}
如果启用了检查,插件将在初始化时确保展示的公钥证书确实是Everial的。
初始化会返回错误。
此错误不是阻止性的,应用程序可以选择是否停止应用。
{"RTRContext" : "2.3.0:capsule-dev", "caller" : "com.everial.rtr.Configuration", "longDescription" : "user=capsule-dev,pub=CBSA08mY+VfrZrjVgkDDpFbz6JBBavdW6TPgbCYde58=, received certificate: Certificate pinning failure!\n Peer certificate chain:\n sha256/tJqnS+/9e9HeWUtNxnTbdpfA0oCOC9ka30l8fGiE4p0=: CN=k8s.doclab.fr\n sha256/Ns1wdAOg3MUrrOICXWYlMXelaJL9M6n/Y9nuYfZawsM=: C=NZ,ST=Auckland,L=Auckland,O=XK72 Ltd,OU=https://charlesproxy.com/ssl,CN=Charles Proxy CA (4 Nov 2021\\, MacBook-Pro-de-Sebastien.local)\n Pinned certificates for log.k8s.doclab.fr:\n sha256/CBSA08mY+VfrZrjVgkDDpFbz6JBBavdW6TPgbCYde58=", "shortDescription" : "Error while pinning certificate", "type" : 2}
更多关于Flutter屏幕捕获插件capture的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter屏幕捕获插件capture的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter应用中使用capture
插件进行屏幕捕获的代码示例。请注意,capture
插件的具体实现可能依赖于某个第三方库,因为Flutter本身并没有一个名为capture
的官方插件。在这里,我将使用一个假定的第三方插件screen_capture
来演示这一过程(请注意,实际使用时你需要替换为真实存在的插件)。
首先,你需要在pubspec.yaml
文件中添加屏幕捕获插件的依赖项(假设插件名为screen_capture
):
dependencies:
flutter:
sdk: flutter
screen_capture: ^x.y.z # 替换为实际的版本号
然后,运行flutter pub get
来安装该依赖项。
接下来,在你的Flutter项目中,你可以按照以下步骤使用屏幕捕获功能:
- 导入插件:
在你的Dart文件中导入插件:
import 'package:screen_capture/screen_capture.dart';
- 请求权限(如果需要):
某些平台(如Android)可能需要额外的权限来捕获屏幕。你需要在AndroidManifest.xml
中声明这些权限,并在运行时请求它们。以下是一个在Android上请求权限的示例(注意,具体实现可能因插件而异):
import 'package:permission_handler/permission_handler.dart';
Future<void> requestPermissions() async {
if (await Permission.storage.status != PermissionStatus.granted) {
Map<Permission, PermissionStatus> statuses = await Permission.request([
Permission.storage,
]);
if (statuses[Permission.storage] != PermissionStatus.granted) {
// 权限被拒绝,处理逻辑
return;
}
}
}
请确保在pubspec.yaml
中也添加了permission_handler
依赖项。
- 捕获屏幕:
使用插件提供的API来捕获屏幕:
void captureScreen() async {
try {
// 捕获屏幕并获取文件路径
String filePath = await ScreenCapture.capture();
// 显示或处理捕获的屏幕截图
print("Screenshot saved to: $filePath");
// 例如,你可以使用Image.file(File(filePath))来显示截图
} catch (e) {
// 处理错误
print("Failed to capture screenshot: $e");
}
}
- 在按钮点击事件中调用捕获函数:
在你的UI中,添加一个按钮来触发屏幕捕获:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Screen Capture Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
await requestPermissions(); // 请求权限(如果需要)
captureScreen(); // 捕获屏幕
},
child: Text('Capture Screen'),
),
),
),
);
}
}
请注意,上述代码是一个简化的示例,实际使用中可能需要处理更多的细节,如权限请求的UI、错误处理、以及在不同平台上的兼容性等。此外,由于screen_capture
是一个假定的插件名称,你需要替换为实际存在的屏幕捕获插件,并根据其文档进行相应的调整。