LoginSignup
11
10

More than 3 years have passed since last update.

BiometricPromptをAndroid Mから使う

Last updated at Posted at 2019-05-23

はじめに

Android PからBiometricPromptというクラスが追加されました。これはバイオメトリック(生体認証)に関連する処理を引き受けてくれるもので、これを使うと今までアプリ側で実装していたダイアログの表示をシステム側で提供してくれるようになります。また、指紋認証だけでなく、虹彩認証や顔認証にも対応しており、ユーザが選択した方式を判別し、適切なダイアログを表示してくれるという優れものです。それに伴い、従来のFingerprintManagerはAndroid API 28より非推奨になりました。こんな便利な物を使わない手がないと、早速移行してみようと思ったのですが、BiometricPromptの最低サポートがAndroid API 28からなので、Min SDKバージョンが28より低い場合は完全に移行することが出来ません😇

今回はこの問題の解決方法と実装の仕方を簡単にまとめました。

解決方法

いきなり結論からです。android.hardware.biometrics.BiometricPromptではなくandroidx.biometrics.BiometricsPromptを使います。ただし、AndroidXを使うので従来のAndroid Support Libraryとは共存出来ない点に注意してください。

実装方法

まず、依存関係をGradleに追加します。

dependencies {
    ...
    implementation 'androidx.biometric:biometric:1.0.0-alpha04'
}

生体認証を使う為、Android Manifestにパーミッションを追加します。

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

最後に認証ダイアログを呼び出す処理を実装します。

val executor = Executors.newSingleThreadExecutor()

val biometricPrompt = BiometricPrompt(this, executor,
    object : BiometricPrompt.AuthenticationCallback() {
        override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
            super.onAuthenticationError(errorCode, errString)
            Log.d("Biometric", "Error")
        }

        override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
            super.onAuthenticationSucceeded(result)
            Log.d("Biometric", "Succeeded")
        }

        override fun onAuthenticationFailed() {
            super.onAuthenticationFailed()
            Log.d("Biometric", "Failed")
        }
    })

val promptInfo = BiometricPrompt.PromptInfo.Builder()
    .setTitle("Title")
    .setSubtitle("Sub title")
    .setDescription("Description")
    .setNegativeButtonText("Cancel")
    .build()

biometricPrompt.authenticate(promptInfo)

これだけで、認証ダイアログを表示できます。

i ii iii
img_1 img_2 img_3

軽くコードの説明をします。

認証の結果を受け取るのはBiometricPromptインスタンス生成時に渡しているBiometricPrompt.AuthenticationCallbackになります。

関数名 内容
onAuthenticationError エラーが発生して操作が完了された時に呼び出される
onAuthenticationSucceeded 生体認証が成功した時に呼び出される
onAuthenticationFailed 生体認証が有効だが認識されない時に呼び出される

キャンセルボタンのイベントはonAuthenticationErrorメソッドでerrorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTONと比較することでキャッチすることができます。BIOMETRIC_ERROR定数に関しては以下のものがあります。

定数名 内容
ERROR_CANCELED 生体認証が利用できない為、操作がキャンセルされた
ERROR_HW_NOT_PRESENT 端末に生体センサが搭載されていない
ERROR_HW_UNAVAILABLE 端末が利用できない
ERROR_LOCKOUT 生体認証に5回失敗した
ERROR_LOCKOUT_PERMANENT ERROR_LOCKOUTの発生回数が多すぎる為、操作がキャンセルされた
ERROR_NEGATIVE_BUTTON ユーザがネガティブボタン(ダイアログのキャンセルボタン)を押した
ERROR_NO_BIOMETRICS ユーザの生体認証情報が登録されていない
ERROR_NO_SPACE 操作を完了するのに十分なストレージが用意されていない
ERROR_TIMEOUT 認証を実行するまでの時間が長すぎる為、タイムアウトが発生した
ERROR_UNABLE_TO_PROCESS 生体センサが画像を処理できない
ERROR_USER_CANCELED ユーザが操作をキャンセルした
ERROR_VENDOR いずれのエラーにも該当しない

ERROR_CANCELEDは具体的に端末で使用するユーザを切り替えた場合(おそらく生体認証情報がリセットされる)や端末がロックされている場合、他のアプリが生体認証を利用中の場合に発生するみたいです。ERROR_HW_UNAVAILABLEはどういったタイミングで発生するのかがわかりませんでした。ERROR_LOCKOUTが発生した場合、30秒後に再度認証可能になるみたいです(知らなかった:sweat_smile:)。ERROR_UNABLE_TO_PROCESSはおそらく虹彩認証や顔認証などのカメラを利用する場合に発生するのかと思います。

認証ダイアログのカスタマイズはBiometricPrompt.PromptInfo.Builderで行います。指定できる項目は以下の通りです。

関数名 内容
setTitle タイトルを設定(必須)
setSubtitle サブタイトルを設定(任意)
setDescription 説明を設定(任意)
setNegativeButtonText ネガティブボタンに表示されるテキストを設定(必須)

ダイアログの画像やメッセージといった細かい部分は流石に設定できないみたいですね。

また、認証ダイアログを表示する前に

private fun isBiometricEnabled(context: Context): Boolean =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        && context.getSystemService(KeyguardManager::class.java).isKeyguardSecure
        && context.packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)

のように端末が生体認証を利用出来るか判定した方が良さそうです。

まとめ

足早にですがBiometricPromptをAndroid Mから使う方法を解説しました。本来はBuild.VERSION.SDK_INTでAndroidのバージョンを取得してFingerprintManagerとの処理を切り分けるのが行儀がいいのですが、ぶっちゃけめんどくさい効率的に出来るのであれば致し方ないのかなと。また、虹彩認証と顔認証については、次期バージョンのAndroid Q(API 29)から利用出来るみたいです。今回のデモアプリをGitHubに公開しておきますので、参考にしていただければ嬉しいです。では。

参考文献

11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10