Habilita la indexación de contenido personal

Con la indexación de contenido personal, la app genera resultados de la búsqueda en Google app que incluyen contenido vinculado con la cuenta del usuario. Los usuarios solo ven contenido personal en sus dispositivos en los resultados personales y en las sugerencias de Búsqueda.

Por ejemplo, si un usuario busca “receta de pollo favorita”, la pestaña de resultados personales incluye la nota que agregó a una receta de pollo en una app culinaria.

Si la app no incluye contenido personal, puedes omitir este paso y dirigirte directamente a Registra acciones de los usuarios.

Antes de comenzar, asegúrate de admitir vínculos al contenido de la app y de agregar la biblioteca de App Indexing a ella.

Establece el índice y agrega objetos

Crea una clase que extienda JobIntentService. La implementación descrita en este documento se basa en la clase JobIntentService para poner en fila las actualizaciones al índice del dispositivo, pero puedes usar una clase alternativa a fin de programar el trabajo. Si realizas la implementación a través de la clase JobIntentService, asegúrate de agregar también la biblioteca de compatibilidad de Android al archivo build.gradle del proyecto.

Para incluir elementos en el índice de contenido personal de la app, crea objetos Indexable en la misma clase:

Tipos de resultados

App Indexing te permite mostrar tus resultados de las siguientes dos maneras:

  • Solo texto: La Búsqueda de Google muestra tu contenido indexado como resultados de texto.
  • Segmentos: La Búsqueda de Google usa segmentos o plantillas de IU de tu app para proporcionar resultados de la búsqueda interactivos y dinámicos.

Puedes elegir el tipo de resultado que mejor se adapte a tu app. Los resultados de solo texto son menos complicados de implementar. Sin embargo, los segmentos ofrecen una mejor experiencia del usuario.

Ejemplo de implementación

Resultados de solo texto

Java
Android

public class AppIndexingUpdateService extends JobIntentService {

    // Job-ID must be unique across your whole app.
    private static final int UNIQUE_JOB_ID = 42;

    public static void enqueueWork(Context context) {
        enqueueWork(context, AppIndexingUpdateService.class, UNIQUE_JOB_ID, new Intent());
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // TODO Insert your Indexable objects — for example, the recipe notes look as follows:

        ArrayList<Indexable> indexableNotes = new ArrayList<>();

        for (Recipe recipe : getAllRecipes()) {
            Note note = recipe.getNote();
            if (note != null) {
                Indexable noteToIndex = Indexables.noteDigitalDocumentBuilder()
                        .setName(recipe.getTitle() + " Note")
                        .setText(note.getText())
                        .setUrl(recipe.getNoteUrl())
                        .build();

                indexableNotes.add(noteToIndex);
            }
        }

        if (indexableNotes.size() > 0) {
            Indexable[] notesArr = new Indexable[indexableNotes.size()];
            notesArr = indexableNotes.toArray(notesArr);

            // batch insert indexable notes into index
            FirebaseAppIndex.getInstance().update(notesArr);
        }
    }

    // ...
}

Kotlin
Android

class AppIndexingUpdateService : JobIntentService() {

    companion object {

        // Job-ID must be unique across your whole app.
        private const val UNIQUE_JOB_ID = 42

        fun enqueueWork(context: Context) {
            JobIntentService.enqueueWork(context, AppIndexingUpdateService::class.java, UNIQUE_JOB_ID, Intent())
        }
    }

    override fun onHandleWork(intent: Intent) {
        // TODO Insert your Indexable objects — for example, the recipe notes look as follows:

        val indexableNotes = arrayListOf<Indexable>()

        for (recipe in getAllRecipes()) {
            val note = recipe.note
            if (note != null) {
                val noteToIndex = Indexables.noteDigitalDocumentBuilder()
                        .setName(recipe.title + " Note")
                        .setText(note.text)
                        .setUrl(recipe.noteUrl)
                        .build()

                indexableNotes.add(noteToIndex)
            }
        }

        if (indexableNotes.size > 0) {
            val notesArr: Array<Indexable> = indexableNotes.toTypedArray()

            // batch insert indexable notes into index
            FirebaseAppIndex.getInstance().update(*notesArr)
        }
    }

    // ...
}
Resultados en segmentos

Los segmentos te permiten designar porciones de tu app para que aparezcan como resultados de la Búsqueda de Google. Actúan como una IU para el contenido de objetos Indexables, por lo que cada segmento debería asignarse a un objeto Indexable. Sigue estos pasos para generar resultados en segmentos de tu app:

  1. Sigue las instrucciones de la Guía de introducción a los segmentos para agregar segmentos a tu app.
  2. Agrega objetos Indexables con los agentes de escucha y los metadatos de los segmentos:
package com.example.myapp;

import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import com.google.firebase.appindexing.builders.Indexables;
import com.google.firebase.appindexing.FirebaseAppIndex;
import com.google.firebase.appindexing.Indexable;
import java.util.ArrayList;

public class AppIndexingUpdateService extends JobIntentService {
  // Job-ID must be unique across your whole app.
  private static final int UNIQUE_JOB_ID = 42;

  public static void enqueueWork(Context context) {
    enqueueWork(context, AppIndexingUpdateService.class, UNIQUE_JOB_ID, new Intent());
  }

  @Override
  protected void onHandleWork(@NonNull Intent intent) {
    // TODO Insert your Indexable objects — for example, the recipe notes look as follows:

    ArrayList<Indexable> indexableNotes = new ArrayList<>();

    for (Recipe recipe : getAllRecipes()) {
        Note note = recipe.getNote();
        if (note != null) {
            Indexable noteToIndex = Indexables.noteDigitalDocumentBuilder()
                    .setName(recipe.getTitle() + " Note")
                    .setText(note.getText())
                    .setUrl(recipe.getNoteUrl())
                    .setMetadata(
                      new Indexable.Metadata.Builder().setSliceUri(
                        Uri.parse("content://com.example.myapp.sliceprovider/note?id=" +
                                  recipe.getNoteId())
                    ))
                    .build();

            indexableNotes.add(noteToIndex);
        }
    }

    if (indexableNotes.size() > 0) {
        Indexable[] notesArr = new Indexable[indexableNotes.size()];
        notesArr = indexableNotes.toArray(notesArr);

        // batch insert indexable notes into index
        FirebaseAppIndex.getInstance().update(notesArr)
                        .addOnSuccessListener(unused -> {
                          Log.d("RecipeApp", "Update succeeded!");
                        })
                        .addOnFailureListener(exception -> {
                          Log.d("RecipeApp", "Update failed: " + exception);
                        });
    }
  }
}

¿Qué debe incluir el índice de contenido personal?

Define los objetos Indexable para los siguientes tipos de contenido:

  • El contenido específico de los usuarios, como mensajes, fotos o documentos.
  • El contenido que es importante para los usuarios, como sus favoritos o el contenido al que, tal vez, quieran acceder con más frecuencia. Por ejemplo, los documentos o las canciones que marcaron o seleccionaron para usar sin conexión.
  • El contenido que se genera dentro de la app, no solo el que se consulta mediante ella. Por ejemplo, los contactos que crean los usuarios directamente dentro de la app y que se almacenan en esta, en lugar de los contactos del directorio del teléfono.

Agrega un receptor de emisión a la app

Los Servicios de Google Play envían periódicamente una solicitud a la app para actualizar el índice del dispositivo. Esta acción permite que el índice tenga el contenido más reciente de tu app en el dispositivo. La clase BroadcastReceiver recibe esta solicitud y activa JobIntentService para procesar el trabajo de indexación. El siguiente ejemplo usa la clase AppIndexingUpdateService del paso anterior.

Java
Android

/** Receives broadcast for App Indexing Update. */
public class AppIndexingUpdateReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null
                && FirebaseAppIndex.ACTION_UPDATE_INDEX.equals(intent.getAction())) {
            // Schedule the job to be run in the background.
            AppIndexingUpdateService.enqueueWork(context);
        }
    }

}

Kotlin
Android

/** Receives broadcast for App Indexing Update. */
class AppIndexingUpdateReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent?) {
        if (intent != null && FirebaseAppIndex.ACTION_UPDATE_INDEX == intent.action) {
            // Schedule the job to be run in the background.
            AppIndexingUpdateService.enqueueWork(context)
        }
    }
}

Genera y actualiza el índice

A continuación, permite que los Servicios de Google Play llamen al servicio de Indexación de aplicaciones para actualizar el índice en el dispositivo con el contenido personal del usuario en estas tres situaciones:

  • Cuando la app se instala en un dispositivo.
  • Si se actualiza una versión existente de la app a una versión compatible con la indexación de contenido personal.
  • Llamadas periódicas para reflejar correctamente los cambios que se produzcan en el contenido indexado a fin de garantizar una experiencia del usuario sin problemas.

Además, si se pierde el índice en el dispositivo por algún motivo (p. ej., si se daña), esta llamada para actualizar el índice restablecerá el contenido.

En el archivo AndroidManifest.xml, registra el BroadcastReceiver para que pueda recibir llamadas desde Servicios de Google Play y actualizar el índice. En el siguiente ejemplo, se usa la clase JobIntentService para programar las actualizaciones de indexación:

<!-- Register the BroadcastReceiver -->
<receiver
    android:name=".AppIndexingUpdateReceiver"
    android:exported="true"
    android:permission="com.google.android.gms.permission.APPINDEXING">
    <intent-filter>
        <action android:name="com.google.firebase.appindexing.UPDATE_INDEX" />
    </intent-filter>
</receiver>

<!-- Grant the AppIndexingUpdateService permission and enable it to run after being triggered -->
<service
    android:name=".AppIndexingUpdateService"
    android:permission="android.permission.BIND_JOB_SERVICE" />

Actualiza el índice

Cuando los usuarios agregan, actualizan o quitan contenido personal, el índice en el dispositivo debe reflejar esos cambios. Agrega el siguiente código para actualizar el contenido del índice:

Actualiza resultados de solo texto

Java
Android

public void indexNote(Recipe recipe) {
    Note note = recipe.getNote();
    Indexable noteToIndex = Indexables.noteDigitalDocumentBuilder()
            .setName(recipe.getTitle())
            .setText(note.getText())
            .setUrl(recipe.getNoteUrl())
            .build();

    Task<Void> task = FirebaseAppIndex.getInstance().update(noteToIndex);
    // ...
}

Kotlin
Android

fun indexNote(recipe: Recipe) {
    val note = recipe.note
    val noteToIndex = Indexables.noteDigitalDocumentBuilder()
            .setName(recipe.title)
            .setText(note!!.text)
            .setUrl(recipe.noteUrl)
            .build()

    val task = FirebaseAppIndex.getInstance().update(noteToIndex)
    // ...
}
Actualiza segmentos

Firebase App Indexing recupera el contenido del segmento cuando se efectúa la indexación, lo almacena y muestra el resumen del segmento cuando se realiza la consulta. Si el contenido del segmento cambia entre el paso de indexación y el de consulta, el resumen podría ser engañoso o confuso para los usuarios. Si quieres evitar lo anterior, actualiza el segmento y vuelve a indexar el objeto indexable al mismo tiempo a fin de que Firebase App Indexing siempre tenga el contenido más reciente.

private void indexNote() {
  Note note = mRecipe.getNote();
  Indexable noteToIndex = Indexables.noteDigitalDocumentBuilder()
          .setName(mRecipe.getTitle())
          .setText(note.getText())
          .setUrl(mRecipe.getNoteUrl())
          .setKeywords("recipe", "cooking")
          .setMetadata(
              new Indexable.Metadata.Builder().setSliceUri(
              Uri.parse("content://com.example.myapp.sliceprovider/note?id=" + note.getNoteId())))
          .build();

  Task<Void> task = FirebaseAppIndex.getInstance().update(noteToIndex);
   ...
}
Quita elementos

Para identificar los elementos que deben quitarse, usa su URL. Agrega la siguiente línea a la función de borrar o quitar de la app correspondiente a ese elemento.

Java
Android

// Deletes or removes the corresponding notes from index.
String noteUrl = recipe.getNoteUrl();
FirebaseAppIndex.getInstance().remove(noteUrl);

Kotlin
Android

// Deletes or removes the corresponding notes from index.
val noteUrl = recipe.noteUrl
FirebaseAppIndex.getInstance().remove(noteUrl)

Borra el índice cuando los usuarios salgan

Borra el índice en el dispositivo cuando los usuarios salgan de la app, durante el evento de salida. Incluye la llamada para generar y actualizar el índice en el dispositivo a través de AppIndexingService a fin de que este se vuelva a propagar cuando los usuarios accedan nuevamente.

Para borrar el índice en el dispositivo, cuando un usuario sale de la app, agrega el siguiente fragmento de código:

Java
Android

FirebaseAppIndex.getInstance().removeAll();

Kotlin
Android

FirebaseAppIndex.getInstance().removeAll()

Siguiente: Registra las acciones de los usuarios

Enviar comentarios sobre...

Si necesitas ayuda, visita nuestra página de asistencia.