[Flutter/Dart]端末の指紋認証システムでロック解除するアプリの作成方法

2020年11月15日

Flutter で iOS や Android の端末に搭載されている生体認証(指紋)を使ってロックを解除できるアプリを作る方法についてです。

パスコードと生体認証で保護されたアプリ

生体認証を導入するには、パッケージ flutter_lock_screen が便利です。

指紋認証のためのパッケージをインストール

flutter_lock_screen は、パッケージ local_auth に依存しているため、これも同時にインストールします。

プロジェクトの pubspec.yaml に以下の dependencies に以下のように記載します。

dependencies:
  local_auth: ^0.6.3+4
  flutter_lock_screen: ^1.0.8
  ...

(バージョン番号は将来変わる可能性があります)

サンプルコードと画像リソース

インストールが完了したら、これらを利用する Dart のソースファイルに忘れずにインポートします。

import 'package:local_auth/local_auth.dart';
import 'package:flutter_lock_screen/flutter_lock_screen.dart';

実際に指紋やパスコードによるロック解除を行うクラスの例を以下に記載します。ほとんどflutter_lock_screenのサンプルと同じものですが、一部変更しています。

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

class PassCodeScreen extends StatefulWidget {
  PassCodeScreen({Key key}) : super(key: key);

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

class _PassCodeScreenState extends State<PassCodeScreen> {
  bool isFingerprint = false;

  Future<Null> biometrics() async {
    final LocalAuthentication auth = LocalAuthentication();
    bool authenticated = false;

    try {
      authenticated = await auth.authenticateWithBiometrics(
          localizedReason: 'Scan your fingerprint to authenticate',
          useErrorDialogs: true,
          stickyAuth: false);
    } on PlatformException catch (e) {
      print(e);
    }
    if (!mounted) return;
    if (authenticated) {
      setState(() {
        isFingerprint = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    var myPass = [1, 2, 3, 4];
    return LockScreen(
        title: "パスワードを入力",
        passLength: myPass.length,
        bgImage: "images/bg.jpg",
        fingerPrintImage: "images/fingerprint.png",
        showFingerPass: true,
        fingerFunction: biometrics,
        fingerVerify: isFingerprint,
        borderColor: Colors.white,
        showWrongPassDialog: true,
        wrongPassContent: "再度入力してください",
        wrongPassTitle: "失敗",
        wrongPassCancelButtonText: "Cancel",
        passCodeVerify: (passcode) async {
          for (int i = 0; i < myPass.length; i++) {
            if (passcode[i] != myPass[i]) {
              return false;
            }
          }

          return true;
        },
        onSuccess: () {
          Navigator.of(context).pushReplacement(
              MaterialPageRoute(builder: (BuildContext context) {
            return [認証後に開くWidgetを指定];
          }));
        });
  }
}

プロジェクトにフォルダ images を作成し、使用する画像(bg.jpg、fingerprint.png)を入れます。画像ファイルはこちらからダウンロードするか、自分で用意したものを使用してください。

画像を読み込むためには pubspec.yaml の assets にもファイルパスを書き込みます。

assets:
- images/bg.jpg
- images/fingerprint.png
# または、ディレクトリごと
# - images/

OSごとの処理

iOS の場合、顔認証を使用する際には Info.plist に以下を記載します。

<key>NSFaceIDUsageDescription</key>
<string>FaceIDを使用する理由をここに書く</string>

Android の場合、AndroidManifest.xml の manifest タグ内に生体認証を使うためのパーミッションを記載します。

ドキュメントでは USE_FINGERPRINT を記載するよう指示されていましたが API level 28 以降は非推奨なので USE_BIOMETRIC を使用します。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.app">
...
    <uses-permission android:name="android.permission.USE_BIOMETRIC"/>
    <!-- 非推奨 <uses-permission android:name="android.permission.USE_FINGERPRINT"/> -->
</manifest>

そして、MainActivity.kt において FlutterActivity から FlutterFragmentActivity を使用するように変更します。

package パッケージ名

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterFragmentActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    }
}

エディタ上では赤線で警告が表示されるかもしれませんが、無視して構いません。

これを行わないと以下のエラーが実行時に発生します。

PlatformException(no_fragment_activity, local_auth plugin requires activity to be a FragmentActivity., null, null)

また、上記の設定後に以下のようなエラーが出ることがあります。

Unhandled Exception: MissingPluginException(No implementation found for method authenticateWithBiometrics on channel plugins.flutter.io/local_auth)

この場合、以下の三つを試してみてください。

  • "Android Studio"の再起動
  • "flutter clean"のコマンド
  • スマホにインストールしたテストアプリの完全削除

動作例

以上で設定が完了しました。実際に動かしてみると、パスコード入力画面が開きます。

パスコードと指紋認証のロックを搭載したアプリのサンプル

左側にある指紋のマークをタップすると、指紋認証の画面が開きます。

(スクリーンショットの撮影はシステムで禁止されていました)

ロックを解除すると、指定したウィジェットが立ち上がります。

以上、指紋認証でロックを解除できるアプリの作成方法でした。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です