You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中获取设备具体的生物识别认证类型?

解决local_auth无法返回具体生物识别类型的问题

核心原因

  1. Android系统权限限制:从Android 10(API 29)开始,Google收紧了生物识别信息的获取权限,系统不再允许应用直接查询具体的生物识别类型(如指纹、面部),仅返回BiometricType.strong或BiometricType.weak的分类。这是系统层面的限制,并非local_auth包的功能缺陷。
  2. 模拟器局限性:Android Studio模拟器的指纹模拟功能,在系统层面仅被标记为strong级生物识别,不会返回BiometricType.fingerprint具体枚举值。

解决方案

1. 针对Android低版本(API <29)

在Android 9及以下设备上,local_auth可以正常返回BiometricType.fingerprint或BiometricType.face,但需确保已在AndroidManifest.xml中添加对应的权限:

<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-feature android:name="android.hardware.fingerprint" android:required="false" />

2. Android 10+设备(API ≥29)

如需获取具体生物识别类型,需通过原生代码扩展实现,以下是通过MethodChannel调用Android原生API的示例:

步骤1:修改Flutter代码添加MethodChannel

import 'package:flutter/material.dart';
import 'package:local_auth/local_auth.dart';
import 'package:flutter/services.dart';

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

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

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final LocalAuthentication _localAuth = LocalAuthentication();
  List<BiometricType> _availableBiometrics = [];
  String _specificBiometric = "";
  static const MethodChannel _channel = MethodChannel('biometric_channel');

  @override
  void initState() {
    super.initState();
    _checkBiometrics();
    _getSpecificBiometricType();
  }

  Future<void> _checkBiometrics() async {
    try {
      _availableBiometrics = await _localAuth.getAvailableBiometrics();
    } catch (e) {
      print("Error checking biometrics availability: $e");
      return;
    }
    setState(() {});
  }

  Future<void> _getSpecificBiometricType() async {
    try {
      final String result = await _channel.invokeMethod('getSpecificBiometric');
      setState(() {
        _specificBiometric = result;
      });
    } on PlatformException catch (e) {
      print("Error getting specific biometric: ${e.message}");
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Biometric Authentication')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text('Available Biometric Types (local_auth):'),
              for (var type in _availableBiometrics) Text(type.toString()),
              const SizedBox(height: 20),
              const Text('Specific Biometric Type (Native):'),
              Text(_specificBiometric.isNotEmpty ? _specificBiometric : 'Not available'),
            ],
          ),
        ),
      ),
    );
  }
}

步骤2:编写Android原生代码

在android/app/src/main/kotlin/[你的包名]/MainActivity.kt中添加通道处理:

import android.content.pm.PackageManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "biometric_channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "getSpecificBiometric") {
                val biometricType = getSpecificBiometricType()
                result.success(biometricType)
            } else {
                result.notImplemented()
            }
        }
    }

    private fun getSpecificBiometricType(): String {
        val packageManager = packageManager
        val hasFingerprint = packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
        val hasFace = packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)
        
        return when {
            hasFace && hasFingerprint -> "Fingerprint + Face"
            hasFace -> "Face"
            hasFingerprint -> "Fingerprint"
            else -> "No specific biometric found"
        }
    }
}

3. iOS平台处理

在iOS上,local_auth包可以正常返回BiometricType.face或BiometricType.fingerprint,只需确保Info.plist中已添加对应的权限描述:

<key>NSFaceIDUsageDescription</key>
<string>需要使用FaceID进行身份验证</string>

4. 测试建议

  • 使用真实Android设备测试:Android 9及以下设备可直接通过local_auth获取具体类型;Android 10+设备需依赖上述原生扩展方案。
  • 模拟器仅用于基础功能验证,无法模拟真实设备的具体生物识别类型返回逻辑。

内容的提问来源于stack exchange,提问作者sleeping_in

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:15:53