Learn about the Autofill Framework introduced in Android O.
Users can save time filling out forms by using autofill in their devices. Android O makes filling forms, such as account and credit card forms, easier with the introduction of the Autofill Framework. The Autofill Framework manages the communication between the app and an autofill service.
Benefits
Filling out forms is a time-consuming and error-prone task. Users can easily get frustrated with apps that require these type of tasks. The Autofill Framework improves the user experience by providing the following benefits:
- Less time spent in filling fields Autofill saves users from re-typing information.
- Minimize user input errors Typing is prone to errors, especially in mobile devices. Removing the necessity of typing information also removes the errors that come with it.
Prerequisites
Before apps can work with the Autofill Framework, an autofill service must be enabled in the system settings. Users can enable or disable autofill as well as change the autofill service in Settings > System > Languages & input > Advanced > Input assistance > Autofill service.
An app can serve the role of the autofill service, which manages autofill data and fills other apps' fields. For more information about how to build an autofill service, see Autofill Framework sample.
An autofill service can require the user to authenticate before the autofill data can be used to complete fields in your app. You don't need to update your app to handle this scenario because this authentication happens on the service.
Optimizing your app for autofill
Apps that use standard views work with the Autofill Framework out of the box. However, you can take some steps to optimize how your app works with the framework.
Ensuring data is available
In some special cases, you need to take additional steps to make sure that the
data is available to the Autofill Framework to save. For example, an activity
can present a layout with standard text views, but then destroy the layout and
replace it with one without child views, such as
GLSurfaceView.
In this case, the data in the original layout is not available to the framework.
To make the data available to the framework, you should call commit() on the AutofillManager object before replacing the original
layout.
Providing hints for autofill
Your app can help an autofill service classify the data correctly by providing the meaning of each view that could be autofillable, such as views representing usernames and passwords.
Typically, there is just one way to autofill a view, but there could be
multiple ways if the view accepts more than one type of information.
For example, a view used to identify the user might accept either a username or
an email address. These hints can be set using either the android:autofillHints attribute or the
setAutofillHints() method.
The Autofill Framework does not validate the hints; they are just passed along
as is to the autofill service. Hence, they can have any value, but it is
recommended to use predefined values such as AUTOFILL_HINT_USERNAME for a username or AUTOFILL_HINT_CREDIT_CARD_NUMBER for a credit card number.
For a list of all predefined autofill hint constants, see the View reference.
Mark fields as important for autofill
You can tell the system whether the individual fields in your app should be
included in a view structure for autofill purposes. You can use the setImportantForAutofill() method,
passing the mode, to determine if the view is important for
autofill. By default, the view uses the IMPORTANT_FOR_AUTOFILL_AUTO mode, which lets Android use its
heuristics to determine if the view is important for autofill.
There are cases when a view, a view structure, or the whole activity is not important for autofill:
- A CAPTCHA field in a login activity is usually not important for autofill. In
cases like this, you can mark the view as
IMPORTANT_FOR_AUTOFILL_NO. - In a view where the user creates content, such as a text or spreadsheet
editor, the whole view structure is usually not important for autofill. In
cases like this, you can mark the view as
IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTSto make sure that all the children are also marked as not important for autofill. - In some activities within gaming apps, such as those that display gameplay,
none of the views in the activities are important for autofill. You can mark
the root view as
IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTSto ensure that all the views in the activity are marked as not important for autofill.
Force an autofill request
Sometimes, you may need to force an autofill request to occur in response to a
user action. For example, TextView offers an autofill
menu item when the user long-presses the view. The following code example shows
how to force an autofill request:
public void eventHandler(View view) {
AutofillManager afm = context.getSystemService(AutofillManager.class);
if (afm != null) {
afm.requestAutofill();
}
}
You can also use the cancel() method
to cancel the current autofill context. This can be useful, for example, if you
have a button that clears the fields in a login page.
Determine if autofill is enabled
You can implement additional autofill functionality in your app, or even in
particular views of your app, if autofill is available to the user. For example,
TextView shows an autofill entry in the overflow menu if
autofill is enabled to the user. To check if autofill is enabled for the user,
call the isEnabled() method of the
AutofillManager object.
Support for custom views
Custom views can specify the metadata that is exposed to the Autofill Framework by using the autofill API. Some views act as a container of virtual children, such as views that contain OpenGL rendered UI. These views must use the API to specify the structure of the information used in the app before they can work with the Autofill Framework.
If your app uses custom views, you must consider the following scenarios:
- The custom view provides a view structure by default, which is referred to as a standard view structure in this document.
- The custom view has a view structure that is not available to the Autofill Framework. This type of view structure is referred to as virtual structure.
Custom views with standard view structure
Custom views can define the metadata that autofill requires to work. You should make sure that your custom view manages the metadata appropriately to work with the Autofill Framework. Your custom view should take the following actions:
- Handle the autofill value that the framework sends to your app.
- Provide the autofill type and value to the framework.
When autofill is triggered, the Autofill Framework calls autofill() on your view and sends the value that
your view should use. You should implement autofill() to specify how your custom view handles the autofill value.
Your view should specify an autofill type and value by overriding the getAutofillType() and getAutofillValue() methods, respectively. By adding this code,
you ensure that your view can provide appropriate autofill types and values to
the framework.
Finally, autofill shouldn't fill the view if the user can't provide a value for
the view in its current state (for example, if the view is disabled). In these
cases, getAutofillType() and getAutofillValue() should return null, and autofill() should do nothing. The following cases
require additional steps to properly work within the framework:
- The custom view is editable.
- The custom view contains sensitive data.
The custom view is editable
If the view is editable, you should notify the Autofill Framework about changes
by calling notifyValueChanged() on the AutofillManager
object.
The custom view contains sensitive data
If the view contains personally identifiable information (PII)—such as
email addresses, credit card numbers, and passwords—it should be marked as
such. In general, views whose content come from static resources don't
contain sensitive data, but views whose content is dynamically set can contain
sensitive data. For example, a label that contains type your user name doesn't
contain sensitive data, while a label that contains Hello, John does. To mark
whether the view contains sensitive data or not, implement onProvideAutofillStructure() and
call setDataIsSensitive()
on the ViewStructure object.
The following code example shows how to mark the data in the view structure as sensitive or not:
@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
super.onProvideAutofillStructure(structure, flags);
// Content that comes from static resources is generally not sensitive
boolean sensitive = !contentIsSetFromResources();
structure.setDataIsSensitive(sensitive);
}
If the view accepts only predefined values, you can use the setAutofillOptions() method to
set the options that can be used to autofill this view. In particular, views
whose autofill type is AUTOFILL_TYPE_LIST should use
this method because the autofill service can do a better job if it knows the
options that are available to fill the view.
Views that use an adapter, such as a Spinner, are a
similar case. For example, a spinner that provides dynamically-created years
(based on the current year) to use in credit card expiration fields can
implement the getAutofillOptions() method of the
Adapter interface to provide a list of years.
Views that use an ArrayAdapter also can provide lists of
values. Although ArrayAdapter automatically sets the
autofill options for static resources, you should override getAutofillOptions() if you provide the values
dynamically.
Custom views with virtual structure
The Autofill Framework requires a view structure before it can edit and save the information in your app's UI. There are some situations where the view structure isn't available to the framework:
- The app uses a low-level rendering engine, such as OpenGL, to render the UI.
- The app uses an instance of
Canvasto draw the UI.
In these cases, you can specify a view structure by implementing
onProvideAutofillVirtualStructure() and following these steps:
- Increase the child count of the view structure by calling
addChildCount(). - Add a child by calling
newChild(). - Set the autofill ID for the child by calling
setAutofillId(). - Set relevant properties, such as the autofill value and type.
- If the data in the virtual child is sensitive, you should pass
truetosetDataIsSensitive()orfalseotherwise.
The following code example shows how to create a new child in the virtual structure:
@Override
public void onProvideAutofillVirtualStructure(ViewStructure structure,
int flags) {
super.onProvideAutofillVirtualStructure(structure, flags);
// Create a new child in the virtual structure.
structure.addChildCount(1);
ViewStructure child =
structure.newChild(childIndex);
// Set the autofill ID for the child
child.setAutofillId(structure.getAutofillId(), childVirtualId);
// Populate the child by providing properties such as value and type.
child.setAutofillValue(childAutofillValue);
child.setAutoFillType(childAutofillType);
// Some children can provide a list of values. For example, if the child is
// a spinner.
CharSequence childAutofillOptions[] = { "option1", "option2" };
child.setAutofillOptions(childAutofillOptions);
// Just like other types of views, mark the data as sensitive, if
// appropriate.
boolean sensitive = !contentIsSetFromResources();
child.setDataIsSensitive(sensitive);
}
When elements in a virtual structure change, you should notify the framework by performing the following tasks:
- If the focus inside the children changes, call
notifyViewEntered()andnotifyViewExited()on theAutofillManagerobject. - If the value of a child changes, call
notifyValueChanged()on theAutofillManagerobject. - If the view hierarchy is no longer available because the user has completed
a step in the workflow (for example, the user signed in using a login form)
call
commit()on theAutofillManagerobject. - If the view hierarchy is not valid anymore because the user has canceled a
step in the workflow (for example, if the user clicks a
button that clears a login form), call
cancel()on theAutofillManagerobject.
Using callbacks on autofill events
Apps can provide their own autocomplete views. If your app does so,
it needs a mechanism that tells the app to enable or disable the views in
response to changes in the UI autofill affordance. The Autofill Framework
provides this mechanism in the form of AutofillCallback.
This class provides the onAutofillEvent(View, int) method,
which the app calls after a change in the autofill state associated with a view.
There is also an overloaded version of this method, which includes a childId
parameter that your app can use with virtual views. The available states are
defined as
constants in the callback.
You can register a callback using the registerCallback(AutofillCallback) method of the AutofillManager class. The following code example shows
how to declare a callback for autofill events:
AutofillManager afm = this.getSystemService(AutofillManager.class);
afm.registerCallback(new AutofillManager.AutofillCallback() {
// For virtual structures, override
// onAutofillEvent(View view, int childId, int event) instead
@Override
public void onAutofillEvent(View view, int event) {
super.onAutofillEvent(view, event);
switch (event) {
case EVENT_INPUT_HIDDEN:
// The autofill affordance associated with the view was hidden
break;
case EVENT_INPUT_SHOWN:
// The autofill affordance associated with the view was shown
break;
case EVENT_INPUT_UNAVAILABLE:
// Autofill is not available.
break;
}
}
});
Use the unregisterCallback(AutofillCallback) method when it's time to remove the
callback.