Cómo usar Autorrelleno de Android O Framework
Spanish (Español) translation by Jean Perez (you can also view the original English article)
Relleno de forma automática, a menudo abreviado a simplemente Autorrelleno, es una característica que los navegadores han apoyado por años ahora. Mayoría de nosotros lo usamos todo el tiempo. Para uno, creo que es indispensable durante las tareas de como llenar un formulario de inscripción o completar un proceso de compra.
La última versión de Android, Android O, trae una funcionalidad similar a aplicaciones Android. En otras palabras, Android puede ahora ayudar a los usuarios rellenar formularios que pertenecen a todas las aplicaciones que se han instalado en sus dispositivos. Esto era una característica esperada ya que escribir con un teclado virtual en una pantalla pequeña tiende a ser una molestia.
Como desarrollador de la aplicación, puede utilizar el nuevo marco de Autorrelleno para crear su propio servicio de Autorrellenar personalizada, un servicio que decide cómo rellenar campos de entrada de la aplicación. En este tutorial, le mostraré cómo.
Requisitos Previos
Para poder seguir este tutorial, necesitará:
- Android Studio 2.4 Preview 7 o superior
- Un emulador o un dispositivo corriendo Android O o superior
1. Cree un Nuevo Proyecto
Fuego Android Studio y cree un nuevo proyecto con una actividad vacía. Debe, por supuesto, recordar elegir Android 7 + en el cuadro de diálogo de Dispositivos Android de Destino.



Este proyecto necesitará unos widgets que pertenecen a la biblioteca de soporte de diseño, pues abren archivo build.gradle del módulo de la app y agregue la siguiente dependencia de compile:
1 |
compile 'com.android.support:design:26.+' |
Por último, pulse el botón Sincronizar Ahora para actualizar el proyecto.
2. Crear una Configuración de Actividad
En este tutorial, nos va creando una aplicación que contiene un servicio muy sencillo rellenar eso objetivos solo los campos donde se espera que el usuario escribe una dirección de correo electrónico de entrada. Porque casi cualquier otra aplicación en Google Play hoy pide una dirección de correo electrónico, este servicio será muy útil.
Nuestro servicio obviamente necesita saber son qué direcciones de correo electrónico del usuario. Por lo tanto, ahora construyamos una actividad donde el usuario puede escribir en el y guardar direcciones de dos correos electrónicos.
Paso 1: Definir el Diseño
Como era de esperar, la distribución de la actividad contendrá dos widgets EditText donde el usuario puede escribir sus direcciones de correo electrónico. Si desea adherirse a las directrices de diseño de Material, colocación de los widgets de EditText dentro de contenedores de TextInputLayout es una buena idea.
Además, el diseño debe tener un widget de Button que el usuario puede pulsar para guardar las direcciones de correo electrónico.
Eres libre colocar los widgets en cualquier lugar que desee. Sin embargo, por ahora, sugiero que colocarlos dentro de un LinearLayout cuya orientación es vertical.
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<LinearLayout
|
3 |
xmlns:android="https://schemas.android.com/apk/res/android" |
4 |
android:layout_width="match_parent" |
5 |
android:layout_height="match_parent" |
6 |
android:orientation="vertical" |
7 |
android:padding="16dp"> |
8 |
|
9 |
<android.support.design.widget.TextInputLayout
|
10 |
android:layout_width="match_parent" |
11 |
android:layout_height="wrap_content"> |
12 |
<EditText
|
13 |
android:layout_width="match_parent" |
14 |
android:layout_height="wrap_content" |
15 |
android:id="@+id/primary" |
16 |
android:hint="Your primary email address" |
17 |
android:inputType="textEmailAddress"/> |
18 |
</android.support.design.widget.TextInputLayout>
|
19 |
|
20 |
<android.support.design.widget.TextInputLayout
|
21 |
android:layout_width="match_parent" |
22 |
android:layout_height="wrap_content"> |
23 |
<EditText
|
24 |
android:layout_width="match_parent" |
25 |
android:layout_height="wrap_content" |
26 |
android:id="@+id/secondary" |
27 |
android:hint="Your other email address" |
28 |
android:inputType="textEmailAddress"/> |
29 |
</android.support.design.widget.TextInputLayout>
|
30 |
|
31 |
<Button
|
32 |
android:layout_width="match_parent" |
33 |
android:layout_height="wrap_content" |
34 |
android:id="@+id/save_button" |
35 |
style="@style/Widget.AppCompat.Button.Colored" |
36 |
android:text="Save" |
37 |
android:onClick="saveEmailAddresses"/> |
38 |
|
39 |
</LinearLayout>
|
En el código anterior, se puede ver que el widget de Button tiene un atributo onClick a un método. Haga clic en la bombilla amarilla al lado de este atributo en estudio Android para generar un trozo de ella en la clase de Activity asociado.
1 |
public void saveEmailAddresses(View view) { |
2 |
// More code will be added here
|
3 |
}
|
Paso 2: Guardar las Direcciones de Correo Electrónico
Usaremos un archivo de preferencias compartido llamado EMAIL_STORAGE para guardar nuestros datos. Puede utilizar el método getSharedPreferences() de la clase de Activity para acceder al archivo. Además, para poder escribir en el fichero, debe llamar a su método edit(), que genera un objeto de SharedPreferences.Editor.
Por consiguiente, agregue el siguiente código dentro del método saveEmailAddresses():
1 |
SharedPreferences.Editor editor = |
2 |
getSharedPreferences("EMAIL_STORAGE", MODE_PRIVATE).edit(); |
Para obtener las direcciones de correo electrónico que el usuario ha escrito en los widgets de EditText, debe primero obtener referencias a ellas mediante el método findViewById() y luego llamar a sus métodos getText().
1 |
String primaryEmailAddress = |
2 |
((EditText)findViewById(R.id.primary)) |
3 |
.getText().toString(); |
4 |
|
5 |
String secondaryEmailAddress = |
6 |
((EditText)findViewById(R.id.secondary)) |
7 |
.getText().toString(); |
En este punto, usted puede llamar al método putString() del editor para añadir las direcciones de correo electrónico en el archivo de preferencias como dos pares de valores clave. Después de hacerlo, no olvide llamar al método commit() para hacer los cambios permanentes.
1 |
editor.putString("PRIMARY_EMAIL", primaryEmailAddress); |
2 |
editor.putString("SECONDARY_EMAIL", secondaryEmailAddress); |
3 |
editor.commit(); |
Paso 3: Crear un Archivo de Meta-Datos
La configuración de actividad que creamos en el paso anterior es sólo una actividad ordinaria. Para permitir que la plataforma Android saben que es una configuración de actividad para un servicio de Autorrelleno, debemos crear un archivo XML de metadatos diciendo esto.
Crear un nuevo archivo XML llamado email_address_filler.xml en la carpeta del proyecto res/xml. En su interior, añadir una <autofill-service> etiqueta y conjunto el valor de su settingsActivity atribuyen el nombre de la clase de Activity.
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<autofill-service
|
3 |
xmlns:android="http://schemas.android.com/apk/res/android" |
4 |
android:settingsActivity="com.tutsplus.simplefill.MainActivity"/> |
Puede ahora ejecutar la aplicación, escriba en dos direcciones de correo electrónico y pulse el botón Save para guardarlos.



3. Crear un Servicio de Autorelleno
Cualquier clase que extiende la clase AutoFillService abstracta puede servir como un servicio de recarga automatica. Así que empieza por crear una nueva clase de Java con el Archivo > Nuevo > Clase Java. En el cuadro de diálogo que aparece, nombre de la clase EmailAddressFiller y asegúrese de que define el valor de Superclase del campo AutoFillService.



Estudio Android ahora le pedirá que generar stubs para dos métodos abstractos: onSaveRequest() y onFillRequest(). En este tutorial, nos va centrando sólo en el método onFillRequest(), que se llama automáticamente cuando el usuario abre una actividad — de cualquier aplicación, que contiene campos de entrada.
1 |
@Override
|
2 |
public void onFillRequest(AssistStructure assistStructure, |
3 |
Bundle bundle, |
4 |
CancellationSignal cancellationSignal, |
5 |
FillCallback fillCallback) { |
6 |
|
7 |
// More code goes here
|
8 |
|
9 |
}
|
Paso 1: Analizar Las Jerarquías de la Vista
Un servicio de Autorelleno debe analizar la interfaz de usuario de la aplicación e identificar puede llenar los campos de entrada. Es por ello que el método onFillRequest() recibe un objeto AssistStructure, que contiene información detallada sobre todos los widgets que son actualmente visibles en la pantalla. Más precisamente, contiene un árbol de objetos de ViewNode.
Si nunca has visto un árbol, le sugiero que utilice la herramienta uiautomatorviewer, que forma parte del SDK de Android, para analizar las jerarquías de la disposición de algunas aplicaciones. Por ejemplo, aquí es lo que la jerarquía de diseño de la aplicación de correo predeterminada de Android:



Naturalmente, para analizar todos los nodos de un árbol, necesita un método recursivo. Vamos a crear uno ahora:
1 |
void identifyEmailFields(AssistStructure.ViewNode node, |
2 |
List<AssistStructure.ViewNode> emailFields) { |
3 |
// More code goes here
|
4 |
}
|
Como se puede ver, este método tiene un ViewNode y una list como sus parámetros. Utilizaremos la list para almacenar todos los campos de entrada que direcciones de correo electrónico.
Ahora quizás se pregunte cómo mediante programación puede decir si un campo de entrada espera una dirección de correo electrónico. Bueno, no hay ningún enfoque infalible que puede seguir. Por ahora, vamos a asumir que todos los desarrolladores de app siempre dan números de recursos significativos a los campos de entrada. Basado en que Asunción, podemos simplemente seleccionamos todos los campos de entrada cuyos recursos IDs contienen cadenas como "correo electrónico" y "username".
Por consiguiente, agregue el código siguiente al método:
1 |
if(node.getClassName().contains("EditText")) { |
2 |
String viewId = node.getIdEntry(); |
3 |
if(viewId!=null && (viewId.contains("email") |
4 |
|| viewId.contains("username"))) { |
5 |
emailFields.add(node); |
6 |
return; |
7 |
}
|
8 |
}
|
A continuación, cuando nos encontramos con un objeto ViewNode que contiene más de ViewNode de objetos, tenemos que llamada de forma recursiva el método identifyEmailFields() para analizar a todos sus hijos. El código siguiente muestra cómo:
1 |
for(int i=0; i<node.getChildCount();i++) { |
2 |
identifyEmailFields(node.getChildAt(i), emailFields); |
3 |
}
|
En este punto, podemos llamar al método identifyEmailFields() en el método onFillRequest() y pase el nodo raíz de la jerarquía de la vista a él.
1 |
// Create an empty list
|
2 |
List<AssistStructure.ViewNode> emailFields = new ArrayList<>(); |
3 |
|
4 |
// Populate the list
|
5 |
identifyEmailFields(assistStructure |
6 |
.getWindowNodeAt(0) |
7 |
.getRootViewNode(), emailFields); |
Si nuestro servicio es incapaz de identificar los campos de entrada para mensajes de correo electrónico, no debe hacer nada. Por lo tanto, agregue el código siguiente:
1 |
if(emailFields.size() == 0) |
2 |
return; |
Paso 2: Crear y Rellenar Vistas Remotas
Si nuestro servicio de identificar un campo de entrada puede llenar, debe rellenar una lista desplegable que aparecerá debajo del campo de entrada. Al hacerlo, sin embargo, no es sencillo porque ni en el campo de entrada ni en la lista desplegable pertenece a nuestra aplicación.
Para rellenar la lista desplegable, debemos utilizar objetos RemoteViews. Como su nombre indica, un objeto RemoteViews es una colección de vistas que se pueden mostrar en otra aplicación.
Para inicializar un objeto RemoteViews, necesitará un archivo de esquema XML. Vamos a crear uno ahora se llama email_suggestion.xml. Por ahora, puede contener solo un widget TextView para mostrar una dirección de correo electrónico.
Por consiguiente, agregue el código siguiente a email_suggestion.xml:
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<TextView xmlns:android="http://schemas.android.com/apk/res/android" |
3 |
android:layout_width="wrap_content" |
4 |
android:layout_height="wrap_content" |
5 |
android:id="@+id/email_suggestion_item" |
6 |
android:textSize="18sp" |
7 |
android:textStyle="bold" |
8 |
android:padding="5dp"> |
9 |
</TextView>
|
Ahora puede volver al método de onFillRequest() y crear dos objetos RemoteViews: uno para el correo electrónico principal y otro para el secundario.
1 |
RemoteViews rvPrimaryEmail = |
2 |
new RemoteViews(getPackageName(), |
3 |
R.layout.email_suggestion); |
4 |
|
5 |
RemoteViews rvSecondaryEmail = |
6 |
new RemoteViews(getPackageName(), |
7 |
R.layout.email_suggestion); |
Los widgets de TextView dentro los objetos RemoteViews deben mostrar las direcciones de correo dos electrónico que almacenan en un archivo de preferencias compartidas anteriormente. Para abrir el archivo, utilice el método de getSharedPreferences() otra vez. Una vez abierto, puede utilizar su método getString() para buscar las direcciones de correo electrónico.
Por último, para establecer el contenido de los widgets de TextView remotos, debe utilizar el método setTextViewText().
1 |
// Load the email addresses from preferences
|
2 |
SharedPreferences sharedPreferences = |
3 |
getSharedPreferences("EMAIL_STORAGE", MODE_PRIVATE); |
4 |
|
5 |
String primaryEmail = |
6 |
sharedPreferences.getString("PRIMARY_EMAIL", ""); |
7 |
String secondaryEmail = |
8 |
sharedPreferences.getString("SECONDARY_EMAIL", ""); |
9 |
|
10 |
// Update remote TextViews
|
11 |
rvPrimaryEmail.setTextViewText(R.id.email_suggestion_item, |
12 |
primaryEmail); |
13 |
rvSecondaryEmail.setTextViewText(R.id.email_suggestion_item, |
14 |
secondaryEmail); |
Paso 3: Crear Conjuntos de Datos
Ahora podemos utilizar las vistas remotas para crear conjuntos de datos de Autorrelleno que puede enviarse a cualquier aplicación. Para mantener este tutorial de conseguir demasiado largo, a crear conjuntos de datos sólo para el primer campo de entrada de correo electrónico que nos encontramos. El código siguiente muestra cómo elegir solamente el primer correo electrónico campo:
1 |
AssistStructure.ViewNode emailField = emailFields.get(0); |
Un conjunto de datos de Autorrelleno no es más que una instancia de la clase Dataset y se puede construir utilizando la clase Dataset.Builder.
Cuando el usuario selecciona una de las direcciones de correo electrónico nuestro servicio se muestra en la lista desplegable, debe establecer el contenido del campo de entrada asociado mediante el método setValue() de la clase Dataset.Builder. Sin embargo, se puede pasar un objeto de ViewNode al método setValue(). Realmente espera un identificador de Autorrelleno, que debe ser obtenido llamando al método getAutoFillId() del objeto ViewNode.
Además, para especificar el texto que debe escribirse en el campo de entrada, debe utilizar el método AutoFillValue.forText(). El código siguiente muestra cómo:
1 |
Dataset primaryEmailDataSet = |
2 |
new Dataset.Builder(rvPrimaryEmail) |
3 |
.setValue( |
4 |
emailField.getAutoFillId(), |
5 |
AutoFillValue.forText(primaryEmail) |
6 |
).build(); |
7 |
|
8 |
Dataset secondaryEmailDataSet = |
9 |
new Dataset.Builder(rvSecondaryEmail) |
10 |
.setValue( |
11 |
emailField.getAutoFillId(), |
12 |
AutoFillValue.forText(secondaryEmail) |
13 |
).build(); |
Antes de enviar los conjuntos de datos a una aplicación, debe agregar a un objeto FillResponse, que se puede construir utilizando la clase FillResponse.Builder. Llamar a su método de addDataset() dos veces para agregar los conjuntos de datos.
Una vez que el objeto de FillResponse, pasa como un argumento al método onSuccess() del objeto FillCallback, que es uno de los parámetros del método onFillRequest().
1 |
FillResponse response = new FillResponse.Builder() |
2 |
.addDataset(primaryEmailDataSet) |
3 |
.addDataset(secondaryEmailDataSet) |
4 |
.build(); |
5 |
|
6 |
fillCallback.onSuccess(response); |
Paso 4: Actualizar el Manifiesto
Como todos los servicios, el servicio de Autorelleno también debe declararse en el archivo del proyecto AndroidManifest.xml. Al hacerlo, debe asegurarse de que está protegido por el permiso de android.permission.BIND_AUTO_FILL.
Este servicio también tiene un <intent-filter> etiqueta que le permite responder a la acción de android.service.autofill.AutoFillService, y un <meta-data> etiqueta que señala el archivo XML de metadatos que creamos en un paso anterior.
Por consiguiente, agregar las siguientes líneas a su archivo de manifiesto:
1 |
<service android:name=".EmailAddressFiller" |
2 |
android:permission="android.permission.BIND_AUTO_FILL"> |
3 |
<meta-data android:name="android.autofill" |
4 |
android:resource="@xml/email_address_filler"/> |
5 |
<intent-filter>
|
6 |
<action android:name="android.service.autofill.AutoFillService"/> |
7 |
</intent-filter>
|
8 |
</service>
|
Nuestro servicio de autorrelleno y aplicación están listos. Genere el proyecto e instalar la aplicación en el dispositivo.
4. Activar y Utilizar el Servicio de Autorelleno
Para activar el servicio de Autorrelleno, abre la aplicación Configuración y vaya a Aplicaciones y Notificaciones > Avanzado > Default apps > Autorrelleno App. En la siguiente pantalla, seleccione su aplicación de la lista de aplicaciones disponibles de Autorrelleno.



Ahora puede abrir cualquier aplicación que solicite una dirección de correo electrónico ver su servicio de Autorrelleno en acción. Por ejemplo, aquí es lo que verá en las pantallas de inicio de sesión de Instagram y Pinterest:



Conclusión
Ahora sabes cómo crear y utilizar un servicio personalizado de Autorrelleno para Android. No dude en ampliar para apoyar otros campos comunes, como el nombre o número de teléfono. Asimismo puede tratar de identificar los campos de entrada con otros atributos, tales como etiquetas y notas.
Para saber más sobre el Framework de Autorrelleno, consulte su documentación oficial. Y mientras tanto, algunos de nuestros otros posts sobre Android O y desarrollo de aplicaciones Android!









