1. Visão Geral
Metas
Neste codelab, você criará um aplicativo de recomendação de restaurantes no Android com suporte do Cloud Firestore. Você vai aprender como:
- Ler e gravar dados no Firestore de um aplicativo Android
- Ouça as alterações nos dados do Firestore em tempo real
- Use o Firebase Authentication e as regras de segurança para proteger os dados do Firestore
- Escrever consultas complexas do Firestore
Pré-requisitos
Antes de iniciar este codelab, verifique se você tem:
- Android Studio 4.0 ou superior
- Um emulador Android com API 19 ou superior
- Node.js versão 10 ou superior
- Java versão 8 ou superior
2. Crie um projeto do Firebase
- Faça login no console do Firebase com sua conta do Google.
- No console do Firebase , clique em Adicionar projeto .
- Conforme mostrado na captura de tela abaixo, insira um nome para seu projeto do Firebase (por exemplo, "Friendly Eats") e clique em Continuar .
- Você pode ser solicitado a ativar o Google Analytics, para os fins deste codelab, sua seleção não importa.
- Após cerca de um minuto, seu projeto do Firebase estará pronto. Clique em Continuar .
3. Configure o projeto de amostra
Baixe o código
Execute o comando a seguir para clonar o código de amostra para este codelab. Isso criará uma pasta chamada friendlyeats-android
em sua máquina:
$ git clone https://github.com/firebase/friendlyeats-android
Se você não tiver o git em sua máquina, também poderá baixar o código diretamente do GitHub.
Adicionar configuração do Firebase
- No console do Firebase , selecione Visão geral do projeto no painel de navegação esquerdo. Clique no botão Android para selecionar a plataforma. Quando for solicitado um nome de pacote, use
com.google.firebase.example.fireeats
- Clique em Register App e siga as instruções para baixar o arquivo
google-services.json
e mova-o para a pastaapp/
do código que você acabou de baixar. Em seguida, clique em Avançar .
Importar o projeto
Abra o Android Studio. Clique em Arquivo > Novo > Importar Projeto e selecione a pasta friendlyeats-android .
4. Configure os emuladores do Firebase
Neste codelab, você usará o Firebase Emulator Suite para emular localmente o Cloud Firestore e outros serviços do Firebase. Isso fornece um ambiente de desenvolvimento local seguro, rápido e sem custo para criar seu aplicativo.
Instalar a CLI do Firebase
Primeiro, você precisará instalar a Firebase CLI . Se você estiver usando macOS ou Linux, poderá executar o seguinte comando cURL:
curl -sL https://firebase.tools | bash
Se você estiver usando o Windows, leia as instruções de instalação para obter um binário autônomo ou para instalar via npm
.
Depois de instalar a CLI, a execução do firebase --version
deve informar uma versão 9.0.0
ou superior:
$ firebase --version 9.0.0
Conecte-se
Execute o firebase login
para conectar a CLI à sua conta do Google. Isso abrirá uma nova janela do navegador para concluir o processo de login. Certifique-se de escolher a mesma conta que você usou ao criar seu projeto do Firebase anteriormente.
Vincule seu projeto
De dentro da pasta friendlyeats-android
execute firebase use --add
para conectar seu projeto local ao seu projeto Firebase. Siga os prompts para selecionar o projeto que você criou anteriormente e, se solicitado a escolher um alias, digite default
.
5. Execute o aplicativo
Agora é hora de executar o Firebase Emulator Suite e o aplicativo Android FriendlyEats pela primeira vez.
Execute os emuladores
No seu terminal, a partir do diretório friendlyeats-android
, execute firebase emulators:start
para iniciar os Firebase Emulators. Você deve ver logs como este:
$ firebase emulators:start i emulators: Starting emulators: auth, firestore i firestore: Firestore Emulator logging to firestore-debug.log i ui: Emulator UI logging to ui-debug.log ┌─────────────────────────────────────────────────────────────┐ │ ✔ All emulators ready! It is now safe to connect your app. │ │ i View Emulator UI at http://localhost:4000 │ └─────────────────────────────────────────────────────────────┘ ┌────────────────┬────────────────┬─────────────────────────────────┐ │ Emulator │ Host:Port │ View in Emulator UI │ ├────────────────┼────────────────┼─────────────────────────────────┤ │ Authentication │ localhost:9099 │ http://localhost:4000/auth │ ├────────────────┼────────────────┼─────────────────────────────────┤ │ Firestore │ localhost:8080 │ http://localhost:4000/firestore │ └────────────────┴────────────────┴─────────────────────────────────┘ Emulator Hub running at localhost:4400 Other reserved ports: 4500 Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
Agora você tem um ambiente de desenvolvimento local completo rodando em sua máquina! Certifique-se de deixar este comando em execução pelo resto do codelab, seu aplicativo Android precisará se conectar aos emuladores.
Conecte o aplicativo aos emuladores
Abra o arquivo FirebaseUtil.java
no Android Studio. Este arquivo contém a lógica para conectar os SDKs do Firebase aos emuladores locais executados em sua máquina.
Na parte superior do arquivo, examine esta linha:
/** Use emulators only in debug builds **/
private static final boolean sUseEmulators = BuildConfig.DEBUG;
Estamos usando o BuildConfig
para garantir que nos conectemos apenas aos emuladores quando nosso aplicativo estiver sendo executado no modo de debug
. Quando compilamos o aplicativo no modo de release
, essa condição será falsa.
Agora dê uma olhada no método getFirestore()
:
public static FirebaseFirestore getFirestore() {
if (FIRESTORE == null) {
FIRESTORE = FirebaseFirestore.getInstance();
// Connect to the Cloud Firestore emulator when appropriate. The host '10.0.2.2' is a
// special IP address to let the Android emulator connect to 'localhost'.
if (sUseEmulators) {
FIRESTORE.useEmulator("10.0.2.2", 8080);
}
}
return FIRESTORE;
}
Podemos ver que ele está usando o método useEmulator(host, port)
para conectar o SDK do Firebase ao emulador local do Firestore. Em todo o aplicativo, usaremos FirebaseUtil.getFirestore()
para acessar essa instância do FirebaseFirestore
para ter certeza de que estamos sempre nos conectando ao emulador do Firestore ao executar no modo de debug
.
Execute o aplicativo
Se você adicionou o arquivo google-services.json
corretamente, o projeto agora deve ser compilado. No Android Studio, clique em Build > Rebuild Project e verifique se não há erros restantes.
No Android Studio Execute o aplicativo em seu emulador Android. No início, você será presenteado com uma tela de "Entrar". Você pode usar qualquer e-mail e senha para entrar no aplicativo. Esse processo de login está se conectando ao emulador do Firebase Authentication, portanto, nenhuma credencial real está sendo transmitida.
Agora abra a interface do usuário de emuladores navegando para http://localhost:4000 em seu navegador da web. Em seguida, clique na guia Autenticação e você deverá ver a conta que acabou de criar:
Depois de concluir o processo de login, você deverá ver a tela inicial do aplicativo:
Em breve adicionaremos alguns dados para preencher a tela inicial.
6. Gravar dados no Firestore
Nesta seção, gravaremos alguns dados no Firestore para que possamos preencher a tela inicial vazia no momento.
O objeto de modelo principal em nosso aplicativo é um restaurante (consulte model/Restaurant.java
). Os dados do Firestore são divididos em documentos, coleções e subcoleções. Armazenaremos cada restaurante como um documento em uma coleção de nível superior chamada "restaurants"
. Para saber mais sobre o modelo de dados do Firestore, leia sobre documentos e coleções na documentação .
Para fins de demonstração, adicionaremos a funcionalidade no aplicativo para criar dez restaurantes aleatórios quando clicarmos no botão "Adicionar itens aleatórios" no menu flutuante. Abra o arquivo MainActivity.java
e substitua o conteúdo no método onAddItemsClicked()
por:
private void onAddItemsClicked() {
// Get a reference to the restaurants collection
CollectionReference restaurants = mFirestore.collection("restaurants");
for (int i = 0; i < 10; i++) {
// Get a random Restaurant POJO
Restaurant restaurant = RestaurantUtil.getRandom(this);
// Add a new document to the restaurants collection
restaurants.add(restaurant);
}
}
Há algumas coisas importantes a serem observadas sobre o código acima:
- Começámos por obter uma referência à colecção
"restaurants"
. As coleções são criadas implicitamente quando os documentos são adicionados, portanto, não havia necessidade de criar a coleção antes de gravar os dados. - Os documentos podem ser criados usando POJOs (Plain Old Java Object), que usamos para criar cada documento Restaurant.
- O método
add()
adiciona um documento a uma coleção com um ID gerado automaticamente, portanto, não precisamos especificar um ID exclusivo para cada restaurante.
Agora execute o aplicativo novamente e clique no botão "Adicionar itens aleatórios" no menu flutuante (no canto superior direito) para invocar o código que você acabou de escrever:
Agora abra a interface do usuário de emuladores navegando para http://localhost:4000 em seu navegador da web. Em seguida, clique na guia Firestore e você verá os dados que acabou de adicionar:
Esses dados são 100% locais para sua máquina. Na verdade, seu projeto real ainda não contém um banco de dados Firestore! Isso significa que é seguro experimentar modificar e excluir esses dados sem consequências.
Parabéns, você acabou de gravar dados no Firestore! Na próxima etapa, aprenderemos como exibir esses dados no aplicativo.
7. Exibir dados do Firestore
Nesta etapa, aprenderemos como recuperar dados do Firestore e exibi-los em nosso aplicativo. A primeira etapa para ler dados do Firestore é criar uma Query
. Abra o arquivo MainActivity.java
e adicione o seguinte código ao início do método onCreate()
:
mFirestore = FirebaseUtil.getFirestore();
// Get the 50 highest rated restaurants
mQuery = mFirestore.collection("restaurants")
.orderBy("avgRating", Query.Direction.DESCENDING)
.limit(LIMIT);
Agora queremos ouvir a consulta, para obter todos os documentos correspondentes e ser notificados de futuras atualizações em tempo real. Como nosso objetivo final é vincular esses dados a um RecyclerView
, precisamos criar uma classe RecyclerView.Adapter
para ouvir os dados.
Abra a classe FirestoreAdapter
, que já foi parcialmente implementada. Primeiro, vamos fazer o adaptador implementar EventListener
e definir a função onEvent
para que ele possa receber atualizações para uma consulta do Firestore:
public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH>
implements EventListener<QuerySnapshot> { // Add this "implements"
// ...
// Add this method
@Override
public void onEvent(QuerySnapshot documentSnapshots,
FirebaseFirestoreException e) {
// Handle errors
if (e != null) {
Log.w(TAG, "onEvent:error", e);
return;
}
// Dispatch the event
for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
// Snapshot of the changed document
DocumentSnapshot snapshot = change.getDocument();
switch (change.getType()) {
case ADDED:
// TODO: handle document added
break;
case MODIFIED:
// TODO: handle document modified
break;
case REMOVED:
// TODO: handle document removed
break;
}
}
onDataChanged();
}
// ...
}
No carregamento inicial, o ouvinte receberá um evento ADDED
para cada novo documento. À medida que o conjunto de resultados da consulta muda ao longo do tempo, o ouvinte receberá mais eventos contendo as alterações. Agora vamos terminar de implementar o listener. Primeiro adicione três novos métodos: onDocumentAdded
, onDocumentModified
e onDocumentRemoved
:
protected void onDocumentAdded(DocumentChange change) {
mSnapshots.add(change.getNewIndex(), change.getDocument());
notifyItemInserted(change.getNewIndex());
}
protected void onDocumentModified(DocumentChange change) {
if (change.getOldIndex() == change.getNewIndex()) {
// Item changed but remained in same position
mSnapshots.set(change.getOldIndex(), change.getDocument());
notifyItemChanged(change.getOldIndex());
} else {
// Item changed and changed position
mSnapshots.remove(change.getOldIndex());
mSnapshots.add(change.getNewIndex(), change.getDocument());
notifyItemMoved(change.getOldIndex(), change.getNewIndex());
}
}
protected void onDocumentRemoved(DocumentChange change) {
mSnapshots.remove(change.getOldIndex());
notifyItemRemoved(change.getOldIndex());
}
Em seguida, chame esses novos métodos de onEvent
:
@Override
public void onEvent(QuerySnapshot documentSnapshots,
FirebaseFirestoreException e) {
// ...
// Dispatch the event
for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
// Snapshot of the changed document
DocumentSnapshot snapshot = change.getDocument();
switch (change.getType()) {
case ADDED:
onDocumentAdded(change); // Add this line
break;
case MODIFIED:
onDocumentModified(change); // Add this line
break;
case REMOVED:
onDocumentRemoved(change); // Add this line
break;
}
}
onDataChanged();
}
Finalmente implemente o método startListening()
para anexar o listener:
public void startListening() {
if (mQuery != null && mRegistration == null) {
mRegistration = mQuery.addSnapshotListener(this);
}
}
Agora o aplicativo está totalmente configurado para ler dados do Firestore. Execute o aplicativo novamente e você verá os restaurantes adicionados na etapa anterior:
Agora volte para a interface do usuário do emulador no seu navegador e edite um dos nomes dos restaurantes. Você deve vê-lo mudar no aplicativo quase instantaneamente!
8. Classifique e filtre dados
Atualmente, o aplicativo exibe os restaurantes mais bem avaliados em toda a coleção, mas em um aplicativo de restaurante real, o usuário deseja classificar e filtrar os dados. Por exemplo, o aplicativo deve ser capaz de mostrar "Principais restaurantes de frutos do mar na Filadélfia" ou "Pizza menos cara".
Clicar na barra branca na parte superior do aplicativo abre uma caixa de diálogo de filtros. Nesta seção, usaremos consultas do Firestore para fazer essa caixa de diálogo funcionar:
Vamos editar o método onFilter()
de MainActivity.java
. Este método aceita um objeto Filters
que é um objeto auxiliar que criamos para capturar a saída da caixa de diálogo de filtros. Vamos alterar este método para construir uma consulta a partir dos filtros:
@Override
public void onFilter(Filters filters) {
// Construct basic query
Query query = mFirestore.collection("restaurants");
// Category (equality filter)
if (filters.hasCategory()) {
query = query.whereEqualTo("category", filters.getCategory());
}
// City (equality filter)
if (filters.hasCity()) {
query = query.whereEqualTo("city", filters.getCity());
}
// Price (equality filter)
if (filters.hasPrice()) {
query = query.whereEqualTo("price", filters.getPrice());
}
// Sort by (orderBy with direction)
if (filters.hasSortBy()) {
query = query.orderBy(filters.getSortBy(), filters.getSortDirection());
}
// Limit items
query = query.limit(LIMIT);
// Update the query
mQuery = query;
mAdapter.setQuery(query);
// Set header
mCurrentSearchView.setText(Html.fromHtml(filters.getSearchDescription(this)));
mCurrentSortByView.setText(filters.getOrderDescription(this));
// Save filters
mViewModel.setFilters(filters);
}
No snippet acima, criamos um objeto Query
anexando as cláusulas where
e orderBy
para corresponder aos filtros fornecidos.
Execute o aplicativo novamente e selecione o filtro a seguir para mostrar os restaurantes de baixo preço mais populares:
Agora você deve ver uma lista filtrada de restaurantes contendo apenas opções de baixo preço:
Se você chegou até aqui, agora criou um aplicativo de visualização de recomendações de restaurantes totalmente funcional no Firestore! Agora você pode classificar e filtrar restaurantes em tempo real. Nas próximas seções, adicionaremos avaliações aos restaurantes e adicionaremos regras de segurança ao aplicativo.
9. Organize os dados em subcoleções
Nesta seção, adicionaremos classificações ao aplicativo para que os usuários possam avaliar seus restaurantes favoritos (ou menos favoritos).
Coleções e subcoleções
Até agora, armazenamos todos os dados do restaurante em uma coleção de nível superior chamada "restaurantes". Quando um usuário avalia um restaurante, queremos adicionar um novo objeto Rating
aos restaurantes. Para esta tarefa, usaremos uma subcoleção. Você pode pensar em uma subcoleção como uma coleção anexada a um documento. Assim, cada documento de restaurante terá uma subcoleção de avaliações cheia de documentos de avaliação. As subcoleções ajudam a organizar os dados sem sobrecarregar nossos documentos ou exigir consultas complexas.
Para acessar uma subcoleção, chame .collection()
no documento pai:
CollectionReference subRef = mFirestore.collection("restaurants")
.document("abc123")
.collection("ratings");
Você pode acessar e consultar uma subcoleção como em uma coleção de nível superior, não há limitações de tamanho ou alterações de desempenho. Você pode ler mais sobre o modelo de dados do Firestore aqui .
Escrevendo dados em uma transação
Adicionar uma Rating
à subcoleção adequada requer apenas chamar .add()
, mas também precisamos atualizar a classificação média do objeto Restaurant
e o número de classificações para refletir os novos dados. Se usarmos operações separadas para fazer essas duas alterações, haverá várias condições de corrida que podem resultar em dados obsoletos ou incorretos.
Para garantir que as avaliações sejam adicionadas corretamente, usaremos uma transação para adicionar avaliações a um restaurante. Esta transação executará algumas ações:
- Leia a classificação atual do restaurante e calcule a nova
- Adicione a classificação à subcoleção
- Atualize a classificação média do restaurante e o número de classificações
Abra RestaurantDetailActivity.java
e implemente a função addRating
:
private Task<Void> addRating(final DocumentReference restaurantRef,
final Rating rating) {
// Create reference for new rating, for use inside the transaction
final DocumentReference ratingRef = restaurantRef.collection("ratings")
.document();
// In a transaction, add the new rating and update the aggregate totals
return mFirestore.runTransaction(new Transaction.Function<Void>() {
@Override
public Void apply(Transaction transaction)
throws FirebaseFirestoreException {
Restaurant restaurant = transaction.get(restaurantRef)
.toObject(Restaurant.class);
// Compute new number of ratings
int newNumRatings = restaurant.getNumRatings() + 1;
// Compute new average rating
double oldRatingTotal = restaurant.getAvgRating() *
restaurant.getNumRatings();
double newAvgRating = (oldRatingTotal + rating.getRating()) /
newNumRatings;
// Set new restaurant info
restaurant.setNumRatings(newNumRatings);
restaurant.setAvgRating(newAvgRating);
// Commit to Firestore
transaction.set(restaurantRef, restaurant);
transaction.set(ratingRef, rating);
return null;
}
});
}
A função addRating()
retorna uma Task
representando toda a transação. Na função onRating()
são adicionados ouvintes à tarefa para responder ao resultado da transação.
Agora execute o aplicativo novamente e clique em um dos restaurantes, que deve abrir a tela de detalhes do restaurante. Clique no botão + para começar a adicionar uma avaliação. Adicione um comentário escolhendo um número de estrelas e digitando algum texto.
Clicar em Enviar iniciará a transação. Quando a transação for concluída, você verá sua avaliação exibida abaixo e uma atualização na contagem de avaliações do restaurante:
Parabéns! Agora você tem um aplicativo de avaliação de restaurantes social, local e móvel criado no Cloud Firestore. Ouvi dizer que esses são muito populares nos dias de hoje.
10. Proteja seus dados
Até agora, não consideramos a segurança deste aplicativo. Como sabemos que os usuários só podem ler e gravar os próprios dados corretos? Os bancos de dados do Firestore são protegidos por um arquivo de configuração chamado Regras de segurança .
Abra o arquivo firestore.rules
, você deverá ver o seguinte:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
//
// WARNING: These rules are insecure! We will replace them with
// more secure rules later in the codelab
//
allow read, write: if request.auth != null;
}
}
}
Vamos alterar essas regras para evitar acessos ou alterações de dados indesejados, abra o arquivo firestore.rules
e substitua o conteúdo pelo seguinte:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Determine if the value of the field "key" is the same
// before and after the request.
function isUnchanged(key) {
return (key in resource.data)
&& (key in request.resource.data)
&& (resource.data[key] == request.resource.data[key]);
}
// Restaurants
match /restaurants/{restaurantId} {
// Any signed-in user can read
allow read: if request.auth != null;
// Any signed-in user can create
// WARNING: this rule is for demo purposes only!
allow create: if request.auth != null;
// Updates are allowed if no fields are added and name is unchanged
allow update: if request.auth != null
&& (request.resource.data.keys() == resource.data.keys())
&& isUnchanged("name");
// Deletes are not allowed.
// Note: this is the default, there is no need to explicitly state this.
allow delete: if false;
// Ratings
match /ratings/{ratingId} {
// Any signed-in user can read
allow read: if request.auth != null;
// Any signed-in user can create if their uid matches the document
allow create: if request.auth != null
&& request.resource.data.userId == request.auth.uid;
// Deletes and updates are not allowed (default)
allow update, delete: if false;
}
}
}
}
Essas regras restringem o acesso para garantir que os clientes façam apenas alterações seguras. Por exemplo, atualizações em um documento de restaurante só podem alterar as classificações, não o nome ou qualquer outro dado imutável. As classificações só podem ser criadas se o ID do usuário corresponder ao usuário conectado, o que impede a falsificação.
Para ler mais sobre as regras de segurança, visite a documentação .
11. Conclusão
Agora você criou um aplicativo completo com base no Firestore. Você aprendeu sobre os recursos mais importantes do Firestore, incluindo:
- Documentos e coleções
- Lendo e escrevendo dados
- Classificando e filtrando com consultas
- Subcoleções
- Transações
Saber mais
Para continuar aprendendo sobre o Firestore, veja alguns bons lugares para começar:
O aplicativo de restaurante neste codelab foi baseado no aplicativo de exemplo "Friendly Eats". Você pode procurar o código-fonte desse aplicativo aqui .
Opcional: implantar na produção
Até agora, este aplicativo usou apenas o Firebase Emulator Suite. Se você quiser aprender a implantar este aplicativo em um projeto real do Firebase, passe para a próxima etapa.
12. (Opcional) Implante seu aplicativo
Até agora, este aplicativo tem sido totalmente local, todos os dados estão contidos no Firebase Emulator Suite. Nesta seção, você aprenderá a configurar seu projeto do Firebase para que este aplicativo funcione em produção.
Autenticação do Firebase
No console do Firebase, acesse a seção Autenticação e clique em Começar . Navegue até a guia Método de login e selecione a opção E- mail/senha de provedores nativos .
Habilite o método de login E- mail/Senha e clique em Salvar .
Firestore
Criar banco de dados
Navegue até a seção Firestore Database do console e clique em Create Database :
- Quando solicitado sobre as regras de segurança, escolha iniciar no modo de produção , atualizaremos essas regras em breve.
- Escolha o local do banco de dados que você gostaria de usar para seu aplicativo. Observe que selecionar um local de banco de dados é uma decisão permanente e para alterá-lo você terá que criar um novo projeto. Para obter mais informações sobre como escolher um local de projeto, consulte a documentação .
Regras de implantação
Para implantar as regras de segurança que você escreveu anteriormente, execute o seguinte comando no diretório codelab:
$ firebase deploy --only firestore:rules
Isso implantará o conteúdo de firestore.rules
em seu projeto, que você pode confirmar navegando até a guia Regras no console.
Implantar índices
O aplicativo FriendlyEats possui classificação e filtragem complexas que requerem vários índices compostos personalizados. Eles podem ser criados manualmente no console do Firebase, mas é mais simples escrever suas definições no arquivo firestore.indexes.json
e implantá-las usando a Firebase CLI.
Se você abrir o arquivo firestore.indexes.json
, verá que os índices necessários já foram fornecidos:
{
"indexes": [
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "city", "mode": "ASCENDING" },
{ "fieldPath": "avgRating", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "category", "mode": "ASCENDING" },
{ "fieldPath": "avgRating", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "price", "mode": "ASCENDING" },
{ "fieldPath": "avgRating", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "city", "mode": "ASCENDING" },
{ "fieldPath": "numRatings", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "category", "mode": "ASCENDING" },
{ "fieldPath": "numRatings", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "price", "mode": "ASCENDING" },
{ "fieldPath": "numRatings", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "city", "mode": "ASCENDING" },
{ "fieldPath": "price", "mode": "ASCENDING" }
]
},
{
"collectionId": "restaurants",
"fields": [
{ "fieldPath": "category", "mode": "ASCENDING" },
{ "fieldPath": "price", "mode": "ASCENDING" }
]
}
],
"fieldOverrides": []
}
Para implantar esses índices, execute o seguinte comando:
$ firebase deploy --only firestore:indexes
Observe que a criação do índice não é instantânea, você pode monitorar o progresso no console do Firebase.
Configurar o aplicativo
Na classe FirebaseUtil
, configuramos o SDK do Firebase para se conectar aos emuladores no modo de depuração:
public class FirebaseUtil {
/** Use emulators only in debug builds **/
private static final boolean sUseEmulators = BuildConfig.DEBUG;
// ...
}
Se quiser testar seu aplicativo com seu projeto real do Firebase, você pode:
- Compile o aplicativo no modo de lançamento e execute-o em um dispositivo.
- Altere temporariamente
sUseEmulators
parafalse
e execute o aplicativo novamente.
Observe que pode ser necessário sair do aplicativo e entrar novamente para se conectar corretamente à produção.