MobileAndroidIntegrating Fingerprint Authentication Into Your App

Integrating Fingerprint Authentication Into Your App

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

As more and more private messages or financial transactions are communicated through our mobile devices, security concerns are rising at a fast pace. Different methods are being used for this purpose, including pins, passwords, security questions, one-time text messages, face recognition, fingerprints, and many others. This tutorial tries to focus on introducing the fingerprint authentication included in the Android APIs. It is fast, simple, and a very commonly used feature nowadays.

Starting from Android 9.0 (SDK 28 with a code name “Pie”), Google includes a BiometricPrompt API for software developers to integrate biometric authentication into their apps in a handy and modular fashion. As of now, it only includes fingerprint authentication, but there will be upcoming updates and releases for other biometric modalities, such as face, iris, and so on. This tutorial will briefly show where the package is and how it is used on the device from user’s perspective. Then, as a software developer, we will detect if the biometric authentication API is supported and if the fingerprint sensor hardware exists on the device. Finally, we will check through the requirements and illustrate how to utilize the API through the implementation of a working example.

Where and How is Fingerprint Authentication Used on Your Mobile Device?

Before we start implementing any software with fingerprint authentication, let us take a look where we can locate its use case on Android devices. Use the system menu or click the “Settings” app icon. Under “Security and location,” you can find the “Imprint” tab with an indication of how many fingerprints are currently set up and available on the device, as shown in Figure 1. Because I have an Android Pixel phone, my tab specifically shows “Pixel Imprint;” some others might see “Nexus Imprint.” If you want to add a new fingerprint, the screenshot as seen in Figure 2 will guide you through the steps to interact and save the results with on-screen instructions. When you have any fingerprints stored on your device, the next time you can simply use them to open the device in a convenient way. For electronic payments, some secure locking mechanism must be in place before mobile devices can be used for that purpose.

Available Fingerprints
Figure 1: Available Fingerprints

Adding a New Fingerprint
Figure 2: Adding a New Fingerprint

How to Detect if a Mobile Device Supports Fingerprint Authentication

First, we need to check if the fingerprint sensor hardware is available. Secondly, if the hardware does indeed exist, we should check whether any fingerprints are set up and enrolled or not. Before you can get access to the hardware for any further actions, your app needs to ask for permissions and specify through AndroidManifest.xml, to be described in the next section. For now, checking if we can perform fingerprint authentication, the code is shown in Listing 1.

public class BioAuthActivity extends AppCompatActivity {
   TextView tvstatus;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.activity_main);

      // This is to display the status message
      tvstatus = (TextView)findViewById(R.id.tv1);

      if (ActivityCompat.checkSelfPermission(this,
         Manifest.permission.USE_BIOMETRIC) != PackageManager
            .PERMISSION_GRANTED) {
               tvstatus.setText("Step 1: Biometric authentication
               permission not granted.");
      } else {
            FingerprintManagerCompat fmc =
               FingerprintManagerCompat.from(this);

            if (!fmc.isHardwareDetected()) {
                tvstatus.setText("Step 1: There is no fingerprint
                sensor hardware found.");
            } else if (!fmc.hasEnrolledFingerprints()) {
                tvstatus.setText("Step 1: There are no fingerprints
                   currently enrolled.");
            } else {
                tvstatus.setText("Step 1: Fingerprint
                   authentication is ready for testing.");
                ...
            }
      }
   }
   ...
}

Listing 1: Fingerprint Authentication Availability Check

BiometricPrompt API and Permission Requirements

The followings are recommendations with the current BiometricPrompt API:

  • android.hardware.biometrics.BiometricPrompt: After Android 9.0, you are recommended to use this API instead of the deprecated android.hardware.fingerprint.FingerprintManager.
  • The related supporting library no longer needs to be specified or included in the gradle file with this API because it already comes with the platform.
  • android.permission.USE_BIOMETRIC: This permission should be used after Android 9.0 instead of the deprecated android.permission.USE_FINGERPRINT in the configuration file AndroidManifest.xml. However, to check the fingerprint sensor hardware in our example, FingerprintManagerCompat still seems to require this permission and at the moment I don’t know of a better way of doing this. Android uses the Fingerprint Hardware Abstraction Layer (HAL) to connect to a vendor-specific library and fingerprint hardware, so please see the reference section for more details.

Example Walk-through

Our example is shown in Listing 2. At the beginning, we check the availability of the fingerprint authentication before performing other tasks. Then, with BiometricPrompt, we set up the general dialog description pertaining to the app’s purpose. An event listener in CancellationSignal() is provided to respond to the cancellation message. BiometricPrompt.AuthenticationCallback() needs to be implemented to accommodate the possible results which are captured in onAuthenticationError(), onAuthenticationHelp(), onAuthenticationFailed(), and onAuthenticationSucceeded().

Sample results after this software are illustrated in Figure 3, Figure 4, and Figure 5.

public class BioAuthActivity extends AppCompatActivity {
   TextView tvstatus;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.activity_main);

      // This is to display the status message
      tvstatus = (TextView)findViewById(R.id.tv1);

      if (ActivityCompat.checkSelfPermission(this,
         Manifest.permission.USE_BIOMETRIC) != PackageManager
               .PERMISSION_GRANTED) {
            tvstatus.setText("Step 1: Biometric authentication
               permission not granted.");
      } else {
         FingerprintManagerCompat fmc =
            FingerprintManagerCompat.from(this);

         if (!fmc.isHardwareDetected()) {
            tvstatus.setText("Step 1: There is no fingerprint
               sensor hardware found.");
         } else if (!fmc.hasEnrolledFingerprints()) {
            tvstatus.setText("Step 1: There are no fingerprints
               currently enrolled.");
         } else {
            tvstatus.setText("Step 1: Fingerprint authentication
               is ready for testing.");

            // Set up the authentication dialog
            BiometricPrompt biometricPrompt = new BiometricPrompt
               .Builder(this)
               .setTitle("Biometric Authentication")
               .setSubtitle("Please authenticate to continue")
               .setDescription("Fingerprinting in biometric
                  authentication API is being tested.")
               .setNegativeButton("Cancel", this.getMainExecutor(),
                  new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface
                           dialogInterface, int i) {
                        tvstatus.setText(tvstatus.getText() +
                           "nnStep 2: Fingerprint authentication
                           cancelled.");
                     }
                  })
               .build();

            // Authenticate with callback functions
            biometricPrompt.authenticate(getCancellationSignal(),
               getMainExecutor(),
               getAuthenticationCallback());
         }
      }
   }

   private BiometricPrompt.AuthenticationCallback
         getAuthenticationCallback() {
      return new BiometricPrompt.AuthenticationCallback() {
         @Override
         public void onAuthenticationError(int errorCode,
               CharSequence errString) {
            tvstatus.setText(tvstatus.getText() + "nnStep 2:
               Fingerprint authentication error: " + errString);
            super.onAuthenticationError(errorCode, errString);
         }

         @Override
         public void onAuthenticationHelp(int helpCode,
               CharSequence helpString) {
            super.onAuthenticationHelp(helpCode, helpString);
         }

         @Override
         public void onAuthenticationFailed() {
            super.onAuthenticationFailed();
         }

         @Override
         public void onAuthenticationSucceeded(
            BiometricPrompt.AuthenticationResult result) {
               tvstatus.setText(tvstatus.getText() + "nnStep 2:
                  Fingerprint authentication Succeeded.");
               super.onAuthenticationSucceeded(result);
         }
      };
   }

   private CancellationSignal cancellationSignal;
   private CancellationSignal getCancellationSignal() {
      cancellationSignal = new CancellationSignal();
      cancellationSignal.setOnCancelListener(new
            CancellationSignal.OnCancelListener() {
         @Override
         public void onCancel() {
            tvstatus.setText(tvstatus.getText() + "nnStep 2:
               Fingerprint authentication cancelled by signal.");
         }
     });

     return cancellationSignal;
   }
}

Listing 2: Fingerprint Authentication Example

Fingerprint Authentication in Action
Figure 3: Fingerprint Authentication in Action

Fingerprint Authentication Failed
Figure 4: Fingerprint Authentication Failed

Fingerprint Authentication Succeeded
Figure 5: Fingerprint Authentication Succeeded

Conclusion

The BiometricPrompt API provided by Google’s Android platform makes it a lot simpler to integrate biometric authentication into your app, so you should consider incorporating it when dealing with sensitive personal data for your audience. In addition to fingerprint authentication, more authentication APIs will be supported in the future, but the implementation framework is similar, so it should be straightforward to include those new features as well. The APIs provide a consistent user interface throughout the system, a convenient way to access your device, and a lower imposter possibility.

In this tutorial, we covered the basics of how to check the availability of fingerprint authentication as well as customize the provided authentication dialog with callback functions in a completely working example. Source codes for the tutorial examples are available for download in the references section.

References

About the Author

Author Chunyen Liu has been a software veteran in Taiwan and U.S. He is a published author of 50+ articles and 100+ tiny apps, a software patentee, technical reviewer, and programming contest winner by ACM/IBM/SUN. He holds advanced degrees in Computer Science with 20+ U.S. graduate-level classes. On the non-technical side, he is enthusiastic about the Olympic sport of table tennis, being a certified USA Table Tennis regional referee/state coach/regional umpire, and categorized event winners at State Games and the U.S. Open.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories