Las apps que usan vistas estándar funcionan con Autofill Framework sin necesitar una configuración especial. También puedes optimizar el funcionamiento de tu app con el framework.
Cómo configurar el entorno de autocompletado
En esta sección, se describe cómo configurar la función básica de autocompletado para tu app.
Cómo configurar un servicio de autocompletado
Debes configurar el servicio de autocompletado en tu dispositivo para que tu app use Autofill Framework. Aunque la mayoría de los teléfonos y tablets que ejecutan Android 8.0 (nivel de API 26) y versiones posteriores incluyen un servicio de autocompletado, te recomendamos que uses un servicio de prueba cuando pruebes la app, como el servicio de autocompletado en la muestra de Autofill Framework de Android. Cuando uses un emulador, configura explícitamente un servicio de autocompletado, ya que es posible que el emulador no incluya un servicio predeterminado.
Después de instalar el servicio de autocompletado de prueba desde la app de ejemplo, habilítalo. Para ello, navega a Configuración > Sistema > Idiomas y entrada > Avanzado > Ayuda con métodos de entrada > Servicio Autocompletar.
Si deseas obtener más información sobre la configuración de un emulador para probar el autocompletado, consulta Cómo probar tu app con autocompletado.
Cómo proporcionar sugerencias de autocompletado
El servicio de autocompletado determina el tipo de cada vista con la heurística. Sin embargo, si tu app se basa en esas heurísticas, el comportamiento del autocompletado puede cambiar inesperadamente a medida que la actualizas. Para asegurarte de que el servicio de autocompletado identifique de manera correcta los factores de forma de tu app, proporciona sugerencias de autocompletado.
Puedes configurar sugerencias de autocompletado con el atributo android:autofillHints
. En el siguiente ejemplo, se configura una sugerencia "password"
en un EditText
:
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:autofillHints="password" />
También puedes configurar sugerencias de manera programática con el método setAutofillHints()
como se muestra en el siguiente ejemplo:
Kotlin
val password = findViewById<EditText>(R.id.password) password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD)
Java
EditText password = findViewById(R.id.password); password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);
Cómo incluir constantes de sugerencias predefinidas
Autofill Framework no valida las sugerencias; tan solo se pasan sin cambio ni validación al servicio de autocompletado. Si bien puedes usar cualquier valor, las clases View
y HintConstants
de AndroidX contienen listas de constantes de sugerencias compatibles oficialmente.
Con una combinación de esas constantes, puedes compilar diseños para situaciones comunes de autocompletado:
Credenciales de la cuenta
En un formulario de acceso, puedes incluir sugerencias de credenciales de cuenta, como AUTOFILL_HINT_USERNAME
y AUTOFILL_HINT_PASSWORD
.
Cuando se crea una cuenta nueva, o cuando alguien cambia su nombre de usuario y contraseña, puedes usar AUTOFILL_HINT_NEW_USERNAME
y AUTOFILL_HINT_NEW_PASSWORD
.
Información de tarjeta de crédito
Cuando solicites información de tarjetas de crédito, puedes usar sugerencias como AUTOFILL_HINT_CREDIT_CARD_NUMBER
y AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE
.
Para las fechas de vencimiento de las tarjetas de crédito, realiza una de las siguientes acciones:
- Si estás usando una vista única para la fecha de vencimiento, utiliza
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE
. - Si usas una vista diferente para cada parte de la fecha de vencimiento, puedes utilizar
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY
,AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH
yAUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR
para cada vista respectiva.
Dirección física
Para los campos del formulario relacionados con la dirección física, puedes usar sugerencias como las siguientes:
- Para una dirección en una sola vista, usa
AUTOFILL_HINT_POSTAL_ADDRESS
. - Si usas vistas separadas para distintas partes de una dirección, puedes utilizar cualquiera de las siguientes opciones:
Nombres de personas
Cuando solicites nombres de personas, puedes usar sugerencias como las siguientes:
- Para autocompletar el nombre completo de una persona en una vista única, usa
AUTOFILL_HINT_PERSON_NAME
. - Si usas vistas separadas para diferentes partes de un nombre, puedes utilizar cualquiera de las siguientes opciones:
Números de teléfono
Para números de teléfono, puedes usar lo siguiente:
- Para solicitar un número de teléfono completo en una vista única, usa
AUTOFILL_HINT_PHONE_NUMBER
. - Si usas vistas separadas para diferentes partes de un número de teléfono, puedes utilizar cualquiera de las siguientes opciones:
Contraseña de un solo uso (OTP)
Para una contraseña de un solo uso en una vista única, puedes utilizar AUTOFILL_HINT_SMS_OTP
.
Cuando se usan varias vistas y cada una se mapea a un solo dígito de la OTP, puedes utilizar el método generateSmsOtpHintForCharacterPosition()
para generar sugerencias por carácter.
Cómo marcar campos como importantes para el autocompletado
Puedes incluir los campos individuales en tu app en una estructura de vistas para fines de autocompletado. De forma predeterminada, las vistas usan el modo IMPORTANT_FOR_AUTOFILL_AUTO
, que le permite a Android usar su heurística para determinar si una vista es importante para el autocompletado.
Sin embargo, hay casos en los que una vista, una estructura de vistas o toda la actividad no son importantes para el autocompletado:
- Un campo
CAPTCHA
en una actividad de acceso - Una vista en la que el usuario crea contenido, como un editor de texto o de hoja de cálculo
- Las vistas en algunas actividades dentro de los juegos, como las que muestran contenido
Puedes establecer la importancia de una vista para el autocompletado con el atributo android:importantForAutofill
:
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:importantForAutofill="no" />
El valor de importantForAutofill
puede ser cualquiera de los siguientes:
auto
- Deja que el sistema Android use su heurística para determinar si la vista es importante para el autocompletado.
no
- Esta vista no es importante para el autocompletado.
noExcludeDescendants
- Esta vista y sus elementos secundarios no son importantes para el autocompletado.
yes
- Esta vista es importante para el autocompletado.
yesExcludeDescendants
- Esta vista es importante para el autocompletado, pero sus elementos secundarios no lo son.
También puedes usar el método setImportantForAutofill()
:
Kotlin
val captcha = findViewById<TextView>(R.id.captcha) captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO)
Java
TextView captcha = findViewById(R.id.captcha); captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
Puedes declarar los casos de uso de ejemplo anteriores como no importantes para el autocompletado de la siguiente manera:
- Un campo
CAPTCHA
en una actividad de acceso: usaandroid:importantForAutofill="no"
oIMPORTANT_FOR_AUTOFILL_NO
para marcar esta vista como no importante. - Una vista en la que el usuario crea contenido: usa
android:importantForAutofill="noExcludeDescendants"
oIMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
para marcar toda la estructura de vistas como no importante. - Las vistas en algunas actividades dentro de los juegos: usa
android:importantForAutofill="noExcludeDescendants"
oIMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
para marcar toda la estructura de vistas como no importante.
Cómo asociar datos de un sitio web y de apps para dispositivos móviles
Los servicios de autocompletado, como Autocompletar con Google, pueden compartir datos de acceso de usuarios entre navegadores y dispositivos Android después de asociar la app y un sitio web. Cuando un usuario selecciona el mismo servicio de autocompletado en ambas plataformas, el acceso a tu app web hace que sus credenciales de acceso estén disponibles para el autocompletado cuando accedan a tu app para Android correspondiente.
Para asociar tu app para Android con tu sitio web, debes alojar un vínculo de recursos digitales con la relación delegate_permission/common.get_login_creds
en tu sitio. Luego, debes declarar la asociación en el archivo AndroidManifest.xml
de tu app. Si deseas obtener instrucciones a fin de asociar tu sitio web con tu app para Android, consulta Cómo habilitar el acceso automático en todas las apps y sitios web.
Cómo completar un flujo de trabajo de autocompletado
En esta sección, se describen situaciones específicas en las que puedes seguir algunos pasos para mejorar la funcionalidad de autocompletado de los usuarios de tu app.
Cómo determinar si está habilitada la función de autocompletado
Los usuarios pueden habilitar o inhabilitar el autocompletado, así como cambiar el servicio de autocompletado, navegando a Configuración > Sistema > Idiomas y entrada > Avanzado > Ayuda con métodos de entrada > Servicio de autocompletado. Tu app no puede anular los parámetros de configuración de autocompletado del usuario, pero puedes implementar funciones de autocompletado adicionales en tu app, o en vistas específicas de esta, si la función de autocompletado está disponible para el usuario.
Por ejemplo, TextView
muestra una entrada de autocompletado en el menú ampliado si el autocompletado está habilitado para el usuario. Para verificar si está habilitado, llama al método isEnabled()
del objeto AutofillManager
.
Para asegurarte de que tu experiencia de registro y acceso esté optimizada para los usuarios sin autocompletado, implementa el acceso con One Tap.
Cómo forzar una solicitud de autocompletado
En ocasiones, es posible que debas forzar una solicitud de autocompletado para que ocurra en respuesta a una acción del usuario. Por ejemplo, TextView
ofrece un elemento de menú de autocompletado cuando el usuario mantiene presionada la vista.
En el siguiente ejemplo de código, se muestra cómo forzar una solicitud de autocompletado:
Kotlin
fun eventHandler(view: View) { val afm = requireContext().getSystemService(AutofillManager::class.java) afm?.requestAutofill(view) }
Java
public void eventHandler(View view) { AutofillManager afm = context.getSystemService(AutofillManager.class); if (afm != null) { afm.requestAutofill(view); } }
También puedes usar el método cancel()
para cancelar el contexto de autocompletado actual. Esto puede ser útil si tienes un botón que borra los campos de una página de acceso.
Cómo usar el tipo correcto de autocompletado para los datos en los controles del selector
Los selectores pueden ser útiles para el autocompletado, ya que proporcionan una IU que permite a los usuarios cambiar el valor de un campo que almacena datos de fecha y hora. Por ejemplo, en un formulario de tarjeta de crédito, un selector de fecha permite que los usuarios ingresen o cambien la fecha de vencimiento de su tarjeta de crédito. Sin embargo, debes usar otra vista, como EditText
, para mostrar datos cuando no esté visible el selector.
De forma nativa, un objeto EditText
espera autocompletar datos de tipo AUTOFILL_TYPE_TEXT
.
Si estás usando un tipo diferente de datos, crea una vista personalizada que herede contenido de EditText
y use los métodos obligatorios para procesar el tipo de datos correspondiente. Por ejemplo, si tienes un campo de datos, implementa los métodos con una lógica que procese correctamente valores de tipo AUTOFILL_TYPE_DATE
.
Cuando especificas el tipo de datos de autocompletado, el servicio de autocompletado puede crear una representación adecuada de los datos que se muestran en la vista. Para obtener más información, consulta Cómo usar los selectores con autocompletado.
Cómo finalizar el contexto de autocompletado
Autofill Framework guarda la entrada del usuario para usarla más tarde y muestra el diálogo "¿Save for autofill?" cuando finaliza el contexto de autocompletado. Por lo general, el contexto de autocompletado finaliza cuando se completa una actividad. Sin embargo, hay algunas situaciones en las que debes notificar al framework de forma explícita, por ejemplo, si usas la misma actividad, pero diferentes fragmentos para las pantallas de acceso y de contenido. En esas situaciones, puedes finalizar explícitamente el contexto llamando a AutofillManager.commit()
.
Compatibilidad para vistas personalizadas
Las vistas personalizadas pueden especificar los metadatos expuestos en Autofill Framework mediante la API de autocompletado. Algunas vistas actúan como un contenedor de elementos secundarios virtuales, como las que contienen una IU procesada por OpenGL. Esas vistas deben usar la API para especificar la estructura de la información que se usa en la app antes de que puedan trabajar con Autofill Framework.
Si tu app usa vistas personalizadas, ten en cuenta las siguientes situaciones:
- La vista personalizada proporciona una estructura de vistas estándar o predeterminada.
- La vista personalizada tiene una estructura virtual o una estructura de vistas que no está disponible para Autofill Framework.
Vistas personalizadas con estructura de vistas estándar
Las vistas personalizadas pueden definir los metadatos que el autocompletado necesita para funcionar. Asegúrate de que la vista personalizada administre los metadatos de forma correcta para trabajar con Autofill Framework. Tu vista personalizada debe realizar las siguientes acciones:
- Procesar el valor de autocompletado que el framework envía a tu app
- Proporcionar el tipo y el valor de autocompletado en el framework
Cuando se activa el autocompletado, Autofill Framework llama a autofill()
en tu vista y envía el valor que se debe usar. Implementa autofill()
para especificar cómo tu vista personalizada procesa el valor de autocompletado.
La vista debe especificar un tipo y valor de autocompletado anulando los métodos getAutofillType()
y getAutofillValue()
, respectivamente.
Por último, el autocompletado no debe llenar la vista si el usuario no puede proporcionar un valor para la vista en su estado actual (por ejemplo, si está inhabilitada).
En estos casos, getAutofillType()
debe mostrar AUTOFILL_TYPE_NONE
, getAutofillValue()
debe mostrar null
y autofill()
no debe hacer nada.
Los siguientes casos requieren pasos adicionales para funcionar correctamente en el framework:
- La vista personalizada se puede editar.
- La vista personalizada contiene datos sensibles.
La vista personalizada se puede editar
Si se puede editar la vista, notifica a Autofill Framework acerca de los cambios llamando a notifyValueChanged()
en el objeto AutofillManager
.
La vista personalizada contiene datos sensibles
Si una vista contiene información de identificación personal (PII), como direcciones de correo electrónico, números de tarjeta de crédito y contraseñas, se debe marcar como sensible.
En general, las vistas cuyo contenido proviene de recursos estáticos no contienen datos sensibles, pero las vistas cuyo contenido se configura de forma dinámica pueden tenerlos. Por ejemplo, una etiqueta que dice Ingresa tu nombre de usuario no contiene datos sensibles, mientras que una etiqueta que dice Hola, Juan sí lo hace.
Nota: Autofill Framework supone que todos los datos son sensibles de forma predeterminada. Puedes marcar los datos que no son sensibles.
Para marcar si una vista contiene datos sensibles, implementa onProvideAutofillStructure()
y llama a setDataIsSensitive()
en el objeto ViewStructure
.
En el siguiente ejemplo de código, se muestra cómo marcar los datos en la estructura de vistas como no sensibles:
Kotlin
override fun onProvideAutofillStructure(structure: ViewStructure, flags: Int) { super.onProvideAutofillStructure(structure, flags) structure.setDataIsSensitive(false) }
Java
@Override public void onProvideAutofillStructure(ViewStructure structure, int flags) { super.onProvideAutofillStructure(structure, flags); structure.setDataIsSensitive(false); }
Si la vista solo acepta valores predefinidos, puedes usar el método setAutofillOptions()
para configurar las opciones que se pueden usar para autocompletar la vista. En particular, las vistas cuyo tipo de autocompletado es AUTOFILL_TYPE_LIST
deben usar este método, ya que el servicio de autocompletado funciona mejor si conoce las opciones disponibles para llenar la vista.
Las vistas que usan un adaptador, como un Spinner
son un caso similar. Por ejemplo, un ícono giratorio que proporciona años creados de forma dinámica (según el año actual) para usar en campos de vencimiento de tarjetas de crédito puede implementar el método getAutofillOptions()
de la interfaz Adapter
para ofrecer una lista de años.
Las vistas que usan un ArrayAdapter
también pueden proporcionar listas de valores. ArrayAdapter
configura automáticamente las opciones de autocompletado para los recursos estáticos.
Si proporcionas los valores de forma dinámica, anula getAutofillOptions()
.
Vistas personalizadas con estructura virtual
Autofill Framework requiere una estructura de vistas para poder editar y guardar la información en la IU de tu app. La estructura de vistas no está disponible para el framework en las siguientes situaciones:
- La app usa un motor de renderización de bajo nivel, como OpenGL, para renderizar la IU.
- La app usa una instancia de
Canvas
para dibujar la IU.
En esos casos, puedes especificar una estructura de vistas implementado onProvideAutofillVirtualStructure()
y siguiendo estos pasos:
- Aumenta el recuento de elementos secundarios de la estructura de vistas llamando a
addChildCount()
. - Para agregar un elemento secundario, llama a
newChild()
. - Configura el ID de autocompletado para el elemento secundario llamando a
setAutofillId()
. - Configura las propiedades relevantes, como el valor y el tipo de autocompletado.
- Si los datos del elemento secundario virtual son sensibles, pasa
true
asetDataIsSensitive()
. De lo contrario, pasafalse
.
En el siguiente fragmento de código, se muestra cómo crear un nuevo elemento secundario en la estructura virtual:
Kotlin
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) }
Java
@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); }
Cuando cambian los elementos de una estructura virtual, notifica al framework con la realización de las siguientes tareas:
- Si cambia el foco de los elementos secundarios, llama a
notifyViewEntered()
ynotifyViewExited()
en el objetoAutofillManager
. - Si cambia el valor de un elemento secundario, llama a
notifyValueChanged()
en el objetoAutofillManager
. - Si la jerarquía de vistas ya no está disponible porque el usuario completó un paso del flujo de trabajo, como cuando accede mediante un formulario de acceso, llama a
commit()
en el objetoAutofillManager
. - Si la jerarquía de vistas no es válida porque el usuario canceló un paso del flujo de trabajo, como cuando presiona un botón que borra un formulario de acceso, llama a
cancel()
en el objetoAutofillManager
.
Cómo usar devoluciones de llamada en eventos de autocompletado
Si tu app proporciona sus propias vistas de autocompletado, necesitas un mecanismo que le indique que habilite o inhabilite las vistas en respuesta a los cambios en la indicación visual de autocompletado de la IU. Autofill Framework proporciona este mecanismo en la forma de AutofillCallback
.
Esta clase proporciona el método onAutofillEvent(View, int)
, al que la app llama después de un cambio en el estado de autocompletado asociado a una vista.
También hay una versión sobrecargada de este método, que incluye un parámetro childId
que tu app puede usar con vistas virtuales. Los estados disponibles se definen como constantes en la devolución de llamada.
Puedes registrar una devolución de llamada con un método registerCallback()
de la clase AutofillManager
. En el siguiente ejemplo de código, se muestra cómo declarar una devolución de llamada para eventos de autocompletado:
Kotlin
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. } } } })
Java
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; } } });
Cuando llegue el momento de quitar la devolución de llamada, usa el método unregisterCallback()
.
Cómo personalizar el elemento de diseño destacado del autocompletado
Cuando se autocompleta una vista, la plataforma renderiza un Drawable
sobre la vista para indicar que se autocompletó su contenido. De forma predeterminada, el elemento de diseño es un rectángulo sólido con un color translúcido apenas más oscuro que el color del tema que se usa para dibujar fondos. No es necesario cambiar el elemento de diseño, pero se puede personalizar con la anulación del elemento android:autofilledHighlight
del tema que usa la aplicación o la actividad, como se muestra en este ejemplo:
<resources>
<style name="MyAutofilledHighlight" parent="...">
<item name="android:autofilledHighlight">@drawable/my_drawable</item>
</style>
</resources>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4DFF0000" />
</shape>
<application ...
android:theme="@style/MyAutofilledHighlight">
<!-- or -->
<activity ...
android:theme="@style/MyAutofilledHighlight">
Cómo autenticar para el autocompletado
Un servicio de autocompletado puede requerir que el usuario se autentique antes de que el servicio pueda completar campos en tu app, en cuyo caso el sistema Android inicia la actividad de autenticación del servicio como parte de la pila de tu actividad.
No necesitas actualizar tu app para admitir la autenticación, porque esta ocurre dentro del servicio. Sin embargo, debes asegurarte de que la estructura de vistas de la actividad se conserve cuando se reinicie la actividad (por ejemplo, creando la estructura de vistas en onCreate()
, no en onStart()
ni onResume()
).
Puedes verificar cómo se comporta tu app cuando un servicio de autocompletado requiere autenticación. Para ello, utiliza HeuristicsService de la muestra AutofillFramework y configúralo para requerir autenticación de respuesta de completado. También puedes usar el ejemplo de BadViewStructureCreationSignInActivity para emular esta cuestión.
Cómo asignar IDs de autocompletado a vistas recicladas
Los contenedores que reciclan vistas, como la clase RecyclerView
, son útiles para las apps que necesitan mostrar listas de desplazamiento de elementos basadas en grandes conjuntos de datos. A medida que el contenedor se desplaza, el sistema reutiliza las vistas del diseño, pero las vistas tienen contenido nuevo.
Si se completa el contenido inicial de una vista reciclada, el servicio de autocompletado retiene el significado lógico de las vistas utilizando sus IDs de autocompletado. Surge un problema cuando, a medida que el sistema reutiliza las vistas del diseño, los IDs lógicos de las vistas siguen siendo iguales, lo que provoca que los datos de autocompletado incorrectos del usuario se asocien con un ID de autocompletado.
Para solucionar este problema en dispositivos que ejecutan Android 9 (nivel de API 28) y versiones posteriores, puedes administrar explícitamente el ID de autocompletado de las vistas que usa RecyclerView
con estos métodos:
- El método
getNextAutofillId()
obtiene un nuevo ID de autocompletado que es exclusivo de la actividad. - El método
setAutofillId()
configura el ID de autocompletado único y lógico de esta vista en la actividad.
Cómo abordar problemas conocidos
En esta sección, se presentan soluciones alternativas a problemas conocidos dentro de Autofill Framework.
La función Autocompletar hace que las apps fallen en Android 8.0 y 8.1
En Android 8.0 (nivel de API 26) y 8.1 (nivel de API 27), el autocompletado puede hacer que tu app falle en determinadas situaciones. Para solucionar cualquier problema potencial, etiqueta las vistas que no se autocompletan con importantForAutofill=no
. También puedes etiquetar toda la actividad con importantForAutofill=noExcludeDescendants
.
Los diálogos que cambiaron de tamaño no se tienen en cuenta para el autocompletado
En Android 8.1 (nivel de API 27) y versiones anteriores, si una vista de un diálogo cambia de tamaño después de mostrarse, no se considera para autocompletado. Esas vistas no están incluidas en el objeto AssistStructure
que el sistema Android envía al servicio de autocompletado. Como resultado, el servicio no puede completar las vistas.
Para evitar ese problema, reemplaza la propiedad token
de los parámetros de la ventana de diálogo con la propiedad token
de la actividad que crea el diálogo. Después de validar la habilitación del autocompletado, guarda los parámetros de la ventana en el método onWindowAttributesChanged()
de la clase que hereda de Dialog
. Luego, reemplaza la propiedad token
de los parámetros guardados con la propiedad token
de la actividad superior en el método onAttachedToWindow()
.
En el siguiente fragmento de código, se muestra una clase que implementa la solución alternativa:
Kotlin
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() } }
Java
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(); } }
Para evitar operaciones innecesarias, el siguiente fragmento de código muestra cómo verificar si el autocompletado es compatible con el dispositivo y si está habilitado para el usuario actual, además de si se requiere esta solución alternativa:
Kotlin
// 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 }
Java
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(); } }
Cómo probar tu app con autocompletado
Después de optimizar tu app para que funcione con los servicios de autocompletado, prueba si funciona según lo previsto con los servicios de autocompletado.
Para poder probar tu app, debes usar un emulador o un dispositivo físico que ejecute Android 8.0 (nivel de API 26) o versiones posteriores. Si deseas obtener más información para crear un emulador, consulta Cómo crear y administrar dispositivos virtuales.
Cómo instalar un servicio de autocompletado
Antes de poder probar tu app con autocompletado, debes instalar otra app que ofrezca esos servicios. Puede usar una app de terceros para este propósito, pero es más fácil usar un servicio de autocompletado de muestra para que no debas registrarte en ningún servicio de terceros.
Puedes usar la muestra de Autofill Framework de Android en Java para probar tu app con servicios de autocompletado. La app de ejemplo proporciona un servicio de autocompletado y clases Activity
de cliente que puedes usar para probar el flujo de trabajo antes de usarlo con tu app. En esta página, se hace referencia a la app de ejemplo android-AutofillFramework.
Después de instalar la app, habilita el servicio de autocompletado en la configuración del sistema del emulador. Para ello, navega aConfiguración > Sistema > Idiomas y entrada > Avanzado > Ayuda con métodos de entrada > Servicio Autocompletar.
Cómo analizar requisitos de datos
Para probar tu app con el servicio de autocompletado, este debe tener datos que se puedan usar para tal fin. El servicio también debe comprender qué tipo de datos se esperan en las vistas de tu app. Por ejemplo, si la app tiene una vista que espera un nombre de usuario, el servicio debe tener un conjunto de datos que contenga un nombre de usuario y algún mecanismo para saber que la vista espera esos datos.
Para indicarle al servicio qué tipo de datos se esperan en tus vistas, configura el atributo android:autofillHints
. Algunos servicios usan heurísticas sofisticadas para determinar el tipo de datos, pero otros, como la app de ejemplo, confían en el desarrollador para proporcionar esta información. Tu app funciona mejor con los servicios de autocompletado si configuras el atributo android:autofillHints
en las vistas que son relevantes para ello.
Cómo realizar la prueba
Después de analizar los requisitos de datos, puedes realizar tu prueba, que incluye guardar los datos de la prueba en el servicio de autocompletado y activar el autocompletado en tu app.
Cómo guardar datos en el servicio
Para guardar datos en el servicio de autocompletado actualmente activo, haz lo siguiente:
- Abre una app que contenga una vista que espere el tipo de datos que quieres usar durante tu prueba. La app de muestra android-AutofillFramework proporciona a la IU vistas que esperan varios tipos de datos, como números de tarjeta de crédito y nombres de usuario.
- Presiona la vista que tiene el tipo de datos que necesitas.
- Ingresa un valor en la vista.
- Presiona el botón de confirmación, como Acceder o Enviar. Por lo general, debes enviar el formulario antes de que el servicio guarde los datos.
- Verifica la solicitud de permiso del diálogo del sistema. El diálogo del sistema muestra el nombre del servicio que está activo y pregunta si es el servicio que deseas utilizar en tu prueba. Si quieres usar el servicio, presiona Guardar.
Si Android no muestra el diálogo de permisos o si el servicio no es el que quieres usar en tu prueba, comprueba que el servicio esté activo en la configuración del sistema.
Cómo activar el autocompletado en tu app
Para activar el autocompletado en tu app, haz lo siguiente:
- Abre la app y busca la actividad que tenga las vistas que quieras probar.
- Presiona la vista que se debe completar.
- El sistema muestra la IU de autocompletado, que contiene los conjuntos de datos que pueden llenar la vista, como se muestra en la Figura 1.
- Presiona el conjunto de datos que contenga los datos que quieras usar. La vista muestra los datos almacenados previamente en el servicio.
Si Android no muestra la IU de autocompletado, puedes probar las siguientes opciones para solucionar problemas:
- Comprueba que las vistas de tu app utilicen el valor correcto en el atributo
android:autofillHints
. Para obtener una lista de posibles valores para el atributo, consulta las constantes con el prefijoAUTOFILL_HINT
en la claseView
. - Comprueba que el atributo
android:importantForAutofill
esté configurado en un valor diferente ano
en la vista que se debe completar, o configura un valor diferente anoExcludeDescendants
en la vista o uno de sus elementos superiores.