點燈坊

失くすものさえない今が強くなるチャンスよ

local_auth 偵測使用生物辨識的可用性

Sam Xiao's Avatar 2024-10-15

生物辨識登入 已經成為手機登入的標配,local_auth 可實現 Android、iOS、macOS 與 Windows 的 跨平台 生物辨識登入。

Version

Flutter 3.24
local_auth 3.2

local_auth

$ flutter pub add local_auth
  • 安裝 local_auth package

Android

Activity

android/app/src/main/java/com/example/MainActivity.java

package com.fii.sks.user;

import io.flutter.embedding.android.FlutterFragmentActivity;

public class MainActivity extends FlutterFragmentActivity {
}
  • import io.flutter.embedding.android.FlutterFragmentActivity
  • MainActivity 改繼承 FlutterFragmentActivity

android/app/src/main/kotlin/com/example/flutter_lab/MainActivity.kotlin

package com.example.flutter_lab

import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity()
  • import io.flutter.embedding.android.FlutterFragmentActivity
  • MainActivity 改繼承 FlutterFragmentActivity

Permission

android/app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.USE_BIOMETRIC"/>
</manifest>
  • <manifest> 下新增 <uses-permission> 啟用 USE_BIOMETRIC

iOS

ios/Runner/Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>NSFaceIDUsageDescription</key>
  <string>Why is my app authenticating using face id?</string>
</dict>
</plist>
  • <dict> 下新增 <key><string>

Flutter

overview

local_auth

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

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

  
  State<Home> createState() {
    return _Home();
  }
}

class _Home extends State<Home> {
  final _auth = LocalAuthentication();
  var _isAuthAvailable = false;

  Future<bool> _hasBiometrics() async {
    var canCheckBiometrics = false;
    var isDeviceSupported = false;

    try {
      canCheckBiometrics = await _auth.canCheckBiometrics;
      isDeviceSupported = await _auth.isDeviceSupported();
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print(e);
      }
      return false;
    }

    return canCheckBiometrics && isDeviceSupported;
  }

  
  Widget build(BuildContext context) {
    var appBar = AppBar(title: const Text('local_auth'));

    var elevatedButton = ElevatedButton(
        onPressed: () async {
          var isAuthAvailable = await _hasBiometrics();

          setState(() {
            _isAuthAvailable = isAuthAvailable;
          });
        },
        child: const Text('auth.canCheckBiometrics'));

    var body = Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            elevatedButton,
            Text('Can check biometrics: $_isAuthAvailable'),
          ],
        ));

    return Scaffold(
      appBar: appBar,
      body: body,
    );
  }
}

Line 16

final _auth = LocalAuthentication();
  • _auth:建立 local_auth object

Line 17

var _isAuthAvailable = false;
  • _isAuthAvailable:顯示是否有 可用 的生物辨識

Line 19

Future<bool> _hasBiometrics() async {
  var canCheckBiometrics = false;
  var isDeviceSupported = false;

  try {
    canCheckBiometrics = await _auth.canCheckBiometrics;
    isDeviceSupported = await _auth.isDeviceSupported();
  } on PlatformException catch (e) {
    if (kDebugMode) {
      print(e);
    }
    return false;
  }

  return canCheckBiometrics && isDeviceSupported;
}
  • 偵測是否有可用的生物辨識

Line 24

canCheckBiometrics = await _auth.canCheckBiometrics;
  • auth.canCheckBiometrics硬體 是否支援生物辨識

Line 25

isDeviceSupported = await _auth.isDeviceSupported();
  • auth.isDeviceSupported用戶 是否有設定生物辨識

Line 33

return canCheckBiometrics && isDeviceSupported;
  • canCheckBiometricsisDeviceSupported 都為 true 時,才表示能啟動生物辨識登入

Line 55

Text('Can check biometrics: $_isAuthAvailable'),
  • 顯示偵測結果

Line 41

onPressed: () async {
  var isAuthAvailable = await _hasBiometrics();

  setState(() {
    _isAuthAvailable = isAuthAvailable;
  });
},
  • 將偵測結果寫入 _isAuthAvailable state

Conclusion

  • canCheckBiometricsisDeviceSupported 單從字面很難清楚知道其背後意義,簡單說 canCheckBiometrics 是判斷硬體是否 有支援,而 isDeviceSupported 試判斷 用戶是否 已設定
  • canCheckBiometricsisDeviceSupported 都為 true 時,才能成功使用生物辨識登入

Reference

pub.dev, local_auth 2.3.0
Flutter Packages, local_auth
Vinayak, Enabling Local Authentication for your Flutter Application
Hussain Mustafa, Flutter Local Authentication Tutorial