You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
12 KiB
233 lines
12 KiB
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!--
|
|
Copyright 2017 The Android Open Source Project
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
-->
|
|
|
|
<sample>
|
|
<name>AutofillFramework</name>
|
|
<group>Input</group> <!-- This field will be deprecated in the future
|
|
and replaced with the "categories" tags below. -->
|
|
<package>com.example.android.autofill.app</package>
|
|
|
|
<!-- change minSdk if needed-->
|
|
<minSdk>26</minSdk>
|
|
<compileSdkVersion>26</compileSdkVersion>
|
|
<targetSdkVersion>26</targetSdkVersion>
|
|
<!-- Include additional dependencies here.-->
|
|
<!-- dependency>com.google.android.gms:play-services:5.0.+</dependency -->
|
|
|
|
<strings>
|
|
<intro>
|
|
<![CDATA[
|
|
This sample app demos the Autofill feature introduced in Android O.
|
|
]]>
|
|
</intro>
|
|
</strings>
|
|
|
|
<!-- The basic templates have already been enabled. Uncomment more as desired. -->
|
|
<template src="base-build" />
|
|
|
|
<metadata>
|
|
<!-- Values: {DRAFT | PUBLISHED | INTERNAL | DEPRECATED | SUPERCEDED} -->
|
|
<status>PUBLISHED</status>
|
|
<!-- See http://go/sample-categories for details on the next 4 fields. -->
|
|
<!-- Most samples just need to udpate the Categories field. This is a comma-
|
|
seperated list of topic tags. Unlike the old category system, samples
|
|
may have multiple categories, so feel free to add extras. Try to avoid
|
|
simply tagging everything with "UI". :)-->
|
|
<categories>Input, Android O Preview</categories>
|
|
<technologies>Android</technologies>
|
|
<languages>Java</languages>
|
|
<solutions>Mobile</solutions>
|
|
<!-- Values: {BEGINNER | INTERMEDIATE | ADVANCED | EXPERT} -->
|
|
<!-- Beginner is for "getting started" type content, or essential content.
|
|
(e.g. "Hello World", activities, intents)
|
|
|
|
Intermediate is for content that covers material a beginner doesn't need
|
|
to know, but that a skilled developer is expected to know.
|
|
(e.g. services, basic styles and theming, sync adapters)
|
|
|
|
Advanced is for highly technical content geared towards experienced developers.
|
|
(e.g. performance optimizations, custom views, bluetooth)
|
|
|
|
Expert is reserved for highly technical or specialized content, and should
|
|
be used sparingly. (e.g. VPN clients, SELinux, custom instrumentation runners) -->
|
|
<level>ADVANCED</level>
|
|
<!-- Dimensions: 512x512, PNG fomrat -->
|
|
<icon>screenshots/icon-web.png</icon>
|
|
<!-- Path to screenshots. Use <img> tags for each. -->
|
|
<screenshots>
|
|
<img>screenshots/1_MainPage.png</img>
|
|
<img>screenshots/2_SampleLoginEditTexts.png</img>
|
|
<img>screenshots/3_SampleLoginEditTextsAutofilled.png</img>
|
|
<img>screenshots/4_WelcomeActivity.png</img>
|
|
<img>screenshots/5_SampleLoginCustomVirtualView.png</img>
|
|
<img>screenshots/6_SampleLoginCustomVirtualViewAutofilled.png</img>
|
|
<img>screenshots/7_SampleCheckOutSpinnersAutofillable.png</img>
|
|
<img>screenshots/8_SampleCheckOutSpinnersAutofilled.png</img>
|
|
<img>screenshots/9_SettingsActivity.png</img>
|
|
<img>screenshots/10_AuthNeeded.png</img>
|
|
<img>screenshots/11_AuthActivity.png</img>
|
|
</screenshots>
|
|
<!-- List of APIs that this sample should be cross-referenced under. Use <android>
|
|
for fully-qualified Framework class names ("android:" namespace).
|
|
|
|
Use <ext> for custom namespaces, if needed. See "Samples Index API" documentation
|
|
for more details. -->
|
|
<api_refs>
|
|
<android>android.view.View</android>
|
|
<android>android.service.autofill.AutoFillService</android>
|
|
<android>android.view.autofill.AutoFillManager</android>
|
|
</api_refs>
|
|
|
|
<!-- 1-3 line description of the sample here.
|
|
|
|
Avoid simply rearranging the sample's title. What does this sample actually
|
|
accomplish, and how does it do it? -->
|
|
<description>
|
|
<![CDATA[
|
|
This sample demonstrates the use of the Autofill Framework. It includes implementations of client
|
|
Activities with views that should be autofilled, and a Service that can provide autofill data to
|
|
client Activities.
|
|
]]>
|
|
</description>
|
|
|
|
<!-- Multi-paragraph introduction to sample, from an educational point-of-view.
|
|
Makrdown formatting allowed. This will be used to generate a mini-article for the
|
|
sample on DAC. -->
|
|
<intro>
|
|
<![CDATA[
|
|
This sample demonstrates the use of the Autofill framework from the service side and the client
|
|
side. In practice, only a small handful of apps will develop Autofill services because a device
|
|
will only have one service as default at a time, and there is just a small number of 3rd-party apps
|
|
providing these services (typically password managers). However, all apps targeting O with any
|
|
autofillable fields should follow the necessary steps to 1) ensure their views can be autofilled
|
|
and 2) optimize their autofill performance. Most of the time, there is little to no extra code
|
|
involved, but the use of custom views and views with virtual child views requires more work.
|
|
|
|
The sample's Autofill service is implemented to parse the client's view hierarchy in search of
|
|
autofillable fields that it has data for. If such fields exist in the hierarchy, the service sends
|
|
data suggestions to the client to autofill those fields. The client uses the following attributes
|
|
to specify autofill properties: `importantForAutofill`, `autofillHints`, and `autofillType`.
|
|
`importantForAutofill` specifies whether the view is autofillable. `autofillHints` is a list of
|
|
strings that hint to the service **what** data to fill the view with. This sample service only
|
|
supports the hints listed [here](https://developer.android.com/reference/android/view/View.html#AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE)
|
|
with the prefix AUTOFILL_HINT_*. `autofillType` tells the service the type of data it expects to
|
|
receive (i.e. a list index, a date, or a string). Specifying `autofillType` is only necessary
|
|
when implementing a custom view since all of the provided widgets in the UI toolkit do this for you.
|
|
|
|
To set the device's default Autofill service to the one in the sample, edit **Settings** >
|
|
**System** > **Languages & Input** > **Advanced** > **Auto-fill service** and select the sample
|
|
app. To edit the service's settings, tap the settings icon next to the **Auto-fill service** list
|
|
item or open the **Autofill Settings** launcher icon.. Here, you can set whether you want to enable
|
|
authentication on the entire autofill Response or just on individual autofill datasets. You should
|
|
also set the main password to “unlock” authenticated autofill data with.
|
|
|
|
**Note:** This sample service stores all autofill data in SharedPreferences and thus is not secure.
|
|
Be careful about what you store when experimenting with the sample because anyone with root access
|
|
to your device will be able to view your autofill data.
|
|
|
|
The client side of the app has three Activities that each have autofillable fields. The first
|
|
Activity uses standard views to comprise a login form. Very little needs to be done by the client
|
|
app to ensure the views get autofilled properly. The second Activity uses a custom view with
|
|
virtual children, meaning some autofillable child views are not known to the View hierarchy to be
|
|
child views. Supporting autofill on these child views is a little more involved.
|
|
|
|
The following code snippet shows how to signal to the autofill service that a specific
|
|
autofillable virtual view has come into focus:
|
|
|
|
```java
|
|
class CustomVirtualView {
|
|
...
|
|
// Cache AutofillManager system service
|
|
mAutofillManager = context.getSystemService(AutofillManager.class);
|
|
...
|
|
// Notify service which virtual view has come into focus.
|
|
mAutofillManager.notifyViewEntered(CustomVirtualView.this, id, absBounds);
|
|
...
|
|
// Notify service that a virtual view has left focus.
|
|
mAutofillManager.notifyViewExited(CustomVirtualView.this, id);
|
|
}
|
|
```
|
|
|
|
Now that the autofillable view has signaled to the service that it has been autofilled, it needs
|
|
to provide the virtual view hierarchy to the Autofill service. This is done out of the box for
|
|
views part of the UI toolkit, but you need to implement this yourself if you have the view has
|
|
virtual child views. The following code example shows the `View` method you have to override in
|
|
order to provide this view hierarchy data to the Autofill service.
|
|
|
|
```java
|
|
@Override
|
|
public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
|
|
// Build a ViewStructure that will get passed to the AutofillService by the framework
|
|
// when it is time to find autofill suggestions.
|
|
structure.setClassName(getClass().getName());
|
|
int childrenSize = mItems.size();
|
|
int index = structure.addChildCount(childrenSize);
|
|
// Traverse through the view hierarchy, including virtual child views. For each view, we
|
|
// need to set the relevant autofill metadata and add it to the ViewStructure.
|
|
for (int i = 0; i < childrenSize; i++) {
|
|
Item item = mItems.valueAt(i);
|
|
ViewStructure child = structure.newChild(index);
|
|
child.setAutofillId(structure, item.id);
|
|
child.setAutofillHints(item.hints);
|
|
child.setAutofillType(item.type);
|
|
child.setDataIsSensitive(!item.sanitized);
|
|
child.setText(item.text);
|
|
child.setAutofillValue(AutofillValue.forText(item.text));
|
|
child.setFocused(item.focused);
|
|
child.setId(item.id, getContext().getPackageName(), null, item.line.idEntry);
|
|
child.setClassName(item.getClassName());
|
|
index++;
|
|
}
|
|
}
|
|
```
|
|
|
|
After the service processes the Autofill request and sends back a series of Autofill `Datasets`
|
|
(wrapped in a `Response` object), the user can pick which `Dataset` they want to autofill their
|
|
views with. When a `Dataset` is selected, this method is invoked for all of the views that were
|
|
associated with that `Dataset` by the service. For example, the `Dataset` might contain Autofill
|
|
values for username, password, birthday, and address. This method would then be invoked on all
|
|
four of those fields. The following code example shows how the sample app implements the method
|
|
to deliver a UI update to the appropriate child view after the user makes their selection.
|
|
|
|
```java
|
|
@Override
|
|
public void autofill(SparseArray<AutofillValue> values) {
|
|
// User has just selected a Dataset from the list of autofill suggestions.
|
|
// The Dataset is comprised of a list of AutofillValues, with each AutofillValue meant
|
|
// to fill a specific autofillable view. Now we have to update the UI based on the
|
|
// AutofillValues in the list.
|
|
for (int i = 0; i < values.size(); i++) {
|
|
final int id = values.keyAt(i);
|
|
final AutofillValue value = values.valueAt(i);
|
|
final Item item = mItems.get(id);
|
|
if (item != null && item.editable) {
|
|
// Set the item's text to the text wrapped in the AutofillValue.
|
|
item.text = value.getTextValue();
|
|
} else if (item == null) {
|
|
// Component not found, so no-op.
|
|
} else {
|
|
// Component not editable, so no-op.
|
|
}
|
|
}
|
|
postInvalidate();
|
|
}
|
|
```
|
|
]]>
|
|
</intro>
|
|
</metadata>
|
|
</sample>
|