生体認証ダイアログを表示する

アプリ内の機密情報やプレミアム コンテンツを保護する方法として、顔認証や指紋認証などの生体認証をリクエストする方法があります。このガイドでは、アプリ内で生体認証ログインフローをサポートする方法について説明します。

生体認証を利用できるかチェックする

BiometricManager クラスの canAuthenticate() メソッドを使用することで、BiometricPrompt を呼び出す前にデバイスが生体認証をサポートしているかチェックできます。

このメソッドを呼び出す方法を次のコード スニペットに示します。

Kotlin

    val biometricManager = BiometricManager.from(this)
    when (biometricManager.canAuthenticate()) {
        BiometricManager.BIOMETRIC_SUCCESS ->
            Log.d("App can authenticate using biometrics.")
        BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
            Log.e("No biometric features available on this device.")
        BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
            Log.e("Biometric features are currently unavailable.")
        BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED ->
            Log.e("The user hasn't associated any biometric credentials " +
            "with their account.")
    }
    

Java

    BiometricManager biometricManager = BiometricManager.from(this);
    switch (biometricManager.canAuthenticate()) {
        case BiometricManager.BIOMETRIC_SUCCESS:
            Log.d("App can authenticate using biometrics.");
            break;
        case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
            Log.e("No biometric features available on this device.");
            break;
        case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
            Log.e("Biometric features are currently unavailable.");
            break;
        case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
            Log.e("The user hasn't associated any biometric credentials " +
                "with their account.");
            break;
    }
    

ログイン プロンプトを表示する

ユーザーに生体認証情報の提供をリクエストするシステム プロンプトを表示するには、生体認証ライブラリを使用します。システムが提供するこのダイアログは、ダイアログを使用するアプリの間で一貫しているため、信頼できるユーザー エクスペリエンスを実現します。ダイアログの例を図 1 に示します。

ダイアログのスクリーンショット
図 1: 生体認証をリクエストするシステム ダイアログ

生体認証ライブラリを使用してアプリに生体認証機能を追加する手順は次のとおりです。

  1. アプリの app/build.gradle ファイル内で、生体認証ライブラリに対する依存関係を追加します。

        dependencies {
            implementation 'androidx.biometric:biometric:1.0.0-beta01'
        }
        
  2. 生体認証ログイン ダイアログをホストするアクティビティまたはフラグメントで、次のコード スニペットに示すロジックを使用してダイアログを表示します。

    Kotlin

        private val executor = Executor { }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            // ...
            // Prompt appears when user clicks "Log in"
            val biometricLoginButton: Button = findViewById(R.id.biometric_login)
            biometricLoginButton.setOnClickListener { showBiometricPrompt() }
        }
    
        private fun showBiometricPrompt() {
            val promptInfo = BiometricPrompt.PromptInfo.Builder()
                    .setTitle("Biometric login for my app")
                    .setSubtitle("Log in using your biometric credential")
                    .setNegativeButtonText("Cancel")
                    .build()
    
            val biometricPrompt = BiometricPrompt(this, executor,
                    object : BiometricPrompt.AuthenticationCallback() {
                override fun onAuthenticationError(errorCode: Int,
                        errString: CharSequence) {
                    super.onAuthenticationError(errorCode, errString)
                    Toast.makeText(applicationContext,
                        "Authentication error: $errString", Toast.LENGTH_SHORT)
                        .show()
                }
    
                override fun onAuthenticationSucceeded(
                        result: BiometricPrompt.AuthenticationResult) {
                    super.onAuthenticationSucceeded(result)
                    val authenticatedCryptoObject: BiometricPrompt.CryptoObject =
                            result.getCryptoObject()
                    // User has verified the signature, cipher, or message
                    // authentication code (MAC) associated with the crypto object,
                    // so you can use it in your app's crypto-driven workflows.
                }
    
                override fun onAuthenticationFailed() {
                    super.onAuthenticationFailed()
                    Toast.makeText(applicationContext, "Authentication failed",
                        Toast.LENGTH_SHORT)
                        .show()
                }
            })
    
            // Displays the "log in" prompt.
            biometricPrompt.authenticate(promptInfo)
        }
        

    Java

        private Handler handler = new Handler();
    
        private Executor executor = new Executor() {
            @Override
            public void execute(Runnable command) {
                handler.post(command);
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // ...
            // Prompt appears when user clicks "Log in"
            Button biometricLoginButton = findViewById(R.id.biometric_login);
            biometricLoginButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    showBiometricPrompt();
                }
            });
        }
    
        private void showBiometricPrompt() {
            BiometricPrompt.PromptInfo promptInfo =
                    new BiometricPrompt.PromptInfo.Builder()
                    .setTitle("Biometric login for my app")
                    .setSubtitle("Log in using your biometric credential")
                    .setNegativeButtonText("Cancel")
                    .build();
    
            BiometricPrompt biometricPrompt = new BiometricPrompt(MainActivity.this,
                    executor, new BiometricPrompt.AuthenticationCallback() {
                @Override
                public void onAuthenticationError(int errorCode,
                        @NonNull CharSequence errString) {
                    super.onAuthenticationError(errorCode, errString);
                    Toast.makeText(getApplicationContext(),
                        "Authentication error: " + errString, Toast.LENGTH_SHORT)
                        .show();
                }
    
                @Override
                public void onAuthenticationSucceeded(
                        @NonNull BiometricPrompt.AuthenticationResult result) {
                    super.onAuthenticationSucceeded(result);
                    BiometricPrompt.CryptoObject authenticatedCryptoObject =
                            result.getCryptoObject();
                    // User has verified the signature, cipher, or message
                    // authentication code (MAC) associated with the crypto object,
                    // so you can use it in your app's crypto-driven workflows.
                }
    
                @Override
                public void onAuthenticationFailed() {
                    super.onAuthenticationFailed();
                    Toast.makeText(getApplicationContext(), "Authentication failed",
                        Toast.LENGTH_SHORT)
                        .show();
                }
            });
    
            // Displays the "log in" prompt.
            biometricPrompt.authenticate(promptInfo);
        }
        

明示的なユーザー アクションを求めずに認証する

デフォルトでは、生体認証情報が受け入れられた後、ユーザーは「ボタンを押す」といった特定のアクションを実行するよう求められます。この構成は、購入など、慎重を要するアクションやリスクの高いアクションを確定するダイアログをアプリ内で表示する場合に適しています。

他方、低リスクのアクションに対する生体認証ダイアログをアプリ内で表示する場合は、「ユーザーによる認証アクションは必要ない」というヒントをシステムに伝えることができます。このヒントにより、ユーザーは、顔や虹彩に基づく認識などの受動的モダリティを使用して再認証を行った後、アプリのコンテンツをすばやく表示することができます。このヒントを提供するには、setConfirmationRequired() メソッドに false を渡します。

同じダイアログの 2 つのバージョンを図 2 に示します。1 つのバージョンでは明示的なユーザー アクションが必要で、もう 1 つのバージョンでは必要ありません。

ダイアログのスクリーンショット ダイアログのスクリーンショット
図 2: ユーザー確認なしの顔認証(上)とユーザー確認ありの顔認証(下)

認証プロセスを完了するうえで明示的なユーザー アクションを要求しないダイアログを表示する方法を、次のコード スニペットに示します。

Kotlin

    // Allows user to authenticate without performing an action, such as pressing a
    // button, after their biometric credential is accepted.
    val promptInfo = BiometricPrompt.PromptInfo.Builder()
            .setTitle("Biometric login for my app")
            .setSubtitle("Log in using your biometric credential")
            .setNegativeButtonText("Cancel")
            .setConfirmationRequired(false)
            .build()
    

Java

    // Allows user to authenticate without performing an action, such as pressing a
    // button, after their biometric credential is accepted.
    BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
            .setTitle("Biometric login for my app")
            .setSubtitle("Log in using your biometric credential")
            .setNegativeButtonText("Cancel")
            .setConfirmationRequired(false)
            .build();
    

非生体認証情報へのフォールバックを許可する

ユーザーが生体認証情報を使用した認証を実行できない場合、setDeviceCredentialAllowed() メソッドに true を渡すことで、デバイスの PIN や、パターン、パスワードを使用した認証を許可できます。このフォールバック サポートを提供する方法を次のコード スニペットに示します。

Kotlin

    // Allows user to authenticate using a PIN, pattern, or password.
    val promptInfo = BiometricPrompt.PromptInfo.Builder()
            .setTitle("Biometric login for my app")
            .setSubtitle("Log in using your biometric credential")
            .setNegativeButtonText("Cancel")
            .setDeviceCredentialAllowed(true)
            .build()
    

Java

    // Allows user to authenticate using a PIN, pattern, or password.
    BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
            .setTitle("Biometric login for my app")
            .setSubtitle("Log in using your biometric credential")
            .setNegativeButtonText("Cancel")
            .setDeviceCredentialAllowed(true)
            .build();