Welcome to MOTODEV  |  Join  |  Log In
 
Created: July 27, 2011

Writing Fingerprint-Enabled Apps

atrix-back.pngMotorola ATRIX™ is one of the most powerful smartphones available today. Running Android™ Gingerbread (after an update), it has a dual-core processor running at 1 GHz, 1 GB of RAM, and a qHD display. When placed into one of the available docks, the webtop application turns the phone/dock combination into a netbook. And it is the first Android phone with a built-in fingerprint reader.

ATRIX integrates AuthenTec's AES1750 "smart sensor" into its power switch. With this sensor fingerprints can be used to authenticate the device user, providing a faster and easier means to unlock the device when compared with the typical on-screen methods (pattern, PIN, password). As an Android developer you can take advantage of this sensor in your own Android applications.

It is important to note that fingerprint-enabled apps—apps that employ the fingerprint reader—will only run on devices running Android v2.3.4, Gingerbread, and later that have the requisite hardware. Froyo is not supported! Also note that for development and testing purposes you'll need an actual device. There is no support for the fingerprint reader in an emulated device.

What your apps can do

AuthenTec has created two separate SDKs to support the fingerprint reader. The "Mobile SDK for Android" is the more basic of the two. It contains the "LAP" APIs that:

  • verify that one or more fingerprints have been set up on the device
  • verify that the person using your app is the device owner, by requiring them to swipe their finger or enter their PIN

Any app can use the Mobile SDK for Android. Beyond registering for access to the developer portion of AuthenTec's web site, you need do nothing more than download the SDK and begin using it. No license keys are required.

AuthenTec's Advanced Mobile SDK for Android (the "Advanced SDK") contains the APIs from the Mobile SDK for Android and adds a set of "GetSecret" APIs. These additional APIs allow you to associate a "secret" (essentially, an encrypted BLOB; the contents of the secret are up to your app) with the registered user. Using these APIs, an app can store and retrieve this secret. The actual contents of the secret are whatever you, the developer, choose. For instance, if creating a digital wallet the secret might be an account number and PIN. Or, if creating an app that stores encrypted personal data, the secret might be a password or a login/password combination that provides expedited access to the app's data store.

The API key is needed by an application to register with the fingerprint framework. This key is based upon your app's package name (for instance, "com.motorola.fingerprintapp"), ensuring that only your app will be able to retrieve the secret that it has stored. Note, however, that this means that you need a separate key for each app you create. Because AuthenTec must construct this key for you—and due to possible export restrictions given the underlying encryption technology that is used—you need to apply to AuthenTec for the API key. It's an easy process, though: a developer registered with AuthenTec only needs to supply the app's package name and a description of the application itself in order to apply. AuthenTec will review your application and, upon approval, send you an email containing a link to the key.

Because the Advanced SDK includes the APIs from the Mobile SDK for Android, apps using this SDK can both verify that the user of the app is the device's owner as well as store and retrieve secret data.

Finally, note that these two SDKs are free. Use of these APIs is also free: neither AuthenTec nor Motorola Mobility imposes any fees for their use.

What the user sees

Whenever the app verifies the user (using the Mobile SDK for Android APIs) or retrieves the app's secret, the user is automatically presented with the following UI:

fingerprint-swipe.png

The display of this UI (with an animation of a finger swiping over the reader) is automatic, but is only triggered if the user has set up a fingerprint in the device settings.

No UI is needed (or shown) when storing a secret.

Getting the SDK

Begin at AuthenTec's developer website, at http://developers.authentec.com/. Click Join Now if you don't already have an account. Once you have a user name and password, supply them in the appropriate fields and click Login. This will take you to the page where you can get direct access to the Mobile SDK for Android (click Download Mobile SDK for Android) or apply for the Advanced SDK.

The Mobile SDK for Android consists of the tsm.jar file—which you must include in your fingerprint-enabled app projects—along with documentation and a sample app. The Advanced SDK includes additional documentation and a sample showing the use of the GetSecret APIs. Note that the tsm.jar file used with either SDK is the same; the API key you receive upon successfully applying for the Advanced SDK unlocks the additional functionality provided by the Advanced SDK.

Registering fingerprints on the device

Neither of the SDKs contains APIs for registering fingerprints with the system. Instead, a user must use the device settings to register their fingerprints as a way to unlock the device. The registered fingerprints are then used by the LAP APIs to authenticate and by the Secret APIs to retrieve the stored secret. Note that after having enabled fingerprint security, the user can then disable it; as long as the user doesn't clear the stored fingerprints, the fingerprint APIs will continue to work with the originally registered fingerprints.

location-security-settings.pngTo enable fingerprint security (and thus register fingerprints):

  1. From the home screen, press the menu button, and select Settings.
  2. Select Location & security.
  3. Within the Security section select Set up screen lock.
  4. Select Fingerprints.
  5. Specify a PIN when prompted (you do this twice, to ensure that you've entered it correctly).
  6. Using your right index finger, swipe the fingerprint reader as shown on the display. You generally have to do this 3 times; you may need to do more.
  7. Using your left index finger, do the same. This lets you unlock the phone using the index finger of either hand.

If the user doesn't want to have to unlock the screen every time they use their device, but still wants to use a fingerprint-protected app, they can now change the screen lock to None. The fingerprint data will still be registered on the device, and will remain usable by fingerprint-enabled apps.

Selecting Clear stored fingerprints from the Location & security settings erases the stored fingerprints; fingerprint-enabled apps will no longer be able to use the fingerprints to gate access to app features or data (but apps can detect this lack of protection and act accordingly). Clearing stored fingerprints also erases the secret associated with those fingerprints. Note that you need to disable unlock security (Settings > Location & security settings > Set up screen lock) before you can erase the stored fingerprints and secret.

Only the registered "unlock" fingerprints (or the PIN code) are used when verifying the user with the LAP APIs, or retrieving the secret stored with the GetSecret APIs. No other fingers can be registered.

Steps required by all apps

Regardless of which fingerprint SDK you use, there are a couple of basic things that all apps must do:

  • Add a <uses-permission> element for android.permission.INTERNET to your app's manifest.
    Even though the LAP and GetSecret APIs don't access the Internet, this permission is required. You must list it in your app's manifest file or the API calls will fail.
  • Include the tsm.jar library in your project.
    If you are using MOTODEV Studio or Eclipse, right-click the project in the Package Explorer and select Properties. On the left side of the Properties dialog, select Java Build Path. In the Java Build Path properties pane select the Libraries tab. Click Add External Jars, locate the tsm.jar file, and click Open. Finally, click OK within the Java Build Path properties dialog to dismiss it.
  • If your app only makes sense on a device that supports a fingerprint reader, add the following to your app's manifest:
    <uses-feature android:name="com.motorola.hardware.fingerprint">
    

    Many applications, however, should be written so that the app degrades gracefully on devices without a fingerprint reader—either by providing an alternate verification mechanism, or by preventing access to some functionality. You can do this as follows:

    1. Add the following to your app's manifest:
      <uses-feature android:name="com.motorola.hardware.fingerprint" android:required="false">
      
    2. Within your source code, detect the presence (or absence) of the fingerprint feature as follows:
      boolean fingerprintHWSupported = getPackageManager().hasSystemFeature("com.motorola.hardware.fingerprint");
      

    Alternatively, you can create an AuthentecMobile object and use it to invoke the AM2ClientLibraryLoaded() method. This method returns true if the framework exists on the device:

    am = new AuthentecMobile(this);    // 'this' is the current context
    
    if(am.AM2ClientLibraryLoaded()){
        // framework exists
    } else {
        // fingerprint framework not present
    }
    
    Or, if your app is using the Advanced SDK, you can simply check the return value from your call to AMInstallApplication(). When your app calls this to register itself with the fingerprint framework on a device that does not have the required feature, the registration will fail with AM_STATUS.eAM_STATUS_LIBRARY_NOT_AVAILABLE. Note, though, that this same error is returned if you neglected to request Internet permission in your app's manifest.

Verifying the user

If your app just needs to verify the user, it can be written entirely using the basic Mobile SDK for Android. This SDK consists of two APIs: one to see if any fingerprints have been configured, and one to verify that the current user is the configured owner of the device.

GetMap()

The GetMap() method returns a binary map indicating which fingers are currently registered. Typically, you'll get back one of three integer values:

  • -1 indicates that there was an error
  • 0 indicates that no fingers have been registered
  • 72 indicates that the index fingers of both hands have been registered

Your app must call the GetMap() function this way:

int iMap = com.authentec.tsm.TSM.LAP(myContext).GetMap().exec();

where myContext is your current Android app context.

verify()

The verify() method prompts the user to swipe a registered finger (or enter their PIN) to verify their identity. This method displays an appropriate UI and waits for the user to verify (or cancel). Until the user responds, this method blocks. Accordingly, you should not call it from the UI thread (see the sample app in the Mobile SDK for Android for one way to do this). In addition, this method can time out: if it returns an unusual result you may want to assume that it timed out and try again.

Call this method as follows. Note that the method call must follow this pattern exactly, including the "lap-verify" string (although you can do what you like with the return value, and you should substitute your app's current Android context for myContext):

int iResult = com.authentec.tsm.TSM.LAP(myContext).verify().viaGfxScreen("lap-verify").exec();

This method returns one of the following values:

  • AM_STATUS.eAM_STATUS_OK indicates that the user was verified.
  • AM_STATUS.eAM_STATUS_USER_CANCELED indicates that the user tapped Cancel.
  • AM_Status.eAM_STATUS_NO_STORED_CREDENTIAL is returned if no fingerprints are registered. In this case, no UI is displayed and the verify() method returns with this value immediately.
  • any other value indicates that an error occurred.

Getting and setting a secret

The "GetSecret()" APIs provided by the Advanced SDK are only slightly more complex. They provide functionality that allows you to associate and then retrieve a "secret" with the user's fingerprints (or PIN).

Exactly what is a secret? From the standpoint of these APIs, a secret is simply a binary BLOB encapsulated within a "Credential" object. As long as you respect the size limitation—the blob cannot exceed AM_MAX_CREDENTIAL_SIZE in bytes—you can store anything you like. Thus, the secret could be a string, a bitmap, a hashed password, or any other value that is useful to your application. Using the API key that you obtain from AuthenTec, the fingerprint framework stores the secret in its own secure and encrypted database. This ensures that the secret is tied solely to your app, and that it can only be retrieved at the behest of the registered owner of the device.

To use the GetSecret APIs you must have applied for and received the Advanced SDK. This SDK contains docs and a sample app that illustrates the use of these APIs. You also will have received the API key for your application, based upon your application's package name.

Within your code, before you can set or get a secret you must register your app with the system using AMInstallApplication(). You do this by creating an AuthenticMobile object, and then invoking AMInstallApplication() on it, like this:

AuthentecMobile am = new AuthentecMobile(this, AM_KEY);
int status = am.AMInstallApplication(null, APP_NAME, null);

In the above, both AM_KEY and APP_NAME are strings: AM_KEY is the API key received from AuthenTec, and APP_NAME is the name of your app. AMInstallApplication() returns an integer value: AM_STATUS.eAM_STATUS_OK if the key was recognized for the app (and thus the app was properly registered with the fingerprint framework) or AM_STATUS.eAM_STATUS_ACCESS_ERROR if the key is incorrect for this app. Because the key is generated from the package name, make sure you are supplying the correct key!

Storing a secret doesn't require any action on the user's part. Your code simply packages the secret within a Credential object and then stores that object, like this (in this example secretData is a String object):

Credential cr = new Credential();
cr.aucData = secretData.getBytes();
cr.aucData_length = secretData.length();
int status = am.StoreSecret(cr);
if(status == AM_STATUS.eAM_STATUS_OK){
    Log.i(TAG, "Credential stored OK");
} else {
    Log.i(TAG, "Credential storage failure: " + AM_STATUS.StatusString(status));
}
The above code shows the use of the StatusString() method to translate the integer status value into a readable text string; this method can be used with any status value returned by any of the fingerprint APIs.

Retrieving the secret triggers display of the UI requiring the user to confirm identity (either by swiping, or by entering their PIN). You retrieve a secret (and extract it from the Credential object) like this:

Credential cr2 = new Credential(); 

int status = am.GetSecret(cr2);
if(status == AM_STATUS.eAM_STATUS_OK){
    String secretData = new String(cr2.aucData, 0, cr2.aucData_length);
    Log.i(TAG, "Credential retrieved OK: [" + secretData + "]");
} else if(status == AM_STATUS.eAM_STATUS_NO_STORED_CREDENTIAL){
    Log.i(TAG, "Credential retrieval failure: no stored credential");
} else if(status == AM_STATUS.eAM_STATUS_USER_CANCELED){
    Log.i(TAG, "User canceled fingerprint swipe");
} else {
    Log.i(TAG, "Credential retrieval failure: " + AM_STATUS.StatusString(status));
}

It is important to note that if the user has not registered any fingerprints with the fingerprint framework, the app can still store and retrieve a secret. You should use the GetMap() method to make sure that the user has registered fingerprints before allowing them to store and retrieve secret data.

If you try to retrieve a secret when no secret has been stored, the GetSecret() method doesn't display any UI to the user, but simply returns AM_STATUS.eAM_STATUS_NO_STORED_CREDENTIAL.

Because the fingerprint framework itself displays its own UI when your app tries to retrieve a secret, your app will undergo a full set of lifecycle events, as if the user exited your app and then reentered it: onPause(), followed by onStop(), onRestart(), onStart(), and finally onResume().

Wrap-up

Although many—perhaps most—apps won't need to take advantage of the fingerprint reader on ATRIX, for those that require an additional level of security the fingerprint reader on the back of Motorola ATRIX can provide a quick and sure means of ensuring that only the owner of the device can access the functionality or data provided by the app. The simple, yet powerful, APIs provided by the AuthenTec SDKs make it easy to fingerprint-enable any app for which this is appropriate.

Questions? The APIs, SDKs, and the fingerprint library and hardware on Motorola ATRIX are all provided by AuthenTec. Accordingly, questions about how to use them within your applications should be directed to AuthenTec's developer support team, at developers@authentec.com.

 

Created: July 27, 2011

ECCN 5D992.a: In accordance with United States Export Administration Regulations (EAR), and specifically the Commerce Control List (CCL), this item has been classified 5D992.a. Export or re-export of this commodity and compliance with the U.S. Export Administration Regulations is ultimately the responsibility of the exporter. For more detailed information related to export or re-export of this item, please consult the EAR at http://www.access.gpo.gov/bis/ear/ear_data.html.

Copyright © 2011, Motorola Mobility, Inc. All rights reserved unless otherwise explicitly indicated. Sample source code written by Motorola Mobility, Inc. is provided to you under the conditions of the Motorola Modified BSD License.


Was This Document Helpful?
Yes  No 

Additional Comments (Optional)



Submit

Share This Page

Bookmark and Share

Table of Contents