Building autofill services

An autofill service is an app that makes it easier for users to fill out forms
by injecting data into the views of other apps. Autofill services can also
retrieve user data from the views in an app and store it to use it at a later
time. Autofill services are usually provided by apps that manage user data, such
as password managers.

Android makes filling out forms easier with the autofill framework available in
Android 8.0 (API level 26) and higher. Users can take advantage of autofill
features only if there is an app that provides autofill services on their
device.

This page shows how to implement an autofill service in your app. If you're
looking for a code sample that shows how to implement a service, see the
Android AutofillFramework Sample.
For further details about how autofill services work, see the reference
documentation of the AutofillService and AutofillManager classes.

Manifest declarations and permissions

Apps that provide autofill services must include a declaration that describes
the implementation of the service. To specify the declaration, include a
<service> element in the
app manifest. The
<service> element should
include the following attributes and elements:

The <meta-data> element
includes an android:resource attribute
that points to an XML resource with further details about the service. The
service_configuration resource in the previous example specifies an activity
that allows the users to configure the service. The following example shows the
service_configuration XML resource:

If the app isn't the current autofill service, then it can request the user to
change the autofill settings by using the ACTION_REQUEST_SET_AUTOFILL_SERVICE intent. The
intent returns a RESULT_OK value if the user
selected an autofill service that matches the package of the caller.

Note: Be mindful of the frequency of requests to change the autofill settings
that your app makes. Analyze the interactions that the users have with your app
and request them to change the settings only in the appropriate scenarios.

Fill out client views

The autofill service receives requests to fill out client views when the user
interacts with other apps. If the autofill service has user data that satisfies
the request then it sends the data in the response. The Android system shows an
autofill UI with the available data, as shown in figure 1:

Figure 1. Autofill UI displaying a dataset.

The autofill framework defines a workflow to fill out views that is designed to
minimize the time that the Android system is bound to the autofill service. In
each request, the Android system sends an AssistStructure object to the service by calling the onFillRequest() method.
The autofill service checks if it can satisfy the request with user data that it
has previously stored. If it can satisfy the request, then the service packages
the data in Dataset objects. The service calls
the onSuccess() method
passing a FillResponse object, which contains
the Dataset objects. If the service doesn't
have data to satisfy the request, it passes null to the onSuccess() method. The service
calls the onFailure()
method instead if there's an error processing the request. For a detailed
explanation of the workflow, see Basic
usage. The
following code shows an example of the onFillRequest() method:

A service could have more than one dataset that satisfies the request. In this
case, the Android system shows multiple options—one for each
dataset—in the autofill UI. The following code example shows how to
provide multiple datasets in a response:

Autofill services can navigate the ViewNode objects in the AssistStructure to retrieve the autofill data
required to fulfill the request. A service can retrieve autofill data using
methods of the ViewNode
class, such as getAutofillId(). A service should be
able to describe the contents of a view to check if it can satisfy the request.
Using the autofillHints attribute
is the first
approach that a service should use to describe the contents of a view. However,
client apps must explicitly provide the attribute in their views before it is
available to the service. If a client app doesn't provide the autofillHints attribute, a service
should use its own heuristics to describe the contents. The service can use
methods of other classes to get information about the contents of the view, such
as getText() or getHint(). For more information,
see Providing hints for
autofill. The
following example shows how to traverse the AssistStructure and retrieve autofill data from a ViewNode object:

Note: Most views provide autofillHints attributes that comply with the list of AUTOFILL_HINT values
included in the View class. However, views such as HtmlInfo are more likely to be compliant
with the attributes listed in the W3C autocomplete
attribute
documentation.

Save user data

An autofill service needs user data to fill out views in apps. When users
manually fill out a view, they're prompted to save the data to the current
autofill service, as shown in figure 2.

Figure 2. Autofill save UI

To save the data, the service must indicate that it is interested in storing the
data for future use. Before the Android system sends a request to save the data,
there is a fill request where the service has the opportunity to fill out the
views. To indicate that it is interested in saving the data, the service
includes a SaveInfo object to the response of
the precedent fill request. The SaveInfo object
contains at least the following data:

The type of user data that would be saved. For a list of the available
SAVE_DATA values, see SaveInfo.

The minimum set of views that need to be changed to trigger a save request.
For example, a login form typically requires the user to update the username
and password views to trigger a save request.

The autofill service can implement logic to persist the user data in the onSaveRequest() method,
which is usually called after the client activity finishes or when the client
app calls commit(). The following
code shows an example of the onSaveRequest() method:

Autofill services should encrypt sensitive data before persisting it. However,
user data includes labels or data that isn't sensitive. For example, a user
account can include a label that marks the data as a work or a personal
account. Services shouldn't encrypt labels, which allows them to use the labels
in presentation views if the user hasn't authenticated, and substitute the
labels with the actual data after the user authenticates.

Require user authentication

Autofill services can provide an additional level of security by requiring the
user to authenticate before it can fill out views. The following scenarios
are good candidates to implement user authentication:

The user data in the app needs to be unlocked using a master password or a
fingerprint scan.

A specific dataset needs to be unlocked, for example, credit card details by
using a card verification code (CVC).

In a scenario where the service requires user authentication before unlocking
the data, the service can present boilerplate data or a label and specify the
Intent that takes care of authentication. If you need
additional data to process the request after the authentication flow is done,
you can add such data to the intent. Your authentication activity can then
return the data to the AutofillService class in
your app. The following code example shows how to specify that the request
requires authentication:

Once the activity completes the authentication flow, it should call the setResult() method passing a RESULT_OK value and set the EXTRA_AUTHENTICATION_RESULT extra to the
FillResponse object that includes the populated
dataset. The following code shows an example of how to return the result once
the authentication flows completes:

In the scenario where a credit card dataset needs to be unlocked, the service
can display UI asking for the CVC. You can hide the data until the dataset is
unlocked by presenting boilerplate data, such as the name of the bank and the
last four digits of the credit card number. The following example shows how to
require authentication for a dataset and hide the data until the user provides
the CVC:

Once the activity validates the CVC, it should call the setResult() method passing a RESULT_OK value and set the EXTRA_AUTHENTICATION_RESULT extra to a
Dataset object that contains the credit card
number and expiration date. The new dataset replaces the dataset that requires
authentication and the views are filled out immediately. The following code
shows an example of how to return the dataset once the user provides the CVC:

Organize the data in logical groups

Autofill services should organize the data in logical groups that isolate
concepts from different domains. These logical groups are referred to as
partitions in this page. The following list shows typical examples of
partitions and fields:

An autofill service that correctly partitions data is able to better protect the
data of its users by not exposing data from more than one partition in a
dataset. For example, a dataset that includes credentials not necessarily should
include payment information. Organizing your data in partitions allows your
service to expose the minimum amount of information required to satisfy a
request.

Organizing the data in partitions enables services to fill activities that have
views from multiple partitions while sending the minimum amount of data to the
client app. For example, consider an activity that includes views for username,
password, street, and city, and an autofill service that has the following data:

Partition

Field 1

Field 2

Credentials

work_username

work_password

personal_username

personal_password

Address

work_street

work_city

personal_street

personal_city

The service can prepare a dataset that includes the credentials partition for
both, the work and personal accounts. When the user chooses one, a subsequent
autofill response can provide either, the work or the personal address,
depending on the user's first choice.

A service can identify the field that originated the request by calling
the isFocused() method while
traversing the AssistStructure object. This allows
services to prepare a FillResponse with the
appropriate partition data.

Advanced autofill scenarios

Paginate datasets

A large autofill response can exceed the allowed transaction size of the
Binder object that represents the remotable object required
to process the request. To prevent Android system from throwing an exception in
these scenarios, you can keep the FillResponse
small by adding no more than 20 Dataset objects
at a time. If your response needs more datasets, you can add a dataset that lets
users know that there's more information and retrieves the next group of
datasets when selected. For more information, see addDataset(Dataset).

Saving data split in multiple screens

Apps often split the user data in multiple screens in the same activity,
especially in activities used to create a new user account. For example, the
first screen asks for a username, and if the username is available, it moves to
a second screen, which asks for a password.
In these situations, the autofill service must wait until the user enters both
fields before the autofill save UI can be shown. A service can follow these
steps to handle such scenarios:

In the first fill
request,
the service adds a client state
bundle
in the response, containing the autofill IDs of the partial fields
present in the screen.

In the second fill
request,
the service retrieves the client state bundle, gets the autofill IDs set
in the previous request from the client state, and adds these IDs and the
FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE
flag to the SaveInfo object used in the
second response.

In the save
request,
the service uses the proper FillContext
objects to get the value of each field. There is one fill context per
fill request.

Every time there's an autofill request, the Android system binds to the
service and calls its onConnected() method. Once the service
processes the request, the Android system calls the onDisconnected() method and unbinds from
the service. You can implement onConnected() to provide code that runs
before processing a request and onDisconnected() to provide code that
runs after processing a request.

Customize the autofill save UI

Autofill services can customize the autofill save UI to help users decide if
they want to allow the service to save their data. Services can provide
additional information about what would be saved either through a simple text or
through a customized view. Services can also change the appearance of the button
that cancels the save request and get a notification when the user taps that
button. For more information, see the SaveInfo
reference documentation.

To test your autofill service using compatibility mode, you must explicitly
whitelist the browser or app that requires compatibility mode. You can check
which packages are already whitelisted by running the following command:

$ adb shell settings get global autofill_compat_mode_allowed_packages

If the package you're testing isn't listed, you can whitelist it by running
this command: