Приложения, использующие стандартные представления, работают с фреймворком автозаполнения без специальной настройки. Вы также можете оптимизировать работу своего приложения с фреймворком.
Настройте среду автозаполнения
В этом разделе описывается, как настроить базовую функцию автозаполнения для вашего приложения.
Настройте службу автозаполнения
Для использования фреймворка автозаполнения на вашем устройстве должна быть настроена служба автозаполнения. Хотя большинство телефонов и планшетов под управлением Android 8.0 (уровень API 26) и выше поставляются со службой автозаполнения, мы рекомендуем использовать тестовую службу при тестировании приложения, например, службу автозаполнения из примера фреймворка автозаполнения Android . При использовании эмулятора явно настройте службу автозаполнения, поскольку в эмуляторе может отсутствовать служба по умолчанию.
После установки тестовой службы автозаполнения из примера приложения включите службу автозаполнения, перейдя в Настройки > Система > Языки и ввод > Дополнительно > Помощь при вводе > Служба автозаполнения .
Дополнительную информацию о настройке эмулятора для тестирования автозаполнения см. в разделе Тестирование приложения с помощью автозаполнения .
Предоставлять подсказки для автозаполнения
Служба автозаполнения определяет тип каждого представления с помощью эвристики. Однако, если ваше приложение использует эту эвристику, поведение автозаполнения может неожиданно измениться при обновлении приложения. Чтобы служба автозаполнения правильно определяла форм-факторы вашего приложения, предоставьте подсказки для автозаполнения.
Вы можете задать подсказки для автозаполнения с помощью атрибута android:autofillHints
. Следующий пример устанавливает подсказку "password"
для EditText
:
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:autofillHints="password" />
Вы также можете задать подсказки программно, используя метод setAutofillHints()
, как показано в следующем примере:
Котлин
val password = findViewById<EditText>(R.id.password) password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD)
Ява
EditText password = findViewById(R.id.password); password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);
Включить предопределенные константы подсказок
Фреймворк автозаполнения не проверяет подсказки; они передаются в службу автозаполнения без изменений и проверки. Хотя вы можете использовать любое значение, классы View
и AndroidX HintConstants
содержат списки официально поддерживаемых констант подсказок.
Используя комбинацию этих констант, вы можете создавать макеты для распространенных сценариев автозаполнения:
Учетные данные
В форму входа можно включить подсказки по учетным данным, такие как AUTOFILL_HINT_USERNAME
и AUTOFILL_HINT_PASSWORD
.
Для создания новой учетной записи или когда пользователи меняют свое имя пользователя и пароль, вы можете использовать AUTOFILL_HINT_NEW_USERNAME
и AUTOFILL_HINT_NEW_PASSWORD
.
Информация о кредитной карте
При запросе данных кредитной карты вы можете использовать подсказки, такие как AUTOFILL_HINT_CREDIT_CARD_NUMBER
и AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE
.
Чтобы узнать дату истечения срока действия кредитной карты, выполните одно из следующих действий:
- Если вы используете единое представление для даты истечения срока действия, используйте
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE
. - Если вы используете разные представления для каждой части срока действия, вы можете использовать
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY
,AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH
иAUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR
для каждого соответствующего представления.
Физический адрес
Для полей формы физического адреса вы можете использовать подсказки, например следующие:
- Для адреса в одном представлении используйте
AUTOFILL_HINT_POSTAL_ADDRESS
. - При использовании отдельных представлений для разных частей адреса можно использовать следующее:
Имена людей
При запросе имен людей вы можете использовать подсказки, например следующие:
- Для автоматического заполнения полного имени человека в одном представлении используйте
AUTOFILL_HINT_PERSON_NAME
. - При использовании отдельных представлений для разных частей имени можно использовать любой из следующих вариантов:
Номера телефонов
Для номеров телефонов вы можете использовать следующее:
- При запросе полного номера телефона в одном представлении используйте
AUTOFILL_HINT_PHONE_NUMBER
. - Если вы используете отдельные представления для разных частей номера телефона, вы можете использовать любой из следующих вариантов:
Одноразовый пароль (OTP)
Для одноразового пароля в одном представлении можно использовать AUTOFILL_HINT_SMS_OTP
.
Для нескольких представлений, где каждое представление сопоставляется с одной цифрой одноразового пароля, можно использовать метод generateSmsOtpHintForCharacterPosition()
для генерации подсказок по символам.
Связанные данные веб-сайта и мобильного приложения
Сервисы автозаполнения, такие как Autofill with Google, могут обмениваться данными пользователя для входа в систему между браузерами и устройствами Android после связывания приложения и веб-сайта. Когда пользователь выбирает один и тот же сервис автозаполнения на обеих платформах, вход в ваше веб-приложение делает его учётные данные доступными для автозаполнения при входе в соответствующее приложение Android.
Чтобы связать приложение Android с веб-сайтом, разместите ссылку на цифровой актив (Digital Asset Link) с отношением delegate_permission/common.get_login_creds
на своём сайте. Затем укажите связь в файле AndroidManifest.xml
вашего приложения. Подробные инструкции по связыванию веб-сайта с приложением Android см. в статье «Включение автоматического входа в приложения и на веб-сайты» .
Завершите процесс автозаполнения
В этом разделе описываются конкретные сценарии, в которых вы можете предпринять шаги по улучшению функциональности автозаполнения для пользователей вашего приложения.
Определите, включено ли автозаполнение
Пользователи могут включить или отключить автозаполнение, а также изменить службу автозаполнения, перейдя в раздел «Настройки» > «Система» > «Языки и ввод» > «Дополнительно» > «Помощь при вводе» > «Служба автозаполнения» . Ваше приложение не может переопределить пользовательские настройки автозаполнения, но вы можете реализовать дополнительные функции автозаполнения в своём приложении или в определённых представлениях приложения, если автозаполнение доступно пользователю.
Например, TextView
отображает запись автозаполнения в дополнительном меню, если автозаполнение включено для пользователя. Чтобы проверить, включено ли автозаполнение для пользователя, вызовите метод isEnabled()
объекта AutofillManager
.
Чтобы убедиться, что процесс регистрации и входа в систему оптимизирован для пользователей без автозаполнения, реализуйте вход одним нажатием .
Принудительный запрос автозаполнения
Иногда требуется принудительно выполнить запрос автозаполнения в ответ на действие пользователя. Например, TextView
предлагает пункт меню автозаполнения, когда пользователь нажимает и удерживает поле. В следующем примере кода показано, как принудительно выполнить запрос автозаполнения:
Котлин
fun eventHandler(view: View) { val afm = requireContext().getSystemService(AutofillManager::class.java) afm?.requestAutofill(view) }
Ява
public void eventHandler(View view) { AutofillManager afm = context.getSystemService(AutofillManager.class); if (afm != null) { afm.requestAutofill(view); } }
Вы также можете использовать метод cancel()
для отмены текущего контекста автозаполнения. Это может быть полезно, если на странице входа есть кнопка очистки полей.
Используйте правильный тип автозаполнения для данных в элементах управления выбором
Средства выбора могут быть полезны при автозаполнении, предоставляя пользовательский интерфейс, позволяющий пользователям изменять значение поля, содержащего дату или время. Например, в форме кредитной карты средство выбора даты позволяет пользователям вводить или изменять срок действия своей кредитной карты. Однако для отображения данных, когда средство выбора не отображается, необходимо использовать другое представление, например EditText
.
Объект EditText
изначально ожидает данные автозаполнения типа AUTOFILL_TYPE_TEXT
. Если вы используете другой тип данных, создайте пользовательское представление, унаследованное от EditText
и реализующее методы, необходимые для обработки соответствующего типа данных. Например, если у вас есть поле даты, реализуйте методы с логикой, которая корректно обрабатывает значения типа AUTOFILL_TYPE_DATE
.
При указании типа данных для автозаполнения служба автозаполнения может создать соответствующее представление данных, отображаемых в представлении. Подробнее см. в разделе Использование средств выбора с автозаполнением .
Завершить автозаполнение контекста
Фреймворк автозаполнения сохраняет введенные пользователем данные для дальнейшего использования, отображая диалоговое окно «Сохранить для автозаполнения?» после завершения контекста автозаполнения. Обычно контекст автозаполнения завершается при завершении активности. Однако в некоторых ситуациях необходимо явно уведомить фреймворк, например, если вы используете одну и ту же активность, но разные фрагменты для экранов входа и содержимого. В таких ситуациях вы можете явно завершить контекст, вызвав AutofillManager.commit()
.
Поддержка пользовательских представлений
Пользовательские представления могут указывать метаданные, предоставляемые фреймворку автозаполнения, используя API автозаполнения. Некоторые представления действуют как контейнер виртуальных дочерних элементов, например, представления, содержащие визуализированный пользовательский интерфейс OpenGL. Эти представления должны использовать API для указания структуры информации, используемой в приложении, прежде чем они смогут работать с фреймворком автозаполнения.
Если ваше приложение использует пользовательские представления, рассмотрите следующие сценарии:
- Пользовательское представление обеспечивает стандартную структуру представления или структуру представления по умолчанию.
- Пользовательское представление имеет виртуальную структуру или структуру представления, которая недоступна для фреймворка автозаполнения.
Пользовательские представления со стандартной структурой представления
Пользовательские представления могут определять метаданные, необходимые для работы автозаполнения. Убедитесь, что ваше пользовательское представление управляет метаданными надлежащим образом для работы с фреймворком автозаполнения. Ваше пользовательское представление должно выполнять следующие действия:
- Обрабатывайте значение автозаполнения, которое фреймворк отправляет в ваше приложение.
- Укажите тип и значение автозаполнения для фреймворка.
При срабатывании функции автозаполнения фреймворк автозаполнения вызывает autofill()
для вашего представления и отправляет значение, которое должно использоваться в представлении. Реализуйте autofill()
, чтобы указать, как ваше пользовательское представление будет обрабатывать значение автозаполнения.
В вашем представлении необходимо указать тип и значение автозаполнения, переопределив методы getAutofillType()
и getAutofillValue()
соответственно.
Наконец, функция автозаполнения не должна заполнять представление, если пользователь не может указать значение для представления в его текущем состоянии, например, если представление отключено. В этих случаях getAutofillType()
должен возвращать AUTOFILL_TYPE_NONE
, getAutofillValue()
должен возвращать null
, а autofill()
не должен выполнять никаких действий.
В следующих случаях для корректной работы в рамках структуры требуются дополнительные шаги:
- Пользовательский вид можно редактировать.
- Пользовательское представление содержит конфиденциальные данные.
Пользовательский вид можно редактировать.
Если представление доступно для редактирования, уведомите инфраструктуру автозаполнения об изменениях, вызвав notifyValueChanged()
для объекта AutofillManager
.
Пользовательское представление содержит конфиденциальные данные
Если представление содержит персональные данные (PII), такие как адреса электронной почты, номера кредитных карт и пароли, его необходимо пометить как конфиденциальное.
Как правило, представления, содержимое которых формируется из статических ресурсов, не содержат конфиденциальных данных, в то время как представления, содержимое которых задаётся динамически, могут содержать конфиденциальные данные. Например, метка с текстом «введите имя пользователя» не содержит конфиденциальных данных, а метка с текстом «Привет, Джон» — содержит.
Система автозаполнения по умолчанию предполагает, что все данные конфиденциальны. Вы можете отметить данные, которые не являются конфиденциальными.
Чтобы отметить, содержит ли представление конфиденциальные данные, реализуйте onProvideAutofillStructure()
и вызовите setDataIsSensitive()
для объекта ViewStructure
.
В следующем примере кода показано, как пометить данные в структуре представления как неконфиденциальные:
Котлин
override fun onProvideAutofillStructure(structure: ViewStructure, flags: Int) { super.onProvideAutofillStructure(structure, flags) structure.setDataIsSensitive(false) }
Ява
@Override public void onProvideAutofillStructure(ViewStructure structure, int flags) { super.onProvideAutofillStructure(structure, flags); structure.setDataIsSensitive(false); }
Если представление принимает только предопределённые значения, вы можете использовать метод setAutofillOptions()
для установки параметров автозаполнения представления. В частности, представления с типом автозаполнения AUTOFILL_TYPE_LIST
должны использовать этот метод, поскольку служба автозаполнения может работать эффективнее, если знает доступные параметры для заполнения представления.
Аналогичный случай представляют собой представления, использующие адаптер, такой как Spinner
. Например, Spinner, предоставляющий динамически создаваемые годы на основе текущего года для использования в полях срока действия кредитной карты, может реализовать метод getAutofillOptions()
интерфейса Adapter
для предоставления списка лет.
Представления, использующие ArrayAdapter
, также могут предоставлять списки значений. ArrayAdapter
автоматически устанавливает параметры автозаполнения для статических ресурсов. Если вы предоставляете значения динамически, переопределите getAutofillOptions()
.
Пользовательские представления с виртуальной структурой
Фреймворку автозаполнения требуется структура представления, прежде чем он сможет редактировать и сохранять информацию в пользовательском интерфейсе вашего приложения. Структура представления недоступна фреймворку в следующих ситуациях:
- Для визуализации пользовательского интерфейса приложение использует низкоуровневый движок рендеринга, такой как OpenGL .
- Приложение использует экземпляр
Canvas
для отрисовки пользовательского интерфейса.
В этих случаях вы можете указать структуру представления, реализовав onProvideAutofillVirtualStructure()
и выполнив следующие шаги:
- Увеличьте количество дочерних элементов структуры представления, вызвав
addChildCount()
. - Добавьте дочерний элемент, вызвав
newChild()
. - Установите идентификатор автозаполнения для дочернего элемента, вызвав
setAutofillId()
. - Задайте соответствующие свойства, такие как значение и тип автозаполнения.
- Если данные в виртуальном дочернем элементе конфиденциальны, передайте
true
вsetDataIsSensitive()
; в противном случае передайтеfalse
.
В следующем фрагменте кода показано, как создать новый дочерний элемент в виртуальной структуре:
Котлин
override fun onProvideAutofillVirtualStructure(structure: ViewStructure, flags: Int) { super.onProvideAutofillVirtualStructure(structure, flags) // Create a new child in the virtual structure. structure.addChildCount(1) val child = structure.newChild(childIndex) // Set the autofill ID for the child. child.setAutofillId(structure.autofillId!!, 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, such as when the child is // a spinner. val childAutofillOptions = arrayOf<CharSequence>("option1", "option2") child.setAutofillOptions(childAutofillOptions) // Just like other types of views, mark the data as sensitive when // appropriate. val sensitive = !contentIsSetFromResources() child.setDataIsSensitive(sensitive) }
Ява
@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, such as when the child is // a spinner. CharSequence childAutofillOptions[] = { "option1", "option2" }; child.setAutofillOptions(childAutofillOptions); // Just like other types of views, mark the data as sensitive when // appropriate. boolean sensitive = !contentIsSetFromResources(); child.setDataIsSensitive(sensitive); }
При изменении элементов виртуальной структуры уведомите фреймворк, выполнив следующие задачи:
- Если фокус внутри дочерних элементов изменяется, вызовите
notifyViewEntered()
иnotifyViewExited()
для объектаAutofillManager
. - Если значение дочернего элемента изменяется, вызовите
notifyValueChanged()
для объектаAutofillManager
. - Если иерархия представлений больше недоступна, поскольку пользователь завершил шаг в рабочем процессе, например, когда он вошел в систему с помощью формы входа, вызовите
commit()
для объектаAutofillManager
. - Если иерархия представлений недействительна, поскольку пользователь отменил шаг в рабочем процессе, например, когда пользователь нажал кнопку, которая очищает форму входа, вызовите
cancel()
для объектаAutofillManager
.
Используйте обратные вызовы для событий автозаполнения
Если ваше приложение предоставляет собственные представления для автозаполнения, вам необходим механизм, который сообщает приложению о необходимости включения или отключения представлений в ответ на изменения возможностей автозаполнения пользовательского интерфейса. Фреймворк автозаполнения предоставляет этот механизм в виде AutofillCallback
.
Этот класс предоставляет метод onAutofillEvent(View, int)
, который приложение вызывает после изменения состояния автозаполнения, связанного с представлением. Существует также перегруженная версия этого метода, включающая параметр childId
, который ваше приложение может использовать с виртуальными представлениями. Доступные состояния определяются как константы в функции обратного вызова.
Вы можете зарегистрировать обратный вызов с помощью метода registerCallback()
класса AutofillManager
. В следующем примере кода показано, как объявить обратный вызов для событий автозаполнения:
Котлин
val afm = context.getSystemService(AutofillManager::class.java) afm?.registerCallback(object : AutofillManager.AutofillCallback() { // For virtual structures, override // onAutofillEvent(View view, int childId, int event) instead. override fun onAutofillEvent(view: View, event: Int) { super.onAutofillEvent(view, event) when (event) { EVENT_INPUT_HIDDEN -> { // The autofill affordance associated with the view was hidden. } EVENT_INPUT_SHOWN -> { // The autofill affordance associated with the view was shown. } EVENT_INPUT_UNAVAILABLE -> { // Autofill isn't available. } } } })
Ява
AutofillManager afm = getContext().getSystemService(AutofillManager.class); afm.registerCallback(new AutofillManager.AutofillCallback() { // For virtual structures, override // onAutofillEvent(View view, int childId, int event) instead. @Override public void onAutofillEvent(@NonNull 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 isn't available. break; } } });
Когда придет время удалить обратный вызов, используйте метод unregisterCallback()
.
Настройте автозаполнение выделенного рисуемого элемента
При автозаполнении представления платформа отображает объект Drawable
поверх него, указывая на то, что его содержимое заполнено автоматически. По умолчанию этот объект Drawable представляет собой сплошной прямоугольник полупрозрачного цвета, который немного темнее цвета фона темы. Этот объект Drawable менять не нужно, но его можно настроить, переопределив свойство android:autofilledHighlight
темы , используемой приложением или действием, как показано в этом примере:
res/values/styles.xml
<resources>
<style name="MyAutofilledHighlight" parent="...">
<item name="android:autofilledHighlight">@drawable/my_drawable</item>
</style>
</resources>
res/drawable/my_drawable.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4DFF0000" />
</shape>
AndroidManifest.xml
<application ...
android:theme="@style/MyAutofilledHighlight">
<!-- or -->
<activity ...
android:theme="@style/MyAutofilledHighlight">
Аутентификация для автозаполнения
Служба автозаполнения может потребовать от пользователя пройти аутентификацию, прежде чем служба сможет заполнить поля в вашем приложении. В этом случае система Android запускает действие аутентификации службы как часть стека ваших действий.
Вам не нужно обновлять приложение для поддержки аутентификации, поскольку аутентификация происходит внутри сервиса. Однако необходимо убедиться, что структура представления активности сохраняется при её перезапуске, например, создав структуру представления в onCreate()
, а не в onStart()
или onResume()
.
Вы можете проверить поведение своего приложения, когда служба автозаполнения требует аутентификации, используя HeuristicsService из примера AutofillFramework и настроив его на требование аутентификации при ответе на автозаполнение. Вы также можете использовать пример BadViewStructureCreationSignInActivity для эмуляции этой проблемы.
Назначьте идентификаторы автозаполнения для переработанных представлений
Контейнеры, повторно использующие представления, такие как класс RecyclerView
, полезны для приложений, которым требуется отображать прокручиваемые списки элементов на основе больших наборов данных. По мере прокрутки контейнера система повторно использует представления в макете, но при этом представления содержат новый контент.
Если исходное содержимое повторно используемого представления заполнено, служба автозаполнения сохраняет логическое значение представлений, используя их идентификаторы автозаполнения. Проблема возникает, когда при повторном использовании представлений в макете логические идентификаторы представлений остаются прежними, что приводит к сопоставлению неверных данных пользователя автозаполнения с идентификатором автозаполнения.
Чтобы решить эту проблему на устройствах под управлением Android 9 (уровень API 28) и выше, явно управляйте идентификатором автозаполнения представлений, которые используются RecyclerView
, с помощью следующих методов:
- Метод
getNextAutofillId()
получает новый идентификатор автозаполнения, уникальный для данного действия. - Метод
setAutofillId()
устанавливает уникальный логический идентификатор автозаполнения этого представления в действии.
Устранение известных проблем
В этом разделе представлены способы решения известных проблем в системе автозаполнения.
Автозаполнение приводит к сбоям приложений на Android 8.0, 8.1
В Android 8.0 (уровень API 26) и 8.1 (уровень API 27) автозаполнение может приводить к сбоям приложения в определённых ситуациях. Чтобы обойти потенциальные проблемы, добавьте тег importantForAutofill=no
ко всем представлениям, для которых не выполняется автозаполнение. Вы также можете добавить тег importantForAutofill=noExcludeDescendants
ко всему действию.
Диалоги с измененным размером не учитываются при автозаполнении.
В Android 8.1 (уровень API 27) и ниже, если размер представления в диалоговом окне изменяется после того, как оно уже отображено, это представление не учитывается для автозаполнения. Такие представления не включаются в объект AssistStructure
, который система Android отправляет службе автозаполнения. В результате служба не может заполнить эти представления.
Чтобы обойти эту проблему, замените свойство token
параметров диалогового окна на свойство token
действия, создающего это диалоговое окно. После проверки того, что автозаполнение включено, сохраните параметры окна в методе onWindowAttributesChanged()
класса, унаследованного от Dialog
. Затем замените свойство token
сохранённых параметров на свойство token
родительского действия в методе onAttachedToWindow()
.
В следующем фрагменте кода показан класс, реализующий этот обходной путь:
Котлин
class MyDialog(context: Context) : Dialog(context) { // Used to store the dialog window parameters. private var token: IBinder? = null private val isDialogResizedWorkaroundRequired: Boolean get() { if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) { return false } val autofillManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { context.getSystemService(AutofillManager::class.java) } else { null } return autofillManager?.isEnabled ?: false } override fun onWindowAttributesChanged(params: WindowManager.LayoutParams) { if (params.token == null && token != null) { params.token = token } super.onWindowAttributesChanged(params) } override fun onAttachedToWindow() { if (isDialogResizedWorkaroundRequired) { token = ownerActivity!!.window.attributes.token } super.onAttachedToWindow() } }
Ява
public class MyDialog extends Dialog { public MyDialog(Context context) { super(context); } // Used to store the dialog window parameters. private IBinder token; @Override public void onWindowAttributesChanged(WindowManager.LayoutParams params) { if (params.token == null && token != null) { params.token = token; } super.onWindowAttributesChanged(params); } @Override public void onAttachedToWindow() { if (isDialogResizedWorkaroundRequired()) { token = getOwnerActivity().getWindow().getAttributes().token; } super.onAttachedToWindow(); } private boolean isDialogResizedWorkaroundRequired() { if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) { return false; } AutofillManager autofillManager = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { autofillManager = getContext().getSystemService(AutofillManager.class); } return autofillManager != null && autofillManager.isEnabled(); } }
Чтобы избежать ненужных операций, следующий фрагмент кода показывает, как проверить, поддерживается ли автозаполнение на устройстве и включено ли оно для текущего пользователя, а также требуется ли этот обходной путь:
Котлин
// AutofillExtensions.kt fun Context.isDialogResizedWorkaroundRequired(): Boolean { // After the issue is resolved on Android, check whether the // workaround is still required for the current device. return isAutofillAvailable() } fun Context.isAutofillAvailable(): Boolean { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // The autofill framework is available on Android 8.0 // or higher. return false } val afm = getSystemService(AutofillManager::class.java) // Return true if autofill is supported by the device and enabled // for the current user. return afm != null && afm.isEnabled }
Ява
public class AutofillHelper { public static boolean isDialogResizedWorkaroundRequired(Context context) { // After the issue is resolved on Android, check whether the // workaround is still required for the current device. return isAutofillAvailable(context); } public static boolean isAutofillAvailable(Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // The autofill framework is available on Android 8.0 // or higher. return false; } AutofillManager afm = context.getSystemService(AutofillManager.class); // Return true if autofill is supported by the device and enabled // for the current user. return afm != null && afm.isEnabled(); } }
Протестируйте свое приложение с автозаполнением
После оптимизации приложения для работы со службами автозаполнения проверьте, работает ли оно со службами автозаполнения так, как задумано.
Для тестирования приложения используйте эмулятор или физическое устройство под управлением Android 8.0 (уровень API 26) или выше. Подробнее о создании эмулятора см. в разделе Создание и управление виртуальными устройствами .
Установить службу автозаполнения
Прежде чем тестировать приложение с функцией автозаполнения, необходимо установить другое приложение, предоставляющее услуги автозаполнения. Вы можете использовать стороннее приложение, но проще использовать пробный сервис автозаполнения, чтобы не регистрироваться в сторонних сервисах.
Вы можете использовать пример фреймворка автозаполнения Android на Java для тестирования своего приложения с сервисами автозаполнения. Этот пример приложения предоставляет сервис автозаполнения и клиентские классы Activity
, которые можно использовать для тестирования рабочего процесса перед его использованием в вашем приложении. На этой странице представлен пример приложения android-AutofillFramework .
После установки приложения включите службу автозаполнения в системных настройках эмулятора, перейдя в Настройки > Система > Языки и ввод > Дополнительно > Помощь при вводе > Служба автозаполнения .
Анализ требований к данным
Чтобы протестировать ваше приложение с использованием сервиса автозаполнения, сервису необходимы данные, которые он может использовать для заполнения вашего приложения. Сервис также должен понимать, какие типы данных ожидаются в представлениях вашего приложения. Например, если в вашем приложении есть представление, которое ожидает имя пользователя, у сервиса должен быть набор данных, содержащий имя пользователя, и механизм, позволяющий определить, что представление ожидает такие данные.
Сообщите сервису, какой тип данных ожидается в ваших представлениях, установив атрибут android:autofillHints
. Некоторые сервисы используют сложную эвристику для определения типа данных, но другие, например, пример приложения, полагаются на разработчика, предоставляющего эту информацию. Ваше приложение будет работать лучше со службами автозаполнения, если вы установите атрибут android:autofillHints
в представлениях, соответствующих автозаполнению.
Проведите тест
После анализа требований к данным вы можете запустить тест, который включает сохранение тестовых данных в службе автозаполнения и запуск автозаполнения в вашем приложении.
Сохраните данные в сервисе
Чтобы сохранить данные в активной в данный момент службе автозаполнения, выполните следующие действия:
- Откройте приложение, содержащее представление, которое ожидает данные того типа, который вы хотите использовать в тесте. Пример приложения android-AutofillFramework предоставляет пользовательский интерфейс с представлениями, которые ожидают данные нескольких типов, например, номера кредитных карт и имена пользователей.
- Нажмите на представление, содержащее нужный вам тип данных.
- Введите значение в представление.
- Нажмите кнопку подтверждения, например «Войти» или «Отправить» . Обычно вам необходимо отправить форму, прежде чем сервис сохранит данные.
- Проверьте запрос на разрешение в системном диалоговом окне. В системном диалоговом окне отображается имя текущей активной службы и спрашивается, хотите ли вы использовать эту службу в тесте. Если вы хотите использовать службу, нажмите «Сохранить» .
Если Android не отображает диалоговое окно разрешения или если служба не та, которую вы хотите использовать в тесте, проверьте, активна ли служба в данный момент в настройках системы.
Включите автозаполнение в вашем приложении
Чтобы активировать автозаполнение в вашем приложении, выполните следующие действия:
- Откройте приложение и перейдите к активности, содержащей представления, которые вы хотите протестировать.
- Нажмите на поле, которое необходимо заполнить.
- Система отображает пользовательский интерфейс автозаполнения, содержащий наборы данных, которые могут заполнить представление, как показано на рисунке 1.
- Нажмите на набор данных, содержащий нужные вам данные. В представлении будут отображены данные, ранее сохранённые в сервисе.
Если Android не отображает пользовательский интерфейс автозаполнения, вы можете попробовать следующие варианты устранения неполадок:
- Проверьте, что представления в вашем приложении используют правильное значение атрибута
android:autofillHints
. Список возможных значений атрибута см. в константах с префиксомAUTOFILL_HINT
в классеView
. - Проверьте, установлено ли для атрибута
android:importantForAutofill
значение, отличное отno
, в представлении, которое необходимо заполнить, или установлено значение, отличное отnoExcludeDescendants
в представлении или одном из его родительских элементов.
Приложения, использующие стандартные представления, работают с фреймворком автозаполнения без специальной настройки. Вы также можете оптимизировать работу своего приложения с фреймворком.
Настройте среду автозаполнения
В этом разделе описывается, как настроить базовую функцию автозаполнения для вашего приложения.
Настройте службу автозаполнения
Для использования фреймворка автозаполнения на вашем устройстве должна быть настроена служба автозаполнения. Хотя большинство телефонов и планшетов под управлением Android 8.0 (уровень API 26) и выше поставляются со службой автозаполнения, мы рекомендуем использовать тестовую службу при тестировании приложения, например, службу автозаполнения из примера фреймворка автозаполнения Android . При использовании эмулятора явно настройте службу автозаполнения, поскольку в эмуляторе может отсутствовать служба по умолчанию.
После установки тестовой службы автозаполнения из примера приложения включите службу автозаполнения, перейдя в Настройки > Система > Языки и ввод > Дополнительно > Помощь при вводе > Служба автозаполнения .
Дополнительную информацию о настройке эмулятора для тестирования автозаполнения см. в разделе Тестирование приложения с помощью автозаполнения .
Предоставлять подсказки для автозаполнения
Служба автозаполнения определяет тип каждого представления с помощью эвристики. Однако, если ваше приложение использует эту эвристику, поведение автозаполнения может неожиданно измениться при обновлении приложения. Чтобы служба автозаполнения правильно определяла форм-факторы вашего приложения, предоставьте подсказки для автозаполнения.
Вы можете задать подсказки для автозаполнения с помощью атрибута android:autofillHints
. Следующий пример устанавливает подсказку "password"
для EditText
:
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:autofillHints="password" />
Вы также можете задать подсказки программно, используя метод setAutofillHints()
, как показано в следующем примере:
Котлин
val password = findViewById<EditText>(R.id.password) password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD)
Ява
EditText password = findViewById(R.id.password); password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);
Включить предопределенные константы подсказок
Фреймворк автозаполнения не проверяет подсказки; они передаются в службу автозаполнения без изменений и проверки. Хотя вы можете использовать любое значение, классы View
и AndroidX HintConstants
содержат списки официально поддерживаемых констант подсказок.
Используя комбинацию этих констант, вы можете создавать макеты для распространенных сценариев автозаполнения:
Учетные данные
В форму входа можно включить подсказки по учетным данным, такие как AUTOFILL_HINT_USERNAME
и AUTOFILL_HINT_PASSWORD
.
Для создания новой учетной записи или когда пользователи меняют свое имя пользователя и пароль, вы можете использовать AUTOFILL_HINT_NEW_USERNAME
и AUTOFILL_HINT_NEW_PASSWORD
.
Информация о кредитной карте
При запросе данных кредитной карты вы можете использовать подсказки, такие как AUTOFILL_HINT_CREDIT_CARD_NUMBER
и AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE
.
Чтобы узнать дату истечения срока действия кредитной карты, выполните одно из следующих действий:
- Если вы используете единое представление для даты истечения срока действия, используйте
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE
. - Если вы используете разные представления для каждой части срока действия, вы можете использовать
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY
,AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH
иAUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR
для каждого соответствующего представления.
Физический адрес
Для полей формы физического адреса вы можете использовать подсказки, например следующие:
- Для адреса в одном представлении используйте
AUTOFILL_HINT_POSTAL_ADDRESS
. - При использовании отдельных представлений для разных частей адреса можно использовать следующее:
Имена людей
При запросе имен людей вы можете использовать подсказки, например следующие:
- Для автоматического заполнения полного имени человека в одном представлении используйте
AUTOFILL_HINT_PERSON_NAME
. - При использовании отдельных представлений для разных частей имени можно использовать любой из следующих вариантов:
Номера телефонов
Для номеров телефонов вы можете использовать следующее:
- При запросе полного номера телефона в одном представлении используйте
AUTOFILL_HINT_PHONE_NUMBER
. - Если вы используете отдельные представления для разных частей номера телефона, вы можете использовать любой из следующих вариантов:
Одноразовый пароль (OTP)
Для одноразового пароля в одном представлении можно использовать AUTOFILL_HINT_SMS_OTP
.
Для нескольких представлений, где каждое представление сопоставляется с одной цифрой одноразового пароля, можно использовать метод generateSmsOtpHintForCharacterPosition()
для генерации подсказок по символам.
Связанные данные веб-сайта и мобильного приложения
Сервисы автозаполнения, такие как Autofill with Google, могут обмениваться данными пользователя для входа в систему между браузерами и устройствами Android после связывания приложения и веб-сайта. Когда пользователь выбирает один и тот же сервис автозаполнения на обеих платформах, вход в ваше веб-приложение делает его учётные данные доступными для автозаполнения при входе в соответствующее приложение Android.
Чтобы связать приложение Android с веб-сайтом, разместите ссылку на цифровой актив (Digital Asset Link) с отношением delegate_permission/common.get_login_creds
на своём сайте. Затем укажите связь в файле AndroidManifest.xml
вашего приложения. Подробные инструкции по связыванию веб-сайта с приложением Android см. в статье «Включение автоматического входа в приложения и на веб-сайты» .
Завершите процесс автозаполнения
В этом разделе описываются конкретные сценарии, в которых вы можете предпринять шаги по улучшению функциональности автозаполнения для пользователей вашего приложения.
Определите, включено ли автозаполнение
Пользователи могут включить или отключить автозаполнение, а также изменить службу автозаполнения, перейдя в раздел «Настройки» > «Система» > «Языки и ввод» > «Дополнительно» > «Помощь при вводе» > «Служба автозаполнения» . Ваше приложение не может переопределить пользовательские настройки автозаполнения, но вы можете реализовать дополнительные функции автозаполнения в своём приложении или в определённых представлениях приложения, если автозаполнение доступно пользователю.
Например, TextView
отображает запись автозаполнения в дополнительном меню, если автозаполнение включено для пользователя. Чтобы проверить, включено ли автозаполнение для пользователя, вызовите метод isEnabled()
объекта AutofillManager
.
Чтобы убедиться, что процесс регистрации и входа в систему оптимизирован для пользователей без автозаполнения, реализуйте вход одним нажатием .
Принудительный запрос автозаполнения
Иногда требуется принудительно выполнить запрос автозаполнения в ответ на действие пользователя. Например, TextView
предлагает пункт меню автозаполнения, когда пользователь нажимает и удерживает поле. В следующем примере кода показано, как принудительно выполнить запрос автозаполнения:
Котлин
fun eventHandler(view: View) { val afm = requireContext().getSystemService(AutofillManager::class.java) afm?.requestAutofill(view) }
Ява
public void eventHandler(View view) { AutofillManager afm = context.getSystemService(AutofillManager.class); if (afm != null) { afm.requestAutofill(view); } }
Вы также можете использовать метод cancel()
для отмены текущего контекста автозаполнения. Это может быть полезно, если на странице входа есть кнопка очистки полей.
Используйте правильный тип автозаполнения для данных в элементах управления выбором
Средства выбора могут быть полезны при автозаполнении, предоставляя пользовательский интерфейс, позволяющий пользователям изменять значение поля, содержащего дату или время. Например, в форме кредитной карты средство выбора даты позволяет пользователям вводить или изменять срок действия своей кредитной карты. Однако для отображения данных, когда средство выбора не отображается, необходимо использовать другое представление, например EditText
.
Объект EditText
изначально ожидает данные автозаполнения типа AUTOFILL_TYPE_TEXT
. Если вы используете другой тип данных, создайте пользовательское представление, унаследованное от EditText
и реализующее методы, необходимые для обработки соответствующего типа данных. Например, если у вас есть поле даты, реализуйте методы с логикой, которая корректно обрабатывает значения типа AUTOFILL_TYPE_DATE
.
При указании типа данных для автозаполнения служба автозаполнения может создать соответствующее представление данных, отображаемых в представлении. Подробнее см. в разделе Использование средств выбора с автозаполнением .
Завершить автозаполнение контекста
Фреймворк автозаполнения сохраняет введенные пользователем данные для дальнейшего использования, отображая диалоговое окно «Сохранить для автозаполнения?» после завершения контекста автозаполнения. Обычно контекст автозаполнения завершается при завершении активности. Однако в некоторых ситуациях необходимо явно уведомить фреймворк, например, если вы используете одну и ту же активность, но разные фрагменты для экранов входа и содержимого. В таких ситуациях вы можете явно завершить контекст, вызвав AutofillManager.commit()
.
Поддержка пользовательских представлений
Пользовательские представления могут указывать метаданные, предоставляемые фреймворку автозаполнения, используя API автозаполнения. Некоторые представления действуют как контейнер виртуальных дочерних элементов, например, представления, содержащие визуализированный пользовательский интерфейс OpenGL. Эти представления должны использовать API для указания структуры информации, используемой в приложении, прежде чем они смогут работать с фреймворком автозаполнения.
Если ваше приложение использует пользовательские представления, рассмотрите следующие сценарии:
- Пользовательское представление обеспечивает стандартную структуру представления или структуру представления по умолчанию.
- Пользовательское представление имеет виртуальную структуру или структуру представления, которая недоступна для фреймворка автозаполнения.
Пользовательские представления со стандартной структурой представления
Пользовательские представления могут определить метаданные, которые необходимо для работы автозапроводно. Убедитесь, что ваш пользовательский просмотр управляет метаданными соответствующим образом для работы с фреймворком автозаполнения. Ваше пользовательское представление должно предпринять следующие действия:
- Обработайте значение автозаполнения, которое платформу отправляет в ваше приложение.
- Предоставьте тип автозаполнения и значение для структуры.
Когда автозаполнение запускается, в вашем представлении вызывает autofill()
и отправляет значение, которое должно использовать ваше представление. Реализуйте autofill()
, чтобы указать, как ваше пользовательское представление обрабатывает значение автозаполнения.
Ваше представление должно указать тип автозаполнения и значение, переопределив методы getAutofillType()
и getAutofillValue()
соответственно.
Наконец, автозаполнение не должно заполнять представление, если пользователь не может предоставить значение для представления в своем текущем состоянии, например, если представление отключено. В этих случаях getAutofillType()
должен возвращать AUTOFILL_TYPE_NONE
, getAutofillValue()
должен возвращать null
, а autofill()
ничего не должен делать.
В следующих случаях требуется дополнительные шаги для правильной работы в рамках:
- Пользовательский вид редактируется.
- Пользовательское представление содержит конфиденциальные данные.
Пользовательский вид редактируется
Если представление редактируется, уведомить структуру автозаполнения об изменениях, вызывая notifyValueChanged()
на объекте AutofillManager
.
Пользовательское представление содержит конфиденциальные данные
Если представление содержит личную информацию (PII), такую как адреса электронной почты, номера кредитных карт и пароли, она должна быть помечена как конфиденциальная.
В целом, представления, содержимое которого поступает из статических ресурсов, не содержат конфиденциальных данных, в то время как представления, содержимое которого динамически установлено, могут содержать конфиденциальные данные. Например, метка, которая содержит введите ваше имя пользователя, не содержит конфиденциальных данных, в то время как метка, которая содержит привет, Джон .
Структура автозаполнения предполагает, что по умолчанию все данные являются конфиденциальными. Вы можете отметить данные, которые не являются конфиденциальными.
Чтобы отметить, содержит ли представление конфиденциальные данные, реализуйте onProvideAutofillStructure()
и Call setDataIsSensitive()
на объекте ViewStructure
.
В следующем примере кода показано, как отмечать данные в структуре представления как не чувствительную:
Котлин
override fun onProvideAutofillStructure(structure: ViewStructure, flags: Int) { super.onProvideAutofillStructure(structure, flags) structure.setDataIsSensitive(false) }
Ява
@Override public void onProvideAutofillStructure(ViewStructure structure, int flags) { super.onProvideAutofillStructure(structure, flags); structure.setDataIsSensitive(false); }
Если представление принимает только предопределенные значения, вы можете использовать метод setAutofillOptions()
для установки параметров, которые можно использовать для автоматического вида. В частности, представления, тип автозаполнения которого является AUTOFILL_TYPE_LIST
, должны использовать этот метод, потому что служба автозаполнения может выполнять лучшее задание, если он знает варианты, доступные для заполнения представления.
Просмотры, которые используют адаптер, такой как Spinner
, являются аналогичным случаем. Например, прядильщик, который обеспечивает динамически созданные годы, основанные на текущем году, для использования в областях истечения срока действия кредитных карт, может реализовать метод getAutofillOptions()
интерфейса Adapter
, чтобы предоставить список лет.
Просмотры, которые используют ArrayAdapter
, также могут предоставить списки значений. ArrayAdapter
автоматически устанавливает параметры автозаполнения для статических ресурсов. Если вы предоставляете значения динамически, переопределите getAutofillOptions()
.
Пользовательские виды с виртуальной структурой
Фреймворк автозаполнения требует структуры представления, прежде чем она сможет редактировать и сохранить информацию в пользовательском интерфейсе вашего приложения. Структура представления не доступна для структуры в следующих ситуациях:
- Приложение использует двигатель рендеринга низкого уровня, такой как OpenGL , для отображения пользовательского интерфейса.
- Приложение использует экземпляр
Canvas
для рисования пользовательского интерфейса.
В этих случаях вы можете указать структуру представления, внедрив onProvideAutofillVirtualStructure()
и выполняя эти шаги:
- Увеличьте количество детей структуры представления, позвонив
addChildCount()
. - Добавьте ребенка, позвонив
newChild()
. - Установите идентификатор автозаполнения для ребенка, вызовите
setAutofillId()
. - Установите соответствующие свойства, такие как значение автозаполнения и тип.
- Если данные в виртуальном ребенке являются конфиденциальными, передайте
true
tosetDataIsSensitive()
; В противном случае пройтиfalse
.
Следующий фрагмент кода показывает, как создать нового ребенка в виртуальной структуре:
Котлин
override fun onProvideAutofillVirtualStructure(structure: ViewStructure, flags: Int) { super.onProvideAutofillVirtualStructure(structure, flags) // Create a new child in the virtual structure. structure.addChildCount(1) val child = structure.newChild(childIndex) // Set the autofill ID for the child. child.setAutofillId(structure.autofillId!!, 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, such as when the child is // a spinner. val childAutofillOptions = arrayOf<CharSequence>("option1", "option2") child.setAutofillOptions(childAutofillOptions) // Just like other types of views, mark the data as sensitive when // appropriate. val sensitive = !contentIsSetFromResources() child.setDataIsSensitive(sensitive) }
Ява
@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, such as when the child is // a spinner. CharSequence childAutofillOptions[] = { "option1", "option2" }; child.setAutofillOptions(childAutofillOptions); // Just like other types of views, mark the data as sensitive when // appropriate. boolean sensitive = !contentIsSetFromResources(); child.setDataIsSensitive(sensitive); }
Когда элементы в виртуальной структуре изменяются, уведомить структуру, выполняя следующие задачи:
- Если фокус внутри детей меняется, вызовите
notifyViewEntered()
иnotifyViewExited()
на объектеAutofillManager
. - Если значение ребенка изменяется, вызовите
notifyValueChanged()
на объектеAutofillManager
. - Если иерархия представления больше не доступна, потому что пользователь выполнил шаг в рабочем процессе, например, когда они войдут в систему, используя форму входа в систему, вызовите
commit()
на объектеAutofillManager
. - Если иерархия представления не действительна, потому что пользователь отменил шаг в рабочем процессе, например, когда пользователь нажимает кнопку, которая очищает форму входа в систему, вызовите
cancel()
на объектеAutofillManager
.
Используйте обратные вызовы на событиях автозаполнения
Если ваше приложение предоставляет свои собственные представления о автозаполнении, вам нужен механизм, который сообщает приложению, чтобы включить или отключить представления в ответ на изменения в предоставлении автопроизводства пользовательского интерфейса. Структура автозаполнения обеспечивает этот механизм в форме AutofillCallback
.
Этот класс предоставляет метод onAutofillEvent(View, int)
, который приложение вызывает после изменения в состоянии автозаполнения, связанного с представлением. Существует также перегруженная версия этого метода, которая включает в себя childId
параметр, который ваше приложение может использовать с виртуальными представлениями. Доступные состояния определяются как постоянные в обратном вызове.
Вы можете зарегистрировать обратный вызов, используя метод registerCallback()
класса AutofillManager
. В следующем примере кода показано, как объявить обратный вызов для событий автозаполнения:
Котлин
val afm = context.getSystemService(AutofillManager::class.java) afm?.registerCallback(object : AutofillManager.AutofillCallback() { // For virtual structures, override // onAutofillEvent(View view, int childId, int event) instead. override fun onAutofillEvent(view: View, event: Int) { super.onAutofillEvent(view, event) when (event) { EVENT_INPUT_HIDDEN -> { // The autofill affordance associated with the view was hidden. } EVENT_INPUT_SHOWN -> { // The autofill affordance associated with the view was shown. } EVENT_INPUT_UNAVAILABLE -> { // Autofill isn't available. } } } })
Ява
AutofillManager afm = getContext().getSystemService(AutofillManager.class); afm.registerCallback(new AutofillManager.AutofillCallback() { // For virtual structures, override // onAutofillEvent(View view, int childId, int event) instead. @Override public void onAutofillEvent(@NonNull 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 isn't available. break; } } });
Когда пришло время удалить обратный вызов, используйте метод unregisterCallback()
.
Настройте выделенный автозаполнение.
Когда представление будет автозаполнено, платформа отдает от Drawable
, чтобы указать, что содержимое представления является автозаполнением. По умолчанию этот нарисован - сплошной прямоугольник с полупрозрачным цветом, который немного темнее, чем цвет темы, используемый для рисования фона. Нарисование не должно быть изменено, но его можно настроить, переопределив элемент android:autofilledHighlight
Theme , используемая приложением или деятельностью, как показано в этом примере:
res/values/styles.xml
<resources>
<style name="MyAutofilledHighlight" parent="...">
<item name="android:autofilledHighlight">@drawable/my_drawable</item>
</style>
</resources>
Res/Drawable/my_drawable.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4DFF0000" />
</shape>
AndroidManifest.xml
<application ...
android:theme="@style/MyAutofilledHighlight">
<!-- or -->
<activity ...
android:theme="@style/MyAutofilledHighlight">
Аутентификация для автозаполнения
Служба автозаполнения может потребовать, чтобы пользователь проверял подлинность, прежде чем служба сможет завершить поля в вашем приложении, и в этом случае система Android запускает деятельность по аутентификации службы как часть стека вашей деятельности.
Вам не нужно обновлять свое приложение для поддержки аутентификации, потому что аутентификация происходит в службе. Тем не менее, вы должны убедиться, что структура вида деятельности сохраняется при перезапуске деятельности, например, создавая структуру представления в onCreate()
, а не в onStart()
или onResume()
.
Вы можете проверить, как ведет себя приложение, когда служба автозаполнения требует аутентификации, используя эвристический справочник из образца AutoFillFramework и настройки ее для требуемой аутентификации ответа заполнения. Вы также можете использовать выборку BadViewStructureCreationInInActivity для эмуляции этой проблемы.
Назначьте идентификаторы автозаполнения для переработанных просмотров
Контейнеры, которые перерабатывают представления, такие как класс RecyclerView
, полезны для приложений, которые должны отображать списки прокрутки элементов на основе больших наборов данных. По мере того, как контейнер прокручивается, система повторно использует представления в макете, но тогда представления содержат новый контент.
Если исходное содержимое переработанного представления заполняется, служба автозаполнения сохраняет логическое значение представлений, используя свои идентификаторы автозаполнения. Проблема возникает, когда, когда система повторно использует представления в макете, логические идентификаторы представлений остаются прежними, что приводит к тому, что неправильные пользовательские данные автозаполнения будут связаны с идентификатором автозаполнения.
Чтобы решить эту проблему на устройствах под управлением Android 9 (API -уровень 28) и выше, явно управляйте идентификатором автоматического заполнения представлений, которые используются RecyclerView
, используя эти методы:
- Метод
getNextAutofillId()
получает новый идентификатор автозаполнения, который является уникальным для деятельности. - Метод
setAutofillId()
устанавливает уникальный, логический идентификатор автозаполнения этого представления в деятельности.
Решать известные вопросы
В этом разделе представлены обходные пути для известных проблем в рамках автозаполнения.
Автозаполнение приводит к сбою приложений на Android 8.0, 8.1
В Android 8.0 (API -уровне 26) и 8.1 (уровень API 27) автозаполнение может привести к сбою вашего приложения в определенных сценариях. Чтобы обойти потенциальные проблемы, отметьте любые представления, которые не заполнены importantForAutofill=no
. Вы также можете пометить всю деятельность с помощью importantForAutofill=noExcludeDescendants
.
Измененные диалоги не рассматриваются для автозаполнения
В Android 8.1 (API -уровне 27) и ниже, если представление в диалоговом окне изменяется после того, как он уже отображается, представление не рассматривается для автозаполнения. Эти представления не включены в объект AssistStructure
, который система Android отправляет в службу автозаполнения. В результате служба не может заполнить представления.
Чтобы обойти эту проблему, замените свойство token
параметров диалогового окна на свойство token
деятельности, которое создает диалог. После того, как вы подтвердите, что автозаполнение включено, сохраните параметры окна в методе onWindowAttributesChanged()
класса, который наследует от Dialog
. Затем замените свойство token
сохраненных параметров на свойство token
родительской деятельности в методе onAttachedToWindow()
.
На следующем фрагменте кода показывает класс, который реализует этот обходной путь:
Котлин
class MyDialog(context: Context) : Dialog(context) { // Used to store the dialog window parameters. private var token: IBinder? = null private val isDialogResizedWorkaroundRequired: Boolean get() { if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) { return false } val autofillManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { context.getSystemService(AutofillManager::class.java) } else { null } return autofillManager?.isEnabled ?: false } override fun onWindowAttributesChanged(params: WindowManager.LayoutParams) { if (params.token == null && token != null) { params.token = token } super.onWindowAttributesChanged(params) } override fun onAttachedToWindow() { if (isDialogResizedWorkaroundRequired) { token = ownerActivity!!.window.attributes.token } super.onAttachedToWindow() } }
Ява
public class MyDialog extends Dialog { public MyDialog(Context context) { super(context); } // Used to store the dialog window parameters. private IBinder token; @Override public void onWindowAttributesChanged(WindowManager.LayoutParams params) { if (params.token == null && token != null) { params.token = token; } super.onWindowAttributesChanged(params); } @Override public void onAttachedToWindow() { if (isDialogResizedWorkaroundRequired()) { token = getOwnerActivity().getWindow().getAttributes().token; } super.onAttachedToWindow(); } private boolean isDialogResizedWorkaroundRequired() { if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) { return false; } AutofillManager autofillManager = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { autofillManager = getContext().getSystemService(AutofillManager.class); } return autofillManager != null && autofillManager.isEnabled(); } }
Чтобы избежать ненужных операций, следующий фрагмент кода показывает, как проверить, поддерживается ли автозаполнение на устройстве и включен для текущего пользователя, и требуется ли этот обходной путь:
Котлин
// AutofillExtensions.kt fun Context.isDialogResizedWorkaroundRequired(): Boolean { // After the issue is resolved on Android, check whether the // workaround is still required for the current device. return isAutofillAvailable() } fun Context.isAutofillAvailable(): Boolean { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // The autofill framework is available on Android 8.0 // or higher. return false } val afm = getSystemService(AutofillManager::class.java) // Return true if autofill is supported by the device and enabled // for the current user. return afm != null && afm.isEnabled }
Ява
public class AutofillHelper { public static boolean isDialogResizedWorkaroundRequired(Context context) { // After the issue is resolved on Android, check whether the // workaround is still required for the current device. return isAutofillAvailable(context); } public static boolean isAutofillAvailable(Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // The autofill framework is available on Android 8.0 // or higher. return false; } AutofillManager afm = context.getSystemService(AutofillManager.class); // Return true if autofill is supported by the device and enabled // for the current user. return afm != null && afm.isEnabled(); } }
Проверьте свое приложение с помощью автозаполнения
После оптимизации своего приложения для работы с службами автопроизводства проверьте, работает ли оно, как предназначено для служб автопроизводства.
Используйте эмулятор или физическое устройство под управлением Android 8.0 (уровень API 26) или выше, чтобы проверить ваше приложение. Для получения дополнительной информации о том, как создать эмулятор, см. Создание и управление виртуальными устройствами .
Установите сервис автозаполнения
Прежде чем вы сможете проверить свое приложение с помощью автозаполнения, вам необходимо установить другое приложение, которое предоставляет услуги автозаполнения. Для этой цели вы можете использовать стороннее приложение, но легче использовать образец службы автозаполнения, чтобы вам не нужно регистрироваться на службы сторонних сторон.
Вы можете использовать образец Android AutoBill Framework в Java , чтобы проверить ваше приложение с помощью служб автопроизводства. Приложение примера предоставляет услуги автозаполнения и классы Activity
клиента, которые вы можете использовать для тестирования рабочего процесса перед его использованием с вашим приложением. Эта страница ссылается на пример примера Android-AutofillFramework .
После установки приложения включите службу автозаполнения в настройках системы эмулятора, навигация на настройки > Система > «Языки и вход» > «Дополнительно» > «Помощь вводах» > «Служба автопроизводства» .
Проанализировать требования к данным
Чтобы проверить ваше приложение с помощью службы автозаполнения, у сервиса необходимо иметь данные, которые он может использовать для заполнения вашего приложения. Служба также должна понять, какой тип данных ожидается в мнениях вашего приложения. Например, если в вашем приложении есть представление, которое ожидает имя пользователя, у сервиса должен быть набор данных, который содержит имя пользователя и некоторый механизм, чтобы знать, что представление ожидает таких данных.
Расскажите службу, какой тип данных ожидается в ваших представлениях, установив атрибут android:autofillHints
. Некоторые службы используют сложную эвристику для определения типа данных, но другие, такие как приложение Sample, полагаются на разработчик, чтобы предоставить эту информацию. Ваше приложение работает лучше с службами автозаполнения, если вы устанавливаете атрибут android:autofillHints
в представлениях, которые имеют отношение к автозаполнению.
Запустите свой тест
После анализа требований к данным вы можете запустить свой тест, который включает в себя сохранение тестовых данных в службе автозаполнения и запуск автозаполнения в вашем приложении.
Сохранить данные в службе
Чтобы сохранить данные в службе автозаполнения, которая в настоящее время активна, сделайте следующее:
- Откройте приложение, содержащее представление, которое ожидает тип данных, которые вы хотите использовать во время вашего теста. Приложение Android-AutofillFramework примером предоставляет пользовательский интерфейс представлениями, которые ожидают несколько типов данных, таких как номера кредитных карт и имена пользователей.
- Нажмите на представление, которое содержит необходимые данные, которые вам нужны.
- Введите значение в представление.
- Нажмите кнопку подтверждения, например, вход или отправьте . Обычно вам нужно отправить форму, прежде чем служба сохранит данные.
- Проверьте запрос разрешения из диалога системы. Системный диалог показывает название сервиса, которая в настоящее время активна, и спрашивает, является ли это сервисом, которую вы хотите использовать в своем тесте. Если вы хотите использовать службу, нажмите « Сохранить» .
Если Android не отображает диалоговое окно разрешения, или если служба не та, которую вы хотите использовать в своем тесте, убедитесь, что служба в настоящее время активна в настройках системы.
Запустите автозаполнение в вашем приложении
Чтобы запустить автозаполнение в вашем приложении, сделайте следующее:
- Откройте свое приложение и перейдите к деятельности, в котором есть представления, которые вы хотите проверить.
- Нажмите на вид, который необходимо заполнить.
- Система отображает пользовательский интерфейс автозаполнения, который содержит наборы данных, которые могут заполнить представление, как показано на рисунке 1.
- Нажмите на набор данных, который содержит данные, которые вы хотите использовать. Видение отображает данные, ранее хранящиеся в службе.
Если Android не отображает пользовательский интерфейс AutoBill, вы можете попробовать следующие параметры устранения неполадок:
- Убедитесь, что представления в вашем приложении используют правильное значение в атрибуте
android:autofillHints
. Список возможных значений для атрибута см. Константы, префиксированныеAUTOFILL_HINT
в классеView
. - Убедитесь, что атрибут
android:importantForAutofill
устанавливается на значение,no
от точки зрения, которое необходимо заполнить, или установить значение, отличное отnoExcludeDescendants
, или одного из его родителей.