Flutter面部识别插件facetec_flutter_plugin_demo的使用
Flutter面部识别插件facetec_flutter_plugin_demo的使用
更新版本以支持最新SDK版本
此插件通过Android或iOS平台为Flutter应用提供对FaceTec SDK的便捷访问。该插件由SnapCommute Labs Pvt. Ltd. 创建。该插件功能有限。如需完整的插件功能,请发送邮件至plugins@snapcommute.com。完整版插件包含注册、认证、ID扫描等功能,并且具有通过FaceTec SDK提供的完整自定义选项。
注意事项
此插件仅是一个演示插件,具有最低限度的功能。目前,该插件与iOS和Android SDK版本9.6.16兼容,Flutter版本为3.3。
安装
在项目的pubspec.yaml
文件中添加以下内容:
facetec_flutter_plugin_demo:
path: ../
根据示例应用,更新FaceTec开发者网站上提供的设备密钥标识符。
文件复制和修改
由于FaceTec SDK文件较大,不包含在Flutter Pub文件夹中。请访问FaceTec开发者网站(dev.facetec.com)下载SDK文件,并将相应的文件复制到此插件的根目录下。
对于Android,下载的zip文件中会有一个.aar文件(例如facetec-sdk-version#.aar
),需要将其复制到android
根目录下的libs
文件夹中。对于iOS,下载的zip文件中会有一个名为FaceTecSDK.xcframework
的文件夹,需要将其复制到iOS根目录下。
还需要复制图像文件以确保最新的SDK正常工作。对于Android,将所有动画和可绘制文件夹复制到res
文件夹中。这些文件夹可以在从FaceTec网站下载的SDK zip文件中的Android示例应用中找到。对于iOS,将所有图像文件复制到类似结构的assets/images
文件夹中,并在pubspec.yaml
文件中添加相应的资产代码。
对于iOS,还需要在info.plist
文件中添加NSCameraUsageDescription
,以便相机权限屏幕出现。
插件中可用的函数
FacetecFlutterPluginDemo.initialize("ADD YOUR KEY HERE", isProductionMode, "PRODUCTION KEY TEXT");
FacetecFlutterPluginDemo.verify();
FacetecFlutterPluginDemo.enroll("user_id");
FacetecFlutterPluginDemo.authenticate("user_id");
FacetecFlutterPluginDemo.idCheck("user_id", isNewUser);
FacetecFlutterPluginDemo.getEnrollmentStatus("user_id", "CUSTOM ENROLLMENT STATUS END POINT");
FacetecFlutterPluginDemo.deleteEnrollment("user_id", "CUSTOM DELETE ENROLLMENT END POINT");
FacetecFlutterPluginDemo.auditTrail();
FacetecFlutterPluginDemo.idScanImages();
FacetecFlutterPluginDemo.setServerUrl("sever_url");
FacetecFlutterPluginDemo.setPublicKey("public_key");
FacetecFlutterPluginDemo.setTheme("theme");
FacetecFlutterPluginDemo.getSdkStatus();
FacetecFlutterPluginDemo.getVersion();
使用示例
以下是完整的示例代码,展示了如何使用facetec_flutter_plugin_demo
插件进行初始化、注册、认证等操作。
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:facetec_flutter_plugin_demo/facetec_flutter_plugin_demo.dart';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
String message = "";
int messageCounter = 0;
TextEditingController textFieldController = TextEditingController();
bool initialized = false;
File? idImageFile;
String base64image = "";
GlobalKey scaffoldKey = GlobalKey();
[@override](/user/override)
void initState() {
super.initState();
initPlatformState();
}
void addMessage(String msg, BuildContext context) {
setState(() {
messageCounter++;
showToast(context, msg);
message = messageCounter.toString() + ": " + msg + "\n" + message;
});
}
void showToast(BuildContext context, String msg) {
final scaffold = ScaffoldMessenger.of(scaffoldKey.currentContext!);
scaffold.showSnackBar(
SnackBar(
content: Text(msg),
action: SnackBarAction(
label: 'OK', onPressed: scaffold.hideCurrentSnackBar),
),
);
}
// 平台消息异步,因此我们在异步方法中初始化。
Future<void> initPlatformState() async {
String platformVersion;
// 平台消息可能失败,所以我们使用try/catch来处理PlatformException。
// 我们还处理消息可能返回null的情况。
try {
platformVersion = await FacetecFlutterPluginDemo.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// 如果在异步平台消息飞行期间小部件从树中删除,我们想要丢弃回复而不是调用
// setState来更新我们的不存在的外观。
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
Future<void> displayTextInputDialog(
BuildContext context, String title, Function onOk) async {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(title),
content: TextField(
controller: textFieldController,
decoration: InputDecoration(hintText: "Enter details"),
),
actions: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.red, primary: Colors.white),
child: Text('CANCEL'),
onPressed: () {
setState(() {
Navigator.pop(context);
});
},
),
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.red, primary: Colors.white),
child: Text('OK'),
onPressed: () {
setState(() {
onOk();
Navigator.pop(context);
});
},
),
],
);
});
}
final ButtonStyle flatButtonStyle = TextButton.styleFrom(
primary: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
backgroundColor: Colors.lightBlue,
);
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: const Text('FaceTec Plugin Demo'),
),
body: Center(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Initialize',
style: TextStyle(fontSize: 20.0),
),
onPressed: () async {
String publicKey = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5PxZ3DLj+zP6T6HFgzzk\n" +
"M77LdzP3fojBoLasw7EfzvLMnJNUlyRb5m8e5QyyJxI+wRjsALHvFgLzGwxM8ehz\n" +
"DqqBZed+f4w33GgQXFZOS4AOvyPbALgCYoLehigLAbbCNTkeY5RDcmmSI/sbp+s6\n" +
"mAiAKKvCdIqe17bltZ/rfEoL3gPKEfLXeN549LTj3XBp0hvG4loQ6eC1E1tRzSkf\n" +
"GJD4GIVvR+j12gXAaftj3ahfYxioBH7F7HQxzmWkwDyn3bqU54eaiB7f0ftsPpWM\n" +
"ceUaqkL2DZUvgN0efEJjnWy5y1/Gkq5GGWCROI9XG/SwXJ30BbVUehTbVcD70+ZF\n" +
"8QIDAQAB\n" +
"-----END PUBLIC KEY-----";
String serverUrl =
"https://api.facetec.com/api/v3.1/biometrics";
String appToken = "Enter your FaceTec license key here";
String publicKeyMsg =
await FacetecFlutterPluginDemo.setPublicKey(
publicKey);
if (publicKeyMsg.startsWith("success")) {
addMessage(publicKeyMsg.substring(7), context);
} else {
addMessage(publicKeyMsg.substring(5), context);
}
String serverUrlMsg =
await FacetecFlutterPluginDemo.setServerUrl(
serverUrl);
if (serverUrlMsg.startsWith("success")) {
addMessage(serverUrlMsg.substring(7), context);
} else {
addMessage(serverUrlMsg.substring(5), context);
}
String initializeMsg =
await FacetecFlutterPluginDemo.initialize(
appToken, false, "");
if (initializeMsg.startsWith("success")) {
initialized = true;
addMessage(initializeMsg.substring(7), context);
} else {
addMessage(initializeMsg.substring(5), context);
}
},
style: flatButtonStyle,
),
),
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Enroll',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
if (initialized) {
displayTextInputDialog(context, "Enter user Id", () async {
String enrollMsg =
await FacetecFlutterPluginDemo.enroll(
textFieldController.text);
if (enrollMsg.startsWith("success")) {
addMessage(enrollMsg.substring(7), context);
} else {
addMessage(enrollMsg.substring(5), context);
}
});
} else {
showToast(context, "SDK not initialized");
}
},
style: flatButtonStyle,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Authenticate',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
if (initialized) {
displayTextInputDialog(context, "Enter user Id", () async {
String enrollMsg =
await FacetecFlutterPluginDemo.authenticate(
textFieldController.text);
if (enrollMsg.startsWith("success")) {
addMessage(enrollMsg.substring(7), context);
} else {
addMessage(enrollMsg.substring(5), context);
}
});
} else {
showToast(context, "SDK not initialized");
}
},
style: flatButtonStyle,
),
),
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Verify',
style: TextStyle(fontSize: 20.0),
),
onPressed: () async {
if (initialized) {
String enrollMsg =
await FacetecFlutterPluginDemo.verify();
if (enrollMsg.startsWith("success")) {
addMessage(enrollMsg.substring(7), context);
} else {
addMessage(enrollMsg.substring(5), context);
}
} else {
showToast(context, "SDK not initialized");
}
},
style: flatButtonStyle,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'IDCheck',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
if (initialized) {
showSimpleDialogIDCheck(context, false);
} else {
showToast(context, "SDK not initialized");
}
},
style: flatButtonStyle,
),
),
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Audit Trail',
style: TextStyle(fontSize: 20.0),
),
onPressed: () async {
if (initialized) {
String enrollMsg =
await FacetecFlutterPluginDemo.auditTrail();
if (enrollMsg.startsWith("success")) {
await showDialog(
context: context,
builder: (_) => imageDialog('IDscanImage', enrollMsg.substring(7), context));
} else {
addMessage(enrollMsg.substring(5), context);
}
} else {
showToast(context, "SDK not initialized");
}
},
style: flatButtonStyle,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'ID Scan Images',
style: TextStyle(fontSize: 20.0),
),
onPressed: () async {
if (initialized) {
String enrollMsg =
await FacetecFlutterPluginDemo.idScanImages();
if (enrollMsg.startsWith("success")) {
await showDialog(
context: context,
builder: (_) => imageDialog('IDscanImage', enrollMsg.substring(7), context));
} else {
addMessage(enrollMsg.substring(5), context);
}
} else {
showToast(context, "SDK not initialized");
}
},
style: flatButtonStyle,
),
),
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Set Theme',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
showSimpleDialog(context);
},
style: flatButtonStyle,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Get Version',
style: TextStyle(fontSize: 20.0),
),
onPressed: () async {
String versionMsg =
await FacetecFlutterPluginDemo.getVersion();
if (versionMsg.startsWith("success")) {
addMessage(versionMsg.substring(7), context);
} else {
addMessage(versionMsg.substring(5), context);
}
},
style: flatButtonStyle,
),
),
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Get SDK Status',
style: TextStyle(fontSize: 20.0),
),
onPressed: () async {
String statusMsg =
await FacetecFlutterPluginDemo.getSdkStatus();
if (statusMsg.startsWith("success")) {
addMessage(statusMsg.substring(7), context);
} else {
addMessage(statusMsg.substring(5), context);
}
},
style: flatButtonStyle,
),
),
],
),
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Get User Enrollment Status',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
if (initialized) {
displayTextInputDialog(context, "Enter user Id", () async {
String enrollMsg = await FacetecFlutterPluginDemo.getUserEnrollmentStatus(
textFieldController.text, "");
if (enrollMsg.startsWith("success")) {
addMessage(enrollMsg.substring(7), context);
} else {
addMessage(enrollMsg.substring(5), context);
}
});
} else {
showToast(context, "SDK not initialized");
}
},
style: flatButtonStyle,
),
),
Container(
margin: EdgeInsets.all(2),
child: TextButton(
child: Text(
'Delete Enrollment',
style: TextStyle(fontSize: 20.0),
),
onPressed: () async {
if (initialized) {
displayTextInputDialog(context, "Enter user Id", () async {
String enrollMsg =
await FacetecFlutterPluginDemo.deleteEnrollment(
textFieldController.text, "");
if (enrollMsg.startsWith("success")) {
addMessage(enrollMsg.substring(7), context);
} else {
addMessage(enrollMsg.substring(5), context);
}
});
} else {
showToast(context, "SDK not initialized");
}
},
style: flatButtonStyle,
),
),
Expanded(
flex: 1,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Text(
message,
),
),
),
],
),
),
)),
);
}
// 显示对话框
showSimpleDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: const Text('Choose an theme'),
children: [
SimpleDialogOption(
child: const Text("FaceTec Theme"),
onPressed: () {
Navigator.of(context).pop();
setTheme("FaceTec Theme");
},
),
SimpleDialogOption(
child: const Text("Pseudo-Fullscreen"),
onPressed: () {
Navigator.of(context).pop();
setTheme("Pseudo-Fullscreen");
},
),
SimpleDialogOption(
child: const Text("Well-Rounded"),
onPressed: () {
Navigator.of(context).pop();
setTheme("Well-Rounded");
},
),
SimpleDialogOption(
child: const Text("Bitcoin Exchange"),
onPressed: () {
Navigator.of(context).pop();
setTheme("Bitcoin Exchange");
},
),
SimpleDialogOption(
child: const Text("eKYC"),
onPressed: () {
Navigator.of(context).pop();
setTheme("eKYC");
},
),
SimpleDialogOption(
child: const Text("Sample Bank"),
onPressed: () {
Navigator.of(context).pop();
setTheme("Sample Bank");
},
)
],
);
},
);
}
setTheme(String theme) {
FacetecFlutterPluginDemo.setTheme(theme);
}
Image imageFromBase64String(String base64String) {
return Image.memory(base64Decode(base64String));
}
Widget imageDialog(text, base64, context) {
return Dialog(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'$text',
style: TextStyle(fontWeight: FontWeight.bold),
),
IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: Icon(Icons.close_rounded),
color: Colors.redAccent,
),
],
),
),
Container(
width: 220,
height: 200,
child: imageFromBase64String(base64),
),
],
),
);
}
showSimpleDialogIDCheck(BuildContext context, bool custom) {
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: const Text('Choose whether existing or new user'),
children: [
SimpleDialogOption(
child: const Text("Existing User"),
onPressed: () {
Navigator.of(context).pop();
if (custom) {
} else {
displayTextInputDialog(context, "Enter user Id", () async {
String enrollMsg = await FacetecFlutterPluginDemo.idCheck(
textFieldController.text, false);
if (enrollMsg.startsWith("success")) {
addMessage(enrollMsg.substring(7), context);
} else {
addMessage(enrollMsg.substring(5), context);
}
});
}
},
),
SimpleDialogOption(
child: const Text("New User"),
onPressed: () {
Navigator.of(context).pop();
if (custom) {
} else {
displayTextInputDialog(context, "Enter user Id", () async {
String enrollMsg = await FacetecFlutterPluginDemo.idCheck(
textFieldController.text, true);
if (enrollMsg.startsWith("success")) {
addMessage(enrollMsg.substring(7), context);
} else {
addMessage(enrollMsg.substring(5), context);
}
});
}
},
),
],
);
},
);
}
}
更多关于Flutter面部识别插件facetec_flutter_plugin_demo的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter面部识别插件facetec_flutter_plugin_demo的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 facetec_flutter_plugin_demo
插件的示例代码。这个插件通常用于面部识别功能,假设你已经安装并配置好了 Flutter 环境,并且已经添加了 facetec_flutter_plugin
到你的 pubspec.yaml
文件中。
1. 添加依赖
首先,确保你的 pubspec.yaml
文件中已经包含了 facetec_flutter_plugin
的依赖:
dependencies:
flutter:
sdk: flutter
facetec_flutter_plugin: ^latest_version # 请替换为实际最新版本号
然后运行 flutter pub get
来安装依赖。
2. 配置 Android 和 iOS
由于面部识别功能涉及到原生代码,你需要在 Android 和 iOS 项目中进行一些配置。这通常包括添加必要的权限和配置文件。详细步骤请参考插件的官方文档。
3. 使用插件进行面部识别
以下是一个简单的 Flutter 应用示例,展示如何使用 facetec_flutter_plugin
进行面部识别:
import 'package:flutter/material.dart';
import 'package:facetec_flutter_plugin/facetec_flutter_plugin.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String result = "";
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Facetec Flutter Plugin Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Face Recognition Result:',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
Text(
result,
style: TextStyle(fontSize: 18),
),
SizedBox(height: 40),
ElevatedButton(
onPressed: () async {
try {
// 这里假设你已经有了一个 FaceTec 账户并获取了必要的 API 密钥等信息
String apiKey = "YOUR_API_KEY";
String apiSecret = "YOUR_API_SECRET";
String sessionId = "YOUR_SESSION_ID"; // 这个通常是在开始会话时由服务器生成的
// 初始化插件
FacetecFlutterPlugin facetec = FacetecFlutterPlugin();
// 开始面部识别
String recognitionResult = await facetec.startFaceRecognition(
apiKey: apiKey,
apiSecret: apiSecret,
sessionId: sessionId,
);
// 更新 UI
setState(() {
result = recognitionResult;
});
} catch (e) {
setState(() {
result = "Error: ${e.message}";
});
}
},
child: Text('Start Face Recognition'),
),
],
),
),
),
);
}
}
注意事项
-
API 密钥和会话管理:在实际应用中,你需要管理 API 密钥和会话 ID。通常,你会有一个后端服务来处理这些敏感信息,并生成会话 ID。
-
错误处理:上面的示例中简单地捕获了异常并更新了 UI,但在生产环境中,你可能需要更详细的错误处理和用户反馈。
-
权限请求:确保在 Android 和 iOS 上请求了必要的权限,如相机权限。
-
UI/UX:上面的示例是一个简单的按钮点击事件,实际应用中你可能需要更复杂的 UI/UX 设计,比如引导用户进行面部扫描的界面。
-
插件版本:确保你使用的是最新版本的插件,并查看官方文档以获取最新的使用指南和 API 更改。
这个示例代码应该能帮助你开始使用 facetec_flutter_plugin
进行面部识别。如果你有更具体的需求或遇到问题,请查阅插件的官方文档或寻求官方支持。