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

Flutter中如何检测手机是否新增指纹?

在Flutter中检测是否新增指纹/生物特征的方法

方案1:对比生物特征类型列表(基础版)

使用官方推荐的local_auth插件结合shared_preferences存储历史生物特征数据,通过对比当前与历史的生物特征类型,判断是否有新增/删除操作。

步骤:

  1. 添加依赖到pubspec.yaml:
dependencies:
  local_auth: ^2.1.7
  shared_preferences: ^2.2.2
  1. 实现检测逻辑:
import 'package:flutter/material.dart';
import 'package:local_auth/local_auth.dart';
import 'package:shared_preferences/shared_preferences.dart';

class BiometricChangeChecker {
  final _localAuth = LocalAuthentication();
  final _savedBiometricsKey = 'previous_biometrics';

  Future<bool> checkBiometricChanges() async {
    // 获取当前可用的生物特征类型
    List<BiometricType> currentTypes = [];
    try {
      if (await _localAuth.canCheckBiometrics) {
        currentTypes = await _localAuth.getAvailableBiometrics();
      }
    } catch (e) {
      print('获取生物特征失败: $e');
      return false;
    }

    // 转换为字符串列表便于存储和对比
    final currentTypeStrs = currentTypes.map((type) {
      switch (type) {
        case BiometricType.fingerprint:
          return 'fingerprint';
        case BiometricType.face:
          return 'face';
        case BiometricType.iris:
          return 'iris';
        default:
          return 'unknown';
      }
    }).toList();

    // 读取历史数据
    final prefs = await SharedPreferences.getInstance();
    final savedTypeStrs = prefs.getStringList(_savedBiometricsKey);

    // 判断是否有变化
    final hasChanged = !listEquals(savedTypeStrs, currentTypeStrs);

    // 更新历史数据
    if (hasChanged) {
      await prefs.setStringList(_savedBiometricsKey, currentTypeStrs);
    }

    return hasChanged;
  }
}

// 使用示例
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final checker = BiometricChangeChecker();
  final changed = await checker.checkBiometricChanges();
  if (changed) {
    print('生物特征已变更(可能新增/删除了指纹/面容)');
    // 这里可以执行重新验证用户、提示用户等逻辑
  }
}

方案2:检测同类型生物特征数量变化(进阶版)

如果需要检测同类型内的新增/删除(比如新增了一个指纹,而生物特征类型还是指纹),上面的方法无法实现,因为local_auth不会返回具体的指纹数量。此时需要针对Android和iOS分别处理:

  • Android端:利用KeyStore创建与生物特征绑定的密钥,当用户新增/删除指纹时,该密钥会失效。可以通过尝试使用密钥签名/加密来判断是否发生变更。
  • iOS端:调用LAContext的evaluatePolicy方法时,若用户新增了指纹,首次验证可能会要求输入设备密码,或者通过监听LAErrorBiometryNotAvailable等错误来间接判断。

以下是Android端的实现示例(通过Platform Channel对接原生代码):

Flutter端代码:

import 'package:flutter/services.dart';

class BiometricTemplateChecker {
  static const MethodChannel _channel = MethodChannel('biometric_template_checker');

  Future<bool> hasBiometricTemplatesChanged() async {
    try {
      return await _channel.invokeMethod('checkTemplateChanges');
    } on PlatformException catch (e) {
      print('检测失败: ${e.message}');
      return false;
    }
  }
}

Android原生代码(MainActivity.kt):

import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.security.KeyStore
import javax.crypto.Cipher
import javax.crypto.KeyGenerator

class MainActivity : FlutterActivity() {
    private val CHANNEL = "biometric_template_checker"
    private val KEY_NAME = "biometric_key"

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "checkTemplateChanges") {
                val changed = checkBiometricTemplatesChanged()
                result.success(changed)
            } else {
                result.notImplemented()
            }
        }
    }

    private fun checkBiometricTemplatesChanged(): Boolean {
        val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
        val key = keyStore.getKey(KEY_NAME, null) ?: run {
            // 首次运行,创建密钥
            val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
            val spec = KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setInvalidatedByBiometricEnrollment(true) // 生物特征变更时失效密钥
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .build()
            keyGenerator.init(spec)
            keyGenerator.generateKey()
            return false
        }

        // 尝试初始化Cipher,失败则说明密钥已失效(生物特征变更)
        return try {
            val cipher = Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}")
            cipher.init(Cipher.ENCRYPT_MODE, key)
            false
        } catch (e: Exception) {
            // 删除失效密钥,重新创建
            keyStore.deleteEntry(KEY_NAME)
            true
        }
    }
}

注意事项

  • 方案1仅能检测生物特征类型的变化(比如从无指纹到有指纹,或从指纹到指纹+面容),无法检测同类型内的数量变化。
  • 方案2可以检测同类型内的变更,但需要编写原生代码,兼容性需要针对不同Android版本和iOS版本测试。
  • 无论哪种方案,都需要在应用启动时或关键操作前执行检测,确保及时发现生物特征变更。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:37:45