Ir para o console

Ativar indexação de conteúdo pessoal

Com a indexação de conteúdo pessoal, seu aplicativo oferece resultados da pesquisa no Google app para conteúdo vinculado a uma conta de usuário. Usuários veem somente o próprio conteúdo pessoal nos dispositivos deles, seja nas Sugestões de pesquisa ou nos Resultados personalizados.

Por exemplo, se um usuário pesquisar "receita favorita de frango", a guia de resultados pessoal inclui a nota adicionada pelo usuário a uma receita de frango do app de receita.

Caso seu aplicativo não inclua conteúdo pessoal, ignore esta etapa e vá diretamente para Registrar ações do usuário.

Antes de começar, aceite links no conteúdo do app e verifique se adicionou a biblioteca do Indexação de apps ao aplicativo.

Estabelecer o índice e adicionar objetos

Crie uma classe que amplie a JobIntentService. A implementação descrita neste documento baseia-se na classe JobIntentService para enfileirar as atualizações para o índice no dispositivo, mas é possível usar uma classe alternativa para programar o trabalho. Se você continuar a implementação usando a classe JobIntentService, será necessário adicionar a Android Support Library ao arquivo build.gradle do seu projeto.

Depois, para incluir itens no índice de conteúdo pessoal do app, crie objetos Indexable na mesma classe:

Tipos de resultados

A Indexação de apps permite a exibição de resultados em duas maneiras:

  • Somente em texto: a Pesquisa Google exibe seu conteúdo indexado como resultados de texto.
  • Slices: a Pesquisa Google usa Slices (em inglês) ou modelos de IU do aplicativo para fornecer resultados de pesquisa dinâmicos e interativos.

É possível escolher o tipo de resultado que melhor se adapta ao seu aplicativo. Resultados somente em texto são menos complicados de implementar, mas os Slices fornecem uma experiência de usuário mais rica.

Implantação de amostra

Resultados somente em texto

Java

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

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) {
            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 em Slices

As Slices (em inglês) permitem que você configure partes do seu aplicativo para aparecer em resposta às consultas da Pesquisa Google. Como as Slices atuam como uma IU para conteúdo nos Indexables, cada Slice deve mapear diretamente para um Indexable. Siga estas etapas para produzir resultados compatíveis com Slices no aplicativo:

  1. Adicione Slices ao aplicativo seguindo as instruções no Guia de primeiros passos das Slices.
  2. Adicione Indexables com metadados e listeners da Slice:
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);
                        });
    }
  }
}

O que meu índice de conteúdo pessoal deve incluir?

Defina objetos Indexable para estes tipos de conteúdo:

  • Conteúdo específico do usuário, como mensagens, fotos e documentos.
  • Conteúdo que é importante para os usuários, como favoritos, ou conteúdo que eles podem desejar acessar com mais freqüência. Por exemplo, documentos ou músicas que marcaram como favoritos ou para uso off-line.
  • Conteúdo gerado no seu aplicativo e não apenas acessado por ele. Por exemplo, contatos criados pelos usuários diretamente no seu app e armazenados nele, e não contatos da agenda do smartphone.

Adicionar um receptor de transmissão ao seu app

O Google Play Services envia uma solicitação regularmente ao seu app para atualizar o índice no dispositivo. Isso permite que o índice no dispositivo tenha o conteúdo mais recente do aplicativo. A classe BroadcastReceiver (em inglês) recebe essa solicitação e aciona a JobIntentService para processar o trabalho de indexação. O exemplo abaixo usa a classe AppIndexingUpdateService da etapa anterior.

Java

/** 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

/** 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)
        }
    }
}

Gerar e atualizar o índice

Em seguida, permita que o Google Play Services chame o serviço de indexação de apps para atualizar o índice no dispositivo com o conteúdo pessoal do usuário nas seguintes situações:

  • Quando o app é instalado em um dispositivo.
  • Caso uma versão existente do aplicativo seja atualizada para uma versão que ofereça suporte à indexação de conteúdo pessoal.
  • Chamadas periódicas ao longo do tempo para refletir com precisão todas as alterações feitas no conteúdo indexado, garantindo uma experiência perfeita do usuário.

Além disso, se o índice no dispositivo for perdido por algum motivo, por exemplo, se estiver corrompido, essa chamada de atualização o recriará.

No arquivo AndroidManifest.xml, registre o BroadcastReceiver para que ele possa receber chamadas do Google Play Services a fim de atualizar o índice. No exemplo abaixo, a classe JobIntentService foi usada para programar as atualizações de indexação:

<!-- 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" />

Atualizar o índice

Quando os usuários adicionam, atualizam ou removem conteúdo pessoal, o índice no dispositivo precisa refletir essas alterações. Adicione o código a seguir para atualizar o conteúdo no índice:

Atualizar "somente em texto"

Java

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

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)
    // ...
}
Atualizar slices

A Indexação de apps no Firebase recupera o conteúdo da Slice no momento da indexação, armazena-o e exibe o instantâneo da Slice no momento da consulta. Se o conteúdo da Slice mudar entre a indexação e a consulta, esse instantâneo pode ser enganoso ou confuso para os usuários. Para evitar isso, atualize a Slice e reindexe o Indexable ao mesmo tempo, para que a Indexação de apps do Firebase tenha sempre o conteúdo mais atualizado da Slice.

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);
   ...
}
Remover

Para identificar itens a serem removidos, use o URL do item. Adicione esta linha à função de exclusão ou remoção do seu aplicativo para esse item.

Java

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

Kotlin

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

Excluir o índice quando o usuário sai

Exclua o índice no dispositivo quando os usuários saírem do seu aplicativo, no evento de logout. Inclua a chamada a fim de gerar e atualizar o índice usando a classe AppIndexingService para recriá-lo no dispositivo quando os usuários fizerem login novamente.

Para excluir o índice no dispositivo quando um usuário sair do seu aplicativo, adicione este código ao aplicativo:

Java

FirebaseAppIndex.getInstance().removeAll();

Kotlin

FirebaseAppIndex.getInstance().removeAll()

Próximo: registrar ações do usuário