Autofill Framework

Android makes filling forms in apps easier thanks to the autofill framework introduced in Android 8.0 (API level 26). Android P provides improvements that autofill services can implement to further enhance the user experience.

Containers can assign autofill IDs to recycled views

Containers that recycle views, such as the RecyclerView class, are very useful for apps that need to display a scrolling list of elements based on large data sets. As the container is scrolled, views in the layout get reused while their contents change. If the initial contents of the view are filled out, the autofill service retains the logical meaning for the views, which are identified by their autofill ID. As the contents of the views in the layout are reused, its logical IDs remain the same, which causes the wrong autofill user data to be associated with the autofill ID.

To solve this problem, you explicitly manage the autofill ID of views that are used by RecyclerView, which can be achieved through two new APIs:

  • The getNextAutofillId() method gets a new autofill ID that is unique to the activity.
  • The setAutofillId() method sets the unique, logical autofill ID of this view in the activity.

Metrics

  • The FileEventHistory.Event class provides a new TYPE_CONTEXT_COMMITTED event that autofill services can use to get the following information:

    • The datasets that the user selected.
    • The datasets that the user ignored.
    • The fields in the selected datasets that the user changed.
    • The fields that match the user data that the service sets for field classification purposes. Field classification is an expensive operation that might not be enabled on all devices. If you need to ensure that it's enabled in your development environment, run the following command:

      adb shell settings put secure autofill_field_classification 1
      
  • Autofill services can also identify the datasets that the user selected by using the getDatasetIds() method of the SaveRequest class.

Input sanitization

The autofill framework provides sanitizer APIs that services can use to clean a field value before a save request is triggered. The sanitization is useful to avoid triggering save requests when an app formats a value that a service just filled out. For example, consider the following flow in an app that has a field for a credit card number:

  1. The autofill service has credit card datasets in which the credit card number is stored in the nnnnnnnnnnnnnnnn format (where n is a digit of the credit card number).
  2. The service fills out the field with the data mentioned in the previous step.
  3. The client app has formatting logic that adds a space every four digits of the credit card number. As a result, the field contains the data in the format nnnn nnnn nnnn nnnn.
  4. The formatting of the data triggers a save request and the save UI is shown for no reason.

Autofill services can avoid the extra save request by adding a sanitizer that removes the spaces added by the client app. For more information, see the addSanitizer() method of the SaveInfo.Builder class.

The autofill framework provides sanitizers for text and date values, see the TextValueSanitizer and DateValueSanitizer classes.

UI improvements

  • Autofill services can provide a custom header and footer in the autofill save UI. For more information, see the setHeader() and setFooter() methods.

  • Autofill services can apply a series of updates to the save UI if a condition is satisfied. The series of updates are useful in cases where the screen has multiple fields (like username, password and address fields) but some are optional. For more information, see the batchUpdate() method of the CustomDescription.Builder class.

  • The ImageTransformation class accepts a content description attribute, which makes it compatible with the accessibility features of the platform. ImageTransformation.Builder class.

  • The autofill framework provides a new DateTransformation class that services can use to display a string representation of a date in a child view of a CustomDescription object. This is useful to easily display dates in the save UI, for example, the expiration date of a credit card in MM/yyyy format.

  • Autofill services can specify the view that commits the autofill context when tapped. In other words, apps can specify the view that serves as a submit button. This is useful in scenarios where the client app clears the views before the autofill context is automatically committed. For more information, see the setTriggerId() method of the SaveInfo.Builder class.

Dataset filtering

Datasets in Android P can include an optional regular expression that serves as a filter pattern for a field. The fill UI uses the filter pattern to decide which datasets to show. For more information, see Filtering.

An autofill service can set the dataset filter pattern for a field to null, which disables filtering for the dataset. This approach is recommended when setting the values of fields that contain sensitive data, such as passwords. For more information, see the setValue() method of the Dataset class.

Compatibility mode

The autofill framework provides a compatibility mode allowing services to work with apps that display their fields in a virtual structure and don't implement the APIs for such structures, such as browsers. For more information, see custom views with virtual structure.

The compatibility mode allows autofill services to use the accessibility virtual structure for autofill purposes. Compatibility mode uses the accessibility APIs to get the virtual structure, when needed.

For matching purposes, autofill services need the web scheme and domain of the page being loaded while in compatibility mode. The browser can provide this information in the view that represents the URL bar. The information in the view is sanitized to protect users' privacy. You can specify multiple resource IDs that identify the views that represent the URL bar in the whitelist settings of the compatibility mode, by using the following command:

adb shell settings put global autofill_compat_allowed_packages pkg1[resId1]:pkg2[resId1,resId2]

You can retrieve the web scheme and domain of the currently loaded page by using the getWebScheme() and getWebDomain() methods of the ViewNode class.

Compatibility mode has the following limitations:

  • A save request is triggered when the service uses the FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE flag or the setTrigger() method is called. FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE is set by default when using compatibility mode.
  • The text value of the nodes might not be available in the onSaveRequest(SaveRequest, SaveCallback) method.
  • When you point Chrome to a different URL, the new page might not be filled out. Restarting the browser might fix the issue.
  • You must manually whitelist the apps that you want to support compatibility mode. For example to whitelist Chrome and Chrome Beta, use the following command:

    adb shell settings put global autofill_compat_allowed_packages com.android.chrome:com.chrome.beta
    

For more information, see compatibility mode.

Changes to the assist structure

  • Autofill services can get the android:id attribute in text views. The android:text attribute of some views might not be meaningful to the service, for example, when the view is localized. Autofill services can use the android:id attribute as additional input to determine the meaning of the data. For more information, see the getTextIdEntry() method.
  • The getWebScheme() method returns the scheme part of a URL if the node represents an HTML document. Autofill services can use the web scheme in scenarios where a website is associated with an app. For more information see, Associate website and mobile app data.
  • The getImportantForAutofill() method returns the value of the getImportantForAutofill() method of the view associated with the node. This method is useful when the user manually requests autofill (i.e., when the FillRequest flags contains the FLAG_MANUAL_REQUEST value).
  • The AssistStructure.ViewNode class exposes the following information about the size of text fields:
    • Maximum width (in ems) of the text associated with the node, see the getMaxTextEms() method.
    • Maximum length of the text associated with this node, see the getMaxTextLength() method.
    • Minimum width in ems of the text associated with the node, see the getMinTextEms() method.

Miscellaneous