- Getting Android’s Autofill to Work for You
- Using autofill
- How autofill works
- Not all autofill services are equal
- Parsing inconsistency
- Data formatting
- Testing suggestions
- How to Use Android O’s Autofill Framework
- Prerequisites
- 1. Create a New Project
- 2. Create a Settings Activity
- Step 1: Define the Layout
- Step 2: Save the Email Addresses
- Step 3: Create a Meta-Data File
- 3. Create an Autofill Service
- Step 1: Analyze View Hierarchies
- Step 2: Create and Populate Remote Views
- Step 3: Create Data Sets
- Step 4: Update the Manifest
- 4. Activate and Use the Autofill Service
- Conclusion
Getting Android’s Autofill to Work for You
May 23, 2018 · 5 min read
Oreo (8.0) added framework support for autofill, allowing users to easily autofill login credentials, addresses, and more. For the most part, the autofill APIs work very well, but there are a few quirks to watch out for.
The benefits are well worth the development cost. Our browsers have been autofilling that information for us for years, so why can’t our apps? Similarly, users who use a password manager have to switch between apps to get the right password. Anything you can do to simplify these processes will make you users much happier!
Using autofill
I won’t g o in depth on how to add basic autofill support for your apps because Google already has excellent documentation on getting started here.
For many use cases autofill will simply work out of the box on Oreo.
If autofill doesn’t work as you expect it to, you will need to do some work to tell autofill how to work with your layout. You do this using the new android:autofillHints attribute to tell autofill what type of content you expect, and android:importantForAutofill to tell autofill which views you want (or do not want) to be filled.
How autofill works
Autofill works with two primary components.
- An Autofill Service, which is an app on the user’s device that can provide data to fill in other apps.
- Your app, which provides hints to the autofill service about what types of data your Views are interested in
Note that while your user may have multiple autofill services installed, only one can be active at a time.
When focus in your app moves to a View that supports autofill, the autofill service will get an opportunity to provide content. Autofill services rely on a variety of attributes to determine what content to provide. Services should use the autofillHints first, but if the hints aren’t clear enough, they might also use the View’s hint text, ID, type, or other properties.
If you want to learn more about how that process works, check out Google’s Build an Autofill Service documentation.
Not all autofill services are equal
One problem you may run into is that not all autofill services are capable of filling the same types of content. While Google’s autofill service can fill in credentials, addresses, phone numbers, credit card information, and more, Dashlane only supports credentials (at the time of writing this article).
This means that based on which autofill service your user selects, they may or may not get autofill options for your app.
Unfortunately there is no getting around this inconsistency. I hope that Google will encourage developers to support a greater (and more consistent) range of content, but that’s tricky to do. It would be nice if you could select a different service for different content types, but I don’t anticipate that happening.
Parsing inconsistency
Each autofill service is responsible for creating its own heuristics for parsing your inputs to determine what content to fill in.
Google’s service is really good at this. It can take a set of fields marked as address fields and correctly determine where to put each component of the address.
Other services may not perform as well. They will almost certainly use different heuristics, and that may result in inconsistent behavior.
As an example of when this might be a problem, think about an address form. This form might be split up into multiple Views- the street address, the city, the state, and the ZIP code. The only address-related autofill hint that Android offers is postalAddress , so all those Views will get the same postalAddress autofill hint. A smart autofill service will then look at the ordering of the Views, the hint text on those fields, and other indicators to figure out which components of the address belong in which View. I have a feeling this complexity is part of why not all autofill services support addresses and other data types.
The approach I took to mitigate this risk was to provide extra autofill hints. Google’s documentation suggests that you use the View.AUTOFILL_HINT_ constants for your hints. However, you can add as many hints as you want . In XML you separate items with commas, in Java/Kotlin you just pass a list. On the web Chrome supports a wide range of hints, for example breaking up name into family-name and given-name . You can provide these hints in addition to Android’s pre-defined hints and other services may consider using those hints as well.
Data formatting
One last issue may run into is that the data the autofill service provides may not be in a format that is usable in your application.
For example, Google’s autofill service may fill in a phone number that includes the country code (e.g. “+1 (555) 555–5555”). Your application may not want to display or consume the country code.
Unfortunately there is no good framework approach to sanitizing data coming from autofill. You can however work around it by creating a custom view and overriding the new autofill() method:
I would really like to see a more flexible approach from the Android team that allows for doing this type of sanitation on any type of view. There is an open feature request here if you are interested in a solution as well.
Testing suggestions
One last note: When testing your app with autofill, I highly recommend running Google’s sample autofill service. It has very basic parsing heuristics for determining how to fill inputs and it supports a wide variety of data types. Because you have access to the source you can see exactly what is happening and debug the behavior.
The biggest problem with a production autofill service when testing your app is that it is a black box. You don’t know what it is doing to determine what data to fill in. The sample autofill service allows you to pull back that curtain, and also lets you manage the data more easily. Google’s autofill service for example doesn’t make it particularly easy to manage your addresses for autofill, but you can easily generate data with the sample service.
Hopefully with these tips you will be able to better manage and work with Android’s autofill framework!
Источник
How to Use Android O’s Autofill Framework
Auto form fill, often shortened to just autofill, is a feature browsers have supported for years now. Most of us use it all the time. I, for one, find it indispensable during tasks such as filling out a registration form or completing a checkout process.
The latest release of Android, Android O, brings similar functionality to Android apps. In other words, Android can now help users fill out forms that belong to all the apps they have installed on their devices. This was a much-awaited feature because typing with a virtual keyboard on a small screen tends to be quite a hassle.
As an app developer, you can use the new Autofill Framework to create your own custom autofill service, a service that decides how to populate an app’s input fields. In this tutorial, I’ll show you how.
Prerequisites
To be able to follow this tutorial, you’ll need:
- Android Studio 2.4 Preview 7 or high er
- An emulator or device running Android O or higher
1. Create a New Project
Fire up Android Studio and create a new project with an empty activity. You must, of course, remember to choose Android 7+ in the Target Android Devices dialog.
This project will need a few widgets that belong to the Design Support Library, so open the app module’s build.gradle file and add the following compile dependency to it:
Lastly, press the Sync Now button to update the project.
2. Create a Settings Activity
In this tutorial, we’ll be creating an app containing a very simple autofill service that targets only those input fields where the user is expected to type in an email address. Because almost every other app on Google Play today asks for an email address, this service will be quite useful.
Our service obviously needs to know what the user’s email addresses are. Therefore, let us now build an activity where the user can type in and save two email addresses.
Step 1: Define the Layout
As you might expect, the layout of the activity will contain two EditText widgets where the user can type in his or her email addresses. If you want it to adhere to the guidelines of Material Design, placing the EditText widgets inside TextInputLayout containers is a good idea.
Additionally, the layout must have a Button widget the user can press to save the email addresses.
You are free to place the widgets anywhere you want. Nevertheless, for now, I suggest you place them all inside a LinearLayout whose orientation is vertical.
In the above code, you can see that the Button widget has an onClick attribute pointing to a method. Click on the yellow light bulb beside this attribute in Android Studio to generate a stub for it in the associated Activity class.
Step 2: Save the Email Addresses
We’ll be using a shared preferences file called EMAIL_STORAGE to save our data. You can use the getSharedPreferences() method of your Activity class to access the file. Additionally, to be able to write to the file, you must call its edit() method, which generates a SharedPreferences.Editor object.
Accordingly, add the following code inside the saveEmailAddresses() method:
To fetch the email addresses the user has typed into the EditText widgets, you’ll have to first get references to them using the findViewById() method, and then call their getText() methods.
At this point, you can call the putString() method of the editor to add the email addresses to the preferences file as two key value pairs. After you do so, don’t forget to call the commit() method to make your changes permanent.
Step 3: Create a Meta-Data File
The settings activity we created in the previous step is currently just an ordinary activity. To let the Android platform know that it is a settings activity for an autofill service, we must create a meta-data XML file saying so.
Create a new XML file called email_address_filler.xml in the project’s res/xml folder. Inside it, add an tag and set the value of its settingsActivity attribute to the name of your Activity class.
You can now run the app, type in two email addresses, and press the Save button to save them.
3. Create an Autofill Service
Any class that extends the abstract AutoFillService class can serve as an autofill service. So start by creating a new Java class with File > New > Java Class. In the dialog that pops up, name the class EmailAddressFiller and make sure that you set the value of the Superclass field to AutoFillService .
Android Studio will now prompt you to generate stubs for two abstract methods: onSaveRequest() and onFillRequest() . In this tutorial, we’ll be focusing only the onFillRequest() method, which is automatically called whenever the user opens an activity—of any app—containing input fields.
Step 1: Analyze View Hierarchies
An autofill service needs to analyze an app’s user interface and identify input fields it can fill. That’s why the onFillRequest() method receives an AssistStructure object, which contains details about all the widgets that are currently visible on the screen. More precisely, it contains a tree of ViewNode objects.
If you’ve never seen such a tree, I suggest you use the uiautomatorviewer tool, which is part of the Android SDK, to analyze the layout hierarchies of a few apps. For example, here’s what the layout hierarchy of Android’s default mail app looks like:
Naturally, to analyze all nodes of a tree, you need a recursive method. Let’s create one now:
As you can see, this method has a ViewNode and a List as its parameters. We’ll be using the List to store all the input fields that expect email addresses.
You might now be wondering how you can programmatically tell if an input field expects an email address. Well, there’s really no foolproof approach you can follow. For now, we’re going to assume that all app developers always give meaningful resource IDs to their input fields. Based on that assumption, we can simply pick all input fields whose resource IDs contain strings such as «email» and «username».
Accordingly, add the following code to the method:
Next, whenever we encounter a ViewNode object that contains more ViewNode objects, we must recursively call the identifyEmailFields() method to analyze all its children. The following code shows you how:
At this point, we can call the identifyEmailFields() method inside the onFillRequest() method and pass the root node of the view hierarchy to it.
If our service is unable to identify any input fields for emails, it should do nothing. Therefore, add the following code to it:
Step 2: Create and Populate Remote Views
If our service does identify an input field it can fill, it must populate a drop-down list that will be shown below the input field. Doing so, however, is not straightforward because neither the input field nor the drop-down list belongs to our app.
To populate the drop-down list, we must use RemoteViews objects. As its name suggests, a RemoteViews object is a collection of views that can be displayed in another app.
To initialize a RemoteViews object, you’ll need a layout XML file. Let’s create one now called email_suggestion.xml. For now, it can contain just one TextView widget to display an email address.
Accordingly, add the following code to email_suggestion.xml:
You can now go back to the onFillRequest() method and create two RemoteViews objects: one for the primary email, and another for the secondary.
The TextView widgets inside the RemoteViews objects must display the two email addresses we stored in a shared preferences file earlier. To open the file, use the getSharedPreferences() method again. Once it’s opened, you can use its getString() method to fetch both the email addresses.
Finally, to set the contents of the remote TextView widgets, you must use the setTextViewText() method.
Step 3: Create Data Sets
We can now use the remote views to create autofill data sets that can be sent to any app. To keep this tutorial from getting too long, we’ll be creating data sets only for the first email input field we encounter. The following code shows how to pick only the first email input field:
An autofill data set is nothing but an instance of the Dataset class, and can be built using the Dataset.Builder class.
When the user selects one of the email addresses our service shows in the drop-down list, it must set the contents of the associated input field using the setValue() method of the Dataset.Builder class. However, you cannot pass a ViewNode object to the setValue() method. It actually expects an autofill identifier, which must be obtained by calling the getAutoFillId() method of the ViewNode object.
Additionally, to specify the text that must be written into the input field, you must use the AutoFillValue.forText() method. The following code shows you how:
Before you send the data sets to an app, you must add them to a FillResponse object, which can be built using the FillResponse.Builder class. Call its addDataset() method twice to add both the data sets.
Once the FillResponse object is ready, pass it as an argument to the onSuccess() method of the FillCallback object, which is one of the parameters of the onFillRequest() method.
Step 4: Update the Manifest
Like all services, the autofill service too must be declared in the project’s AndroidManifest.xml file. While doing so, you must make sure that it is protected by the android.permission.BIND_AUTO_FILL permission.
This service also needs an tag that allows it to respond to the android.service.autofill.AutoFillService action, and a tag that points to the meta-data XML file we created in an earlier step.
Accordingly, add the following lines to your manifest file:
Our autofill service and app are now ready. Build the project and install the app on your device.
4. Activate and Use the Autofill Service
To activate the autofill service, open your device’s Settings app and navigate to Apps & Notifications > Advanced > Default apps > Autofill app. In the next screen, select your app from the list of available autofill apps.
You can now open any app that asks for an email address to see your autofill service in action. For example, here’s what you’d see on the login screens of Instagram and Pinterest:
Conclusion
You now know how to create and use a custom autofill service for Android. Feel free to extend it to support other common fields, such as first name or phone number. You can also try identifying input fields using other attributes, such as labels and hints.
To learn more about the Autofill Framework, do refer to its official documentation. And in the meantime, check out some of our other posts about Android O and Android app development!
Источник