Flutter活体检测插件oiti_liveness2d的使用
Flutter活体检测插件oiti_liveness2d的使用

Oiti - Liveness 2D插件简介
在这个仓库中,我们找到了Oiti的Liveness 2D插件。该插件允许Flutter应用程序通过访问设备的原生功能来实现活体检测。
插件简介
Pub.dev是Dart语言的包管理器,包含了许多可重用的库和包,适用于Flutter和Dart程序。在Flutter中,插件是一种软件包,它提供对设备原生资源的访问,使Flutter应用能够与iOS和Android操作系统通信,并增加额外的功能,从而改善用户体验。这些插件通常使用Dart编写,并可能包含Kotlin或Swift等本地语言的代码。
最低要求
Android | iOS |
---|---|
Gradle: 6.8 | iOS: 11 |
概要
为了简化集成和定制流程,我们为Flutter开发者提供了以下指南:
更新日志
可以通过此链接查看各个版本的新功能。
更多信息
完整示例代码
以下是完整的示例代码,展示了如何在Flutter中使用oiti_liveness2d
插件进行活体检测。
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:oiti_liveness2d/common/doccore_success_result.dart';
import 'package:oiti_liveness2d/oiti_liveness2d.dart';
import 'package:oiti_liveness2d_example/widgets/camera_permission.dart';
import 'package:oiti_liveness2d_example/widgets/documentscopy.dart';
void main() {
runApp(const MaterialApp(
title: 'Navigation Basics',
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late TextEditingController _controller;
late TextEditingController _controllerT;
String _platformVersion = 'Unknown';
var appKey = '';
var ticket = '';
var showFeedback = false;
var resultTitle = '';
var resultContent = '';
final environment = Environment.hml;
// 初始化平台状态
Future<void> initPlatformState() async {
String? platformVersion = "10";
if (!mounted) return;
setState(() {
_platformVersion = platformVersion!;
});
}
[@override](/user/override)
void initState() {
super.initState();
initPlatformState();
_controller = TextEditingController();
_controllerT = TextEditingController();
}
[@override](/user/override)
void dispose() {
_controller.dispose();
_controllerT.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Liveness + Doc - Flutter'),
),
body: ListView(
children: [
_liveness2DWidgetOption(
context,
'Livneness2D',
true,
),
_liveness2DWidgetOption(
context,
'Livneness2D - S/ Feedback',
false,
),
const Padding(
padding: EdgeInsets.all(0),
child: Text(""),
),
_documentscopyWidgetOption(
context,
'Doc Core',
),
_documentscopyWidgetOption(
context,
'Doc Core - S/ Feedback',
showFeedback: false,
),
_documentscopyWidgetOption(
context,
'Doc Core Custom',
themeBuilder: _themeCustomization(),
instructionWidget: instructionScreen(),
permissionWidget: CameraPermissionWidget(),
),
_documentscopyWidgetOption(
context,
'Doc Intrução & Permissão Custom',
instructionWidget: instructionScreen(),
permissionWidget: CameraPermissionWidget(),
),
_documentscopyWidgetOption(
context,
'Doc Core Intrução Custom',
instructionWidget: instructionScreen(),
),
_documentscopyWidgetOption(
context,
'Doc Core Permissão Custom',
permissionWidget: CameraPermissionWidget(),
),
_hideInstructionWidgetOption(
context,
'Doc Core - Pular Telas',
themeBuilder: _themeCustomization(),
),
Padding(
padding: const EdgeInsets.all(20),
child: Text(resultContent),
),
Padding(
padding: const EdgeInsets.all(10),
child:
Text(ticket.isEmpty ? 'Ticket vazio' : 'Ticket disponivel'),
),
Padding(
padding: const EdgeInsets.all(10),
child:
Text(appKey.isEmpty ? 'AppKey vazia' : 'AppKey disponivel'),
),
ticketSection(),
appKeySection()
],
),
),
);
}
hideInstructions(
BuildContext context,
String appKey,
String ticket,
Environment environment,
ThemeBuilder? themeBuilder,
) {
OitiLiveness2d().checkPermission().then((authorized) => {
if (authorized)
{
OitiLiveness2d()
.openDocumentscopy(
appKey: appKey,
ticket: ticket,
themeBuilder: themeBuilder,
environment: environment,
showFeedback: true,
)
.then((result) async => {_onDocSuccess(result)})
.onError((error, stackTrace) async =>
{_onDocError(error as PlatformException)})
.catchError((error) async =>
{_onDocError(error as PlatformException)})
.whenComplete(() => _showAlertDialog(
context,
resultTitle,
resultContent,
))
}
});
}
Widget _liveness2DWidgetOption(
BuildContext context,
String title,
bool showFeedback,
) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 10, bottom: 5),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(50),
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OitiLiveness2d.createLiveness2DWidget(
appKey: appKey,
environment: environment,
showFeedback: showFeedback,
onSuccess: (result) => _onLiveness2DSuccess(result),
onError: (error) =>
_onLiveness2DError(error as PlatformException),
),
),
).whenComplete(
() => _showAlertDialog(
context,
resultTitle,
resultContent,
),
),
child: Text(title),
),
);
}
Widget _hideInstructionWidgetOption(
BuildContext context,
String title, {
ThemeBuilder? themeBuilder,
}) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 10, bottom: 5),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(50),
),
onPressed: () => hideInstructions(
context,
appKey,
ticket,
environment,
themeBuilder,
),
child: Text(title),
),
);
}
Widget _documentscopyWidgetOption(
BuildContext context,
String title, {
ThemeBuilder? themeBuilder,
Widget? instructionWidget,
Widget? permissionWidget,
bool showFeedback = true,
}) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 10, bottom: 5),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(50),
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OitiLiveness2d.createDocumentscopyWidget(
appKey: appKey,
ticket: ticket,
environment: environment,
showFeedback: showFeedback,
themeBuilder: themeBuilder,
onSuccess: (result) => _onDocSuccess(result),
onError: (error) => _onDocError(error as PlatformException),
instructionWidget: instructionWidget,
permissionWidget: permissionWidget,
),
),
).whenComplete(
() => _showAlertDialog(
context,
resultTitle,
resultContent,
),
),
child: Text(title),
),
);
}
Widget appKeySection() {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 45),
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'App Key',
),
obscureText: false,
controller: _controller,
onChanged: (value) => chageAppKey(value),
onSubmitted: (value) => _pasteAppKey(),
),
);
}
_pasteAppKey() {
setState(() => appKey = _controller.text);
_controller.text = appKey;
}
chageAppKey(String appkey) {
setState(() => appKey = appkey);
_controller.text = appkey;
}
Widget instructionScreen() {
return DocumentscopyWidget(
onError: (error) => _onDocError(error as PlatformException),
onSuccess: (result) => _onDocSuccess(result),
);
}
Widget ticketSection() {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 10),
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Ticket',
),
obscureText: false,
controller: _controllerT,
onChanged: (value) => chageTicket(value),
onSubmitted: (value) => _pasteTicket(),
),
);
}
_pasteTicket() {
setState(() => ticket = _controllerT.text);
_controllerT.text = ticket;
}
chageTicket(String ticketS) {
setState(() => ticket = ticketS);
_controllerT.text = ticketS;
}
Future<void> _showAlertDialog(
BuildContext context, String resultType, String content) async {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Resultado: $resultType'),
content: Text(content),
actions: <Widget>[
TextButton(
child: const Text('OK'),
onPressed: () => Navigator.of(context).pop(),
),
],
);
},
);
}
/// Liveness 3D Callbacks
_onLiveness2DSuccess(LivenessSuccessResult result) {
resultTitle = 'Sucesso';
resultContent =
'Valid: ${result.valid}\nCodID: ${result.codId}\nCause: ${result.cause}\nProtocol: ${result.protocol}\n';
}
_onLiveness2DError(PlatformException? error) {
resultTitle = 'Error';
resultContent = 'Cause: ${error?.message}';
}
_onDocSuccess(DocCoreSuccessResult result) {
resultTitle = 'Sucesso';
resultContent = result.message;
}
_onDocError(PlatformException? error) {
resultTitle = 'Error';
resultContent = 'Cause: ${error?.message}';
}
ThemeBuilder _themeCustomization() {
return ThemeBuilder()
..setCaptureBackgroundColor = "#ff1d0d"
..setInstructionBackgroundColor = "#123456"
..setInstructionBackButtonColorsIcon = "#789abc"
..setInstructionBackButtonColorsBackground = "#def123"
..setInstructionBackButtonColorsBorder = "#456789"
..setInstructionLoadingColor = "#abc789"
..setInstructionBottomSheetColor = "#345678"
..setInstructionBottomSheetRadius = 8
..setInstructionTitleText = "Your Title"
..setInstructionTitleColor = "#234567"
..setInstructionTitleFont = "Roboto"
..setInstructionCaptionText = "Your Caption"
..setInstructionCaptionColor = "#345678"
..setInstructionCaptionFont = "Arial"
..setInstructionDocOptionBackgroundColor = "#456789"
..setInstructionDocOptionTitleText = "Document Option"
..setInstructionDocOptionTitleColor = "#567890"
..setInstructionDocOptionTitleFont = "Courier New"
..setInstructionDocOptionBorderColor = "#678901"
..setInstructionDocOptionBorderWidth = 2
..setInstructionDocOptionBorderRadius = 4
..setInstructionDocOptionBackgroundColor = "#456789"
..setInstructionDocOptionTitleText = "Document Option"
..setInstructionDocOptionTitleColor = "#567890"
..setInstructionDocOptionTitleFont = "Courier New"
..setInstructionDocOptionBorderColor = "#678901"
..setInstructionDocOptionBorderWidth = 2
..setInstructionDocOptionBorderRadius = 4
..setInstructionEnvOptionBackgroundColor = "#789012"
..setInstructionEnvOptionTitleText = "Environment Option"
..setInstructionEnvOptionTitleColor = "#890123"
..setInstructionEnvOptionTitleFont = "Helvetica"
..setInstructionEnvOptionBorderColor = "#901234"
..setInstructionEnvOptionBorderWidth = 3
..setInstructionEnvOptionBorderRadius = 6
..setInstructionContinueButtonBackgroundColor = "#234567"
..setInstructionContinueButtonHighlightedBackgroundColor = "#345678"
..setInstructionContinueButtonBorderColor = "#456789"
..setInstructionContinueButtonHighlightedBorderColor = "#567890"
..setInstructionContinueButtonContentColor = "#678901"
..setInstructionContinueButtonHighlightedContentColor = "#789012"
..setInstructionContinueButtonTextColor = "#890123"
..setInstructionContinueButtonFont = "Arial"
..setCaptureInstructionGuideReviewText = "Review"
..setLoadingBackgroundColor = "#901234"
..setLoadingSpinnerColor = "#012345"
..setLoadingSpinnerWidth = 2
..setLoadingSpinnerScale = 1
..setCaptureBackgroundColor = "#123456"
..setTextFront = "Front Text"
..setTextBack = "Back Text"
..setCaptureInstructionGuideTextFront = "Front Guide Text"
..setCaptureInstructionGuideTextBack = "Back Guide Text"
..setTextOk = "OK Text"
..setCaptureTakeNewPictureButtonText = "Take New Picture"
..setCaptureInstructionGuideTextColor = "#345678"
..setTextConfirmation = "Confirmation Text"
..setBackgroundOkColor = "#456789"
..setCaptureBackButtonIcon = "back_icon.png"
..setCaptureBackButtonColorsIcon = "#567890"
..setCaptureBackButtonColorsBackground = "#678901"
..setCaptureBackButtonColorsBorder = "#789012"
..setCaptureCloseButtonColorsIcon = "#890123"
..setCaptureCloseButtonColorsBackground = "#901234"
..setCaptureCloseButtonColorsBorder = "#012345"
..setCaptureFrontIndicatorColor = "#123456"
..setCaptureFrontIndicatorFocusedStateColor = "#234567"
..setCaptureFrontIndicatorUnfocusedStateColor = "#345678"
..setCaptureBackIndicatorColor = "#456789"
..setCaptureBackIndicatorFocusedStateTextColor = "#567890"
..setCaptureBackIndicatorUnfocusedStateTextColor = "#678901"
..setCaptureInstructionTextColor = "#789012"
..setCapturePreviewBorderColorForCapture = "#234567"
..setCapturePreviewBorderColorForUncapturedState = "#345678"
..setCaptureCaptureButtonHighlightedStateColorsIcon = "#456789"
..setCaptureCaptureButtonHighlightedStateColorsBackground = "#567890"
..setCaptureCaptureButtonHighlightedStateColorsBorder = "#678901"
..setCaptureCaptureButtonNormalStateColorsIcon = "#789012"
..setCaptureCaptureButtonNormalStateColorsBackground = "#890123"
..setCaptureCaptureButtonNormalStateColorsBorder = "#901234"
..setCaptureCaptureButtonDisabledStateColorsIcon = "#012345"
..setCaptureCaptureButtonDisabledStateColorsBackground = "#123456"
..setCaptureCaptureButtonDisabledStateColorsBorder = "#234567"
..setCaptureBottomSheetShapeColor = "#345678"
..setCaptureBottomSheetShapeCornerRadius = 10
..setCaptureTakeNewPictureButtonHighlightedStateColorsText = "#456789"
..setCaptureTakeNewPictureButtonHighlightedStateColorsBackground =
"#567890"
..setCaptureTakeNewPictureButtonHighlightedStateColorsBorder = "#678901"
..setCaptureTakeNewPictureButtonNormalStateColorsText = "#789012"
..setCaptureTakeNewPictureButtonNormalStateColorsBackground = "#890123"
..setCaptureTakeNewPictureButtonNormalStateColorsBorder = "#901234"
..setCaptureTakeNewPictureButtonDisabledStateColorsText = "#012345"
..setCaptureTakeNewPictureButtonDisabledStateColorsBackground = "#123456"
..setCaptureTakeNewPictureButtonDisabledStateColorsBorder = "#234567"
..setCaptureUsePictureButtonText = "Use Picture"
..setCaptureUsePictureButtonConfirmationText = "Confirm"
..setCaptureUsePictureButtonHighlightedStateColorsText = "#345678"
..setCaptureUsePictureButtonHighlightedStateColorsBackground = "#456789"
..setCaptureUsePictureButtonHighlightedStateColorsBorder = "#567890"
..setCaptureUsePictureButtonNormalStateColorsText = "#678901"
..setCaptureUsePictureButtonNormalStateColorsBackground = "#789012"
..setCaptureUsePictureButtonNormalStateColorsBorder = "#890123"
..setCaptureUsePictureButtonDisabledStateColorsText = "#901234"
..setCaptureUsePictureButtonDisabledStateColorsBackground = "#012345"
..setCaptureUsePictureButtonDisabledStateColorsBorder = "#123456"
..setResultBackgroundColorSuccess = "#234567"
..setResultBackgroundColorError = "#345678"
..setResultBackgroundColorTryAgain = "#456789"
..setResultMessageSuccess = "Success Message"
..setResultMessageError = "Error Message"
..setResultMessageTryAgain = "Try Again Message"
..setResultMessageColorSuccess = "#567890"
..setResultMessageColorError = "#678901"
..setResultMessageColorTryAgain = "#789012"
..setResultTryAgainButtonText = "Try Again"
..setResultTryAgainButtonHighlightedStateColorsText = "#890123"
..setResultTryAgainButtonHighlightedStateColorsBackground = "#901234"
..setResultTryAgainButtonHighlightedStateColorsBorder = "#012345"
..setResultTryAgainButtonNormalStateColorsText = "#123456"
..setResultTryAgainButtonNormalStateColorsBackground = "#234567"
..setResultTryAgainButtonNormalStateColorsBorder = "#345678";
}
}
更多关于Flutter活体检测插件oiti_liveness2d的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter活体检测插件oiti_liveness2d的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter中的活体检测插件oiti_liveness2d
的使用,下面是一个简单的代码示例,展示如何在Flutter应用中集成和使用该插件。请注意,为了运行此代码,你需要在pubspec.yaml
文件中添加oiti_liveness2d
依赖,并确保已经正确配置好Android和iOS平台的权限和依赖。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加oiti_liveness2d
依赖:
dependencies:
flutter:
sdk: flutter
oiti_liveness2d: ^最新版本号 # 请替换为最新的版本号
然后运行flutter pub get
来安装依赖。
2. 配置权限
确保在AndroidManifest.xml
和Info.plist
中配置了必要的相机和面部识别权限。
Android (AndroidManifest.xml
)
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
iOS (Info.plist
)
<key>NSCameraUsageDescription</key>
<string>App需要访问相机进行活体检测</string>
<key>NSFaceIDUsageDescription</key>
<string>App需要访问面部识别进行活体检测</string>
3. 使用插件
下面是一个简单的Flutter应用示例,展示如何使用oiti_liveness2d
插件进行活体检测:
import 'package:flutter/material.dart';
import 'package:oiti_liveness2d/oiti_liveness2d.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter 活体检测示例',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LivenessDetectionScreen(),
);
}
}
class LivenessDetectionScreen extends StatefulWidget {
@override
_LivenessDetectionScreenState createState() => _LivenessDetectionScreenState();
}
class _LivenessDetectionScreenState extends State<LivenessDetectionScreen> {
OitiLiveness2dController? _controller;
bool _isDetecting = false;
String _result = '';
@override
void initState() {
super.initState();
_initLivenessDetection();
}
Future<void> _initLivenessDetection() async {
_controller = OitiLiveness2dController();
_controller!.initCamera().then((_) {
setState(() {
_isDetecting = true;
});
}).catchError((error) {
print('初始化相机失败: $error');
});
_controller!.setListener((result) {
setState(() {
_result = result ? '活体检测通过' : '活体检测失败';
_isDetecting = false; // 假设单次检测后停止
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('活体检测示例'),
),
body: Center(
child: _isDetecting
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
SizedBox(height: 20),
Text('正在检测中...'),
],
)
: Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
height: 300,
width: 300,
decoration: BoxDecoration(
color: Colors.black,
),
child: _controller!.previewWidget,
),
ElevatedButton(
onPressed: _startDetection,
child: Text('开始检测'),
),
SizedBox(height: 20),
Text(_result),
],
),
),
);
}
void _startDetection() {
if (_controller!.isCameraReady) {
_controller!.startDetection();
} else {
print('相机未准备好');
}
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
}
注意事项
- 权限请求:在实际应用中,你需要在开始检测前请求用户授权相机权限。这可以通过
permission_handler
等插件来实现。 - UI优化:示例代码中的UI较为简单,你可以根据实际需求进行优化。
- 错误处理:示例代码中对错误处理较为简单,实际应用中应添加更详细的错误处理逻辑。
希望这个示例能帮你快速上手oiti_liveness2d
插件的使用。如果有更多问题,欢迎继续提问!