Android 9 PieのBiometricPromptをさらっと試した

# 前置き
FingerprintManagerで奮闘した経験を投稿しようと思い復習していましたら、Android Pieでは[deprecated](https://developer.android.com/reference/android/hardware/fingerprint/FingerprintManager)になりました。急遽、復習をやめて予習を始めました。

# BiometricPromptとは
[ここ](https://developers-jp.googleblog.com/2018/06/whats-new-in-android-p-beta.html)で紹介されている説明をご覧ください。要するにAndroid Pieからは指紋認証、顔認証、虹彩認証を統合した認証APIということです。iOSのLAContextもFaceIDが利用出来るので、それに近いと思います。
ちなみに私の愛機P20 ProやGalaxy S8は顔認証や虹彩認証を備えていましたが、サードパーティのアプリでは指紋認証しか出来ませんでした。ここが改善され便利になるということですよね:grinning:
それと引き換えに前述のとおりFingerprintManagerにdeprecatedなりました。

# 準備
こちらで少し試した限りはAndroid Studio 3.1.3では試用出来ないと思います。~~私は[Android Studio 3.3 Canary 2](https://developer.android.com/studio/preview/?hl=ja)で試用してみることにしました。~~また、SDK/AVDにP(API 28)を予め用意しておきます。
Android Pieが正式公開されたので再確認したところAndroid Studio 3.1.4で動作することを確認しました。
<img width="1142" alt="" src="https://qiita-image-store.s3.amazonaws.com/0/240974/d7be813e-7298-bb88-632b-8d76ff3951cd.png"><img width="1066" alt="" src="https://qiita-image-store.s3.amazonaws.com/0/240974/51e51f5c-6d1f-0000-852e-fdb4e03de611.png">
# 使い方
FingerprintManagerを使用したことがある方なら、すぐにご理解頂けると思います。GitHubにもアップロードしておきます。[こちら](https://github.com/devnokiyo/BiometricPromptSample)からどうぞ。
![マイムービー.gif](https://qiita-image-store.s3.amazonaws.com/0/240974/0b75c33e-138d-cfba-e179-04b2bafed062.gif)


パーミッションを追加します。

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

あとはActivityなりFragmentにBiometricPromptをコードを書きます。

```kotlin:MainActivity.kt
package com.devnokiyo.biometricpromptsample

import android.content.DialogInterface
import android.hardware.biometrics.BiometricPrompt
import android.os.Bundle
import android.os.CancellationSignal
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private lateinit var cancelSignal: CancellationSignal

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        cancelSignal = CancellationSignal()
        val builder = BiometricPrompt.Builder(this)
        builder.setTitle("生体認証します")
        builder.setNegativeButton("キャンセル", mainExecutor, DialogInterface.OnClickListener { dialogInterface, i ->
            cancelSignal.cancel()
        })
        builder.build().authenticate(cancelSignal, mainExecutor, object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                when (errorCode) {
                    BiometricPrompt.BIOMETRIC_ERROR_NO_BIOMETRICS ->
                        Toast.makeText(this@MainActivity, "非対応です。", Toast.LENGTH_SHORT).show()
                    else ->
                        Toast.makeText(this@MainActivity, "その他のエラーです。", Toast.LENGTH_SHORT).show()
                }
            }

            override fun onAuthenticationHelp(helpCode: Int, helpString: CharSequence) {
                throw RuntimeException("Stub!")
            }

            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                Toast.makeText(this@MainActivity, "認証成功です。", Toast.LENGTH_SHORT).show()
            }

            override fun onAuthenticationFailed() {
                Toast.makeText(this@MainActivity, "認証失敗です。", Toast.LENGTH_SHORT).show()
            }
        })
    }
}

```

# 所感
FingerprintManagerを利用していたときは、DialogFragmentと併用して開発していました。指紋認証中のダイアログも画面回転に対応したくなってしまったので、いろいろ茨の道を歩みました。しかし、少なくとも現時点ではBiometricPromptは回転には非対応のように見えます。また、認証表示枠の外をタッチすると認証がキャンセルされてしまいます。これを抑制する方法があれば追って調査したいと思います。

# 終わりに
FingerprintManagerも、まだ利用していきます。奮闘した記事はまた今後書きたいと思います。でもdeprecatedになると興味が薄れていくんですよね:sweat_smile: