生体認証

Kotlin + Jetpack Compose では、生体認証そのものは Jetpack Biometric ライブラリを使用し、Compose から呼び出す形が一般的です。

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

dependencies {
    implementation("androidx.biometric:biometric:1.2.0-alpha05")
}

生体認証マネージャークラス

再利用しやすいようにクラス化すると次のようになります。


Composeから利用


AndroidManifest

特別な権限は通常不要ですが、機能宣言を追加できます。

<uses-feature
    android:name="android.hardware.fingerprint"
    android:required="false" />

ViewModelと組み合わせる場合

Composeでは認証結果をStateFlowに流す構成がよく使われます。

sealed interface AuthState {
    data object Idle : AuthState
    data object Success : AuthState
    data class Error(val message: String) : AuthState
}
class AuthViewModel : ViewModel() {

    private val _authState =
        MutableStateFlow<AuthState>(AuthState.Idle)

    val authState = _authState.asStateFlow()

    fun onAuthSuccess() {
        _authState.value = AuthState.Success
    }

    fun onAuthError(message: String) {
        _authState.value = AuthState.Error(message)
    }
}

Compose側では collectAsState() で監視します。

この構成にすると、認証処理は BiometricAuthManager、状態管理は ViewModel、UIはComposeという責務分離ができ、保守しやすくなります。

SwiftUIのように自動で認証画面は出ない

Jetpack Compose + Android の BiometricPrompt は、SwiftUI の LocalAuthentication のように画面表示まで自動では行いません。

iOSでは例えば:

let context = LAContext()

context.evaluatePolicy(
    .deviceOwnerAuthenticationWithBiometrics,
    localizedReason: "ログインします"
) { success, error in
    ...
}

この1行の呼び出しで Face ID / Touch ID ダイアログが表示されます。

一方 Android では:

biometricPrompt.authenticate(promptInfo)

を呼んだ瞬間にシステムの生体認証ダイアログが表示されますが、その前に

  • BiometricPrompt
  • PromptInfo
  • AuthenticationCallback

を作成する必要があります。

つまり Android は

BiometricPrompt作成
↓
PromptInfo作成
↓
authenticate()
↓
システム認証画面表示

という流れです。


SwiftUI に近い使い勝手にしたい場合は、自分でラッパークラスを作ります。

Compose側では

と書けるので、SwiftUI の

let success = await authenticate()

にかなり近い感覚になります。

ちなみに Android 14以降でも、Composeに「Face IDボタンを置いたら自動で認証UIが出る」ような仕組みはなく、必ず BiometricPrompt.authenticate() を呼び出してシステムダイアログを表示します。これはセキュリティ上、アプリが勝手に認証画面を出し続けることを防ぐためでもあります。

タイトルとURLをコピーしました