Flutter生物识别访问插件biometric_access的使用

Flutter生物识别访问插件biometric_access的使用

生物识别访问插件biometric_access

Biometric Access 插件允许在单个插件中无缝集成多种生物识别设备,包括指纹和虹膜扫描仪。它为开发者提供了一个易于使用的API,以便在多个受支持的设备上实现安全高效的基于生物识别的身份验证。

支持平台

  • Android(开发中)
  • Web

生物识别设备

计划支持多种生物识别设备:

  • Mantra(测试于:MSF100)
  • Mantra IRIS(测试于:MIS100V2)
  • Morpho(部分测试于:MSO 1300)
  • Secugen(仅限Web)
  • Evolute(仅限Web)
  • Startek(仅限Web)

安装

pubspec.yaml 文件中添加 biometric_access 依赖:

dependencies:
  biometric_access: ^0.0.1

运行以下命令来安装包:

flutter pub get

驱动程序

Android

  1. 从Play商店下载:

Web

  1. 从官方站点下载最新驱动和RD服务:

Web平台的使用说明

  1. 将您的生物识别设备插入,并确保驱动程序和RD服务已正确安装。
  2. 在初始设置时,您会在右下角看到一个提示,指示您拔出并重新插入设备以进行正确的初始化。
  3. 重新连接设备后,您应该会看到另一个提示确认生物识别设备的连接。
  4. 一旦设备成功连接到服务器,会出现一条消息“Framework ready to use”。

使用示例

导入包

import 'package:biometric_access/biometric_access.dart';

发现RDServices(仅限Web平台)

try {
  List<RdServiceModel> result = await BiometricAccess().discoverRDServices();
  if (result.isNotEmpty) {
    result.forEach((e) => print(e.rdInfo));
    _biometricAccessPlugin.setRDService = result[0]; // 更新当前RD服务
  } else {
    print('No RDService found, please restart services on Windows'); 
  }
} on RDClientNotFound catch (err)  {
  print(err.toJson());
} catch (e) => customToast(e.toString());

设备信息作为XML

try {
  String result = await BiometricAccess().getDeviceInfoAsXML();
  print(result); // 返回原始设备信息XML,未经验证
} catch (e) => print(e.toString());

设备信息作为字符串和DeviceInfoModel对象

try {
  (String, DeviceInfoModel) result = await BiometricAccess().getDeviceInfoAsObject();
  print(result); // 返回设备信息作为 ([String], [DeviceInfoModel])
} catch (e) => print(e.toString());

捕获指纹作为XML

try {
  String result = await BiometricAccess().captureFingerPrintAsXml();
  print(result); // 返回原始捕获XML,未经验证
} catch (e) => print(e.toString());

捕获指纹作为字符串和PidDataModel对象

try {
  (String, PidDataModel) result = await BiometricAccess().captureFingerPrintAsObject();
  print(result); // 返回捕获响应作为 ([String], [PidDataModel])
} catch (e) => print(e.toString());

示例代码

以下是完整的示例代码:

import 'dart:developer';

import 'package:biometric_access/biometric_access.dart';
import 'package:biometric_access/model/biometric_access_exception.dart';
import 'package:biometric_access/model/pid_data_model.dart';
import 'package:biometric_access/model/rd_services_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _biometricAccessPlugin = BiometricAccess();
  final _messangerKey = GlobalKey<ScaffoldMessengerState>();
  bool enableClipBoardCoping = true;
  String? resultData;
  bool showLoader = false;
  List<RdServiceModel>? rdServiceList;
  Size get responsive => MediaQuery.of(context).size;
  TextEditingController textCtrl = TextEditingController(
      text:
          """<?xml version="1.0"?>
          <PidOptions ver="1.0">
            <Opts fCount="1" fType="0" iCount="0" pCount="0" format="0" pidVer="2.0" timeout="10000" posh="UNKNOWN" env="PP" />
          </PidOptions>""");

  updateUi() => setState(() {});
  void customToast(String message) {
    debugPrint(message);
    _messangerKey.currentState!.showSnackBar(SnackBar(
      behavior: SnackBarBehavior.floating,
      content: Text(
        message,
        style: const TextStyle(fontSize: 12),
      ),
    ));
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      scaffoldMessengerKey: _messangerKey,
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: const Color.fromARGB(221, 17, 16, 16),
          title: const Text(
            'BioMetric access',
            style: TextStyle(color: Colors.white),
          ),
          actions: [
            Container(
              padding: const EdgeInsets.only(right: 15),
              height: 30,
              child: Row(
                children: [
                  const Text(
                    "Auto Clipboard",
                    style: TextStyle(fontSize: 13, color: Colors.white),
                  ),
                  const SizedBox(width: 5),
                  FittedBox(
                    fit: BoxFit.fill,
                    child: Switch(
                      value: enableClipBoardCoping,
                      activeColor: Colors.white,
                      onChanged: (bool value) {
                        setState(() {
                          enableClipBoardCoping = value;
                        });
                      },
                    ),
                  ),
                ],
              ),
            )
          ],
        ),
        bottomNavigationBar: Padding(
          padding: const EdgeInsets.only(top: 20, right: 10, left: 10, bottom: 10),
          child: Wrap(
            children: [
              customButton("Discover RDService", () async {
                setState(() => showLoader = true);
                try {
                  _biometricAccessPlugin.setRDService = null;
                  rdServiceList = (await _biometricAccessPlugin.discoverRDServices());
                  setState(() {});
                  showLoader = false;
                } on RDClientNotFound catch (err)  {
                  debugPrint(err.toJson().toString());
                } 
                catch (e) {
                  customToast(e.toString());
                }
              }),
              customButton("DeviceInfo as XML", () async {
                try {
                  setState(() => showLoader = true);
                  final data = await _biometricAccessPlugin.getDeviceInfoAsXML();
                  resultData = data;
                  await copyToClipboard(resultData);
                } catch (e) {
                  customToast(e.toString());
                }
                setState(() => showLoader = false);
              }),
              customButton("DeviceInfo as object", () async {
                try {
                  setState(() => showLoader = true);
                  final data = await _biometricAccessPlugin.getDeviceInfoAsObject();
                  resultData = (data.$2.toJson().toString());
                  await copyToClipboard(resultData);
                } catch (e) {
                  customToast(e.toString());
                }
                setState(() => showLoader = false);
              }),
              customButton("Capture FingerPrint as object", () async {
                try {
                  setState(() => showLoader = true);
                  (String, PidDataModel) data = await _biometricAccessPlugin
                      .captureFingerPrintAsObject(textCtrl.text);
                  resultData = data.$2.toJson().toString();
                  await copyToClipboard(resultData);
                } catch (e, s) {
                  customToast(e.toString());
                  log(s.toString());
                }
                setState(() => showLoader = false);
              }),
              customButton("Capture FingerPrint as XML", () async {
                try {
                  setState(() => showLoader = true);
                  final data =
                      await _biometricAccessPlugin.captureFingerPrintAsXml(textCtrl.text);
                  resultData = (data);
                  await copyToClipboard(resultData);
                } catch (e, s) {
                  customToast(e.toString());
                  log(s.toString());
                }
                setState(() => showLoader = false);
              }),
            ],
          ),
        ),
        body: Stack(
          children: [
            if (showLoader) const Center(child: CircularProgressIndicator.adaptive()),
            SingleChildScrollView(
              padding: const EdgeInsets.symmetric(horizontal: 20),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  SizedBox(height: responsive.height * .03),
                  Wrap(
                    alignment: WrapAlignment.center,
                    crossAxisAlignment: WrapCrossAlignment.center,
                    children: [
                      FittedBox(
                        child: DropdownButton<RdServiceModel>(
                          hint: const Text(
                            "Discover RDService",
                            style: TextStyle(fontSize: 13),
                          ),
                          value: _biometricAccessPlugin.rdService,
                          items: (rdServiceList ?? []).map((value) {
                            return DropdownMenuItem<RdServiceModel>(
                              value: value,
                              child: Text(value.rdInfo ?? ""),
                            );
                          }).toList(),
                          onChanged: (val) {
                            _biometricAccessPlugin.setRDService = val!;
                            updateUi();
                          },
                        ),
                      ),
                      const SizedBox(width: 30),
                      SizedBox(
                        height: 20,
                        child: Text(
                            style:
                                const TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
                            'Status: ${_biometricAccessPlugin.rdService?.rdStatus?.name ?? "Unavailable"}\n'),
                      ),
                    ],
                  ),
                  const SizedBox(height: 30),
                  ...[
                    const Text(
                      style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
                      'PidOptions:',
                    ),
                    const SizedBox(height: 8),
                    TextField(
                      minLines: 2,
                      maxLines: 4,
                      controller: textCtrl,
                      decoration: const InputDecoration(border: OutlineInputBorder()),
                    ),
                  ],
                  const SizedBox(height: 20),
                  if (resultData != null) ...[
                    const Text(
                      "Device data",
                      style: TextStyle(fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    SelectableText(
                      resultData ?? "",
                      style: const TextStyle(fontSize: 10),
                    ),
                    const SizedBox(height: 30),
                  ]
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> copyToClipboard(String? resultData) async {
    try {
      if (enableClipBoardCoping && resultData != null) {
        await Clipboard.setData(ClipboardData(text: resultData));
        customToast("Copied to Clipboard");
      }
    } catch (e) {
      log(e.toString());
    }
  }

  Widget customButton(String txt, Function() onTap) {
    return Padding(
      padding: const EdgeInsets.all(5.0),
      child: ElevatedButton(
        onPressed: onTap,
        child: Text(
          txt,
          style: const TextStyle(fontSize: 13),
        ),
      ),
    );
  }
}

更多关于Flutter生物识别访问插件biometric_access的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter生物识别访问插件biometric_access的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用biometric_access插件来实现生物识别访问的示例代码。biometric_access插件允许你使用设备的生物识别功能(如指纹、面部识别)来验证用户身份。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加biometric_access依赖:

dependencies:
  flutter:
    sdk: flutter
  biometric_access: ^0.x.x  # 请使用最新版本号

2. 导入包

在你的Dart文件中导入biometric_access包:

import 'package:biometric_access/biometric_access.dart';
import 'package:flutter/material.dart';

3. 配置权限

android/app/src/main/AndroidManifest.xml中添加必要的权限:

<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>

对于iOS,需要在Info.plist中添加描述字符串,例如:

<key>NSFaceIDUsageDescription</key>
<string>我们需要使用Face ID来验证您的身份。</string>
<key>NSFingerprintUsageDescription</key>
<string>我们需要使用Touch ID来验证您的身份。</string>

4. 实现生物识别访问

下面是一个简单的Flutter应用示例,它展示了如何使用biometric_access插件进行生物识别验证:

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Biometric Access Example'),
        ),
        body: Center(
          child: BiometricButton(),
        ),
      ),
    );
  }
}

class BiometricButton extends StatefulWidget {
  @override
  _BiometricButtonState createState() => _BiometricButtonState();
}

class _BiometricButtonState extends State<BiometricButton> {
  final BiometricAuthService biometricAuthService = BiometricAuthService();
  bool isAuthenticated = false;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () async {
        try {
          bool canAuthenticate = await biometricAuthService.canAuthenticate();
          if (canAuthenticate) {
            bool authenticated = await biometricAuthService.authenticate(
              localizedReason: '请验证您的身份以继续。',
              stickyAuth: true, // 是否在用户取消后继续显示认证提示
            );
            setState(() {
              isAuthenticated = authenticated;
            });

            if (authenticated) {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('认证成功!')),
              );
            } else {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('认证失败或取消。')),
              );
            }
          } else {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text('设备不支持生物识别。')),
            );
          }
        } catch (e) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('发生错误: $e')),
          );
        }
      },
      child: Text('验证身份'),
    );
  }
}

5. 运行应用

确保你的Flutter环境已经正确配置,然后运行应用:

flutter run

这个示例应用展示了如何使用biometric_access插件来检查设备是否支持生物识别,并尝试进行生物识别验证。根据验证结果,应用会显示相应的SnackBar消息。

请注意,实际项目中可能需要更复杂的错误处理和用户反馈机制。此外,还要确保你的应用符合相关的隐私政策和用户协议。

回到顶部