Skip to main content

Cloud Firestore




Part 1 – Introduction
Part 2 – Preparations & Set Document
Part 3 – Get Document
Part 4 – SnapshotListener
Part 5 – Merge & Update
Part 6 – Delete Field & Document
Part 7 – Custom Objects
Part 8 – Add & Retrieve Multiple Documents
Part 9 – Simple Queries
Part 10 – Compound Queries
Part 11 – OR Queries
Part 12 – Pagination
Part 13 – DocumentChanges
Part 14 – Batched Writes
Part 15 – Transactions
Part 16 – Arrays
Part 17 – Nested Objects
Part 18 – Subcollections

            

  Part 1 – Introduction


In this tutorial we will learn, how to use the Cloud Firestore database to store and retrieve data in an Android app.
Firestore is a cloud-hosted database that makes it easy to synchronize data in realtime between multiple connected client apps and across different platforms, without us having to manage our own servers.
Firestore is a schemaless NoSQL database and stores it’s data in documents which each contain a set of key-value pairs (fields). These fields can be simple datatypes like strings, integers and booleans, but also geographical points, raw binary values, timestamps, arrays, nested objects (maps) etc.
Documents are organized into collections and can contain subcollections.
Links:
Explanation Firestore data model:
firebase.google.com/docs/firestore/data-model
Comparison Firestore vs Realtime Database:
firebase.google.com/docs/firestore/rtdb-vs-firestore



Part 2 – Preparations & Set Document


In part 2 of the Firestore tutorial, we connect a new Android Studio project to Firebase with help of the Firebase assistant and add the Firestore dependency.
When that’s done we upload our first document into our first collection, by retrieving the user input from 2 EditText fields, saving the input as strings in a HashMap together with their keys, and passing this HashMap to Firestore over a database reference that we get with the static Firestore getInstance method. For this we simply call the collection and document reference methods on our Firestore reference, pass strings for their names and lastly call the set method to pass our Map to this reference and set it as the fields on our first document.
We also add an OnSuccessListener and an OnFailureListener to have callbacks about the upload success.

Add dependencies in gradle file from the official link of firebase:-


In activity_main.xml file add these lines:-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context="com.codinginflow.firestoreexampleproject.MainActivity">

    <EditText
        android:id="@+id/edit_text_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Title"
        android:inputType="text" />

    <EditText
        android:id="@+id/edit_text_description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Description"
        android:inputType="text" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="saveNote"
        android:text="Save" />

</LinearLayout>


In MainActivity.java class file add these lines of codes:-

import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.firestore.FirebaseFirestore;

import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    private static final String KEY_TITLE = "title";
    private static final String KEY_DESCRIPTION = "description";

    private EditText editTextTitle;
    private EditText editTextDescription;

    private FirebaseFirestore db = FirebaseFirestore.getInstance();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editTextTitle = findViewById(R.id.edit_text_title);
        editTextDescription = findViewById(R.id.edit_text_description);
    }

    public void saveNote(View v) {
        String title = editTextTitle.getText().toString();
        String description = editTextDescription.getText().toString();

        Map<String, Object> note = new HashMap<>();
        note.put(KEY_TITLE, title);
        note.put(KEY_DESCRIPTION, description);

        db.collection("Notebook").document("My First Note").set(note)
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Toast.makeText(MainActivity.this, "Note saved", Toast.LENGTH_SHORT).show();
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(MainActivity.this, "Error!", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, e.toString());
                    }
                });
    }

}

        Part 3 – Get Document


In part 3 of the Firestore tutorial, we retrieve our uploaded document by calling the get method on our DocumentReference. As before we add an OnSuccessListener where we get a DocumentSnapshot that contains the data of our document. We can either retrieve our values directly by passing the key for each value to the DocumentSnapshot’s getString method, or alternatively recreate our original Map as a whole.
In the OnFailure method we print the exception to the stacktrace.

Add dependencies in gradle file from the official link of firebase:-


In activity_main.xml add these codes:-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context="com.codinginflow.firestoreexampleproject.MainActivity">
    <EditText
        android:id="@+id/edit_text_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Title"
        android:inputType="text" />
    <EditText
        android:id="@+id/edit_text_description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Description"
        android:inputType="text" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="saveNote"
        android:text="Save" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="loadNote"
        android:text="Load" />
    <TextView
        android:id="@+id/text_view_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp" />
</LinearLayout>

In MainActivity.java class add these lines of codes:-


import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private static final String KEY_TITLE = "title";
    private static final String KEY_DESCRIPTION = "description";
    private EditText editTextTitle;
    private EditText editTextDescription;
    private TextView textViewData;
    private FirebaseFirestore db = FirebaseFirestore.getInstance();
    private DocumentReference noteRef = db.document("Notebook/My First Note");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editTextTitle = findViewById(R.id.edit_text_title);
        editTextDescription = findViewById(R.id.edit_text_description);
        textViewData = findViewById(R.id.text_view_data);
    }
    public void saveNote(View v) {
        String title = editTextTitle.getText().toString();
        String description = editTextDescription.getText().toString();
        Map<String, Object> note = new HashMap<>();
        note.put(KEY_TITLE, title);
        note.put(KEY_DESCRIPTION, description);
        noteRef.set(note)
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Toast.makeText(MainActivity.this, "Note saved", Toast.LENGTH_SHORT).show();
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(MainActivity.this, "Error!", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, e.toString());
                    }
                });
    }
    public void loadNote(View v) {
        noteRef.get()
                .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                    @Override
                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                        if (documentSnapshot.exists()) {
                            String title = documentSnapshot.getString(KEY_TITLE);
                            String description = documentSnapshot.getString(KEY_DESCRIPTION);
                            //Map<String, Object> note = documentSnapshot.getData();
                            textViewData.setText("Title: " + title + "\n" + "Description: " + description);
                        } else {
                            Toast.makeText(MainActivity.this, "Document does not exist", Toast.LENGTH_SHORT).show();
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(MainActivity.this, "Error!", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, e.toString());
                    }
                });
    }
}



Comments

Popular posts from this blog

Why Ethereum Smart Contracts Make It Hard to Get Payments

  The Unique Role of Smart Contracts in Ethereum One of Ethereum’s standout features is its ability to host diverse applications on its blockchain using smart contracts. However, these smart contracts, while powerful, sometimes complicate simple tasks. For instance, determining the amount of ETH deposited into a specific Ethereum address can be surprisingly complex. This is because you cannot understand the actions of a smart contract without executing it. Synchronizing Blockchain Internals and Externals Smart contracts operate exclusively within the blockchain's data, reading and writing information stored on-chain. This limitation does not prevent the creation of valuable applications, such as multi-signature wallets or tokens like ERC-20 and ERC-721, which rely solely on on-chain data. However, most practical applications also require interaction with off-chain systems. Take cryptocurrency exchanges, for example. Exchanges facilitate converting ETH into fiat currency or vice ver...

Room + ViewModel + LiveData + RecyclerView (MVVM)

Part 1 - Introduction Part 2 – Entity Part 3 – DAO & RoomDatabase Part 4 – Repository Part 5 – ViewModel Part 6 – RecyclerView + Adapter Part 7 – Add Note Activity Part 8 – Swipe to Delete Part 9 – OnItemClickListener & Update Functionality Part 10 – ListAdapter                     Part 1 - Introduction In this tutorial we will build a note taking app, using the Android Architecture Component libraries (Room, ViewModel, LiveData and LifeCycle), a RecyclerView and Java. The data will be stored in an SQLite database and supports insert, read, update and delete operations. For this we will follow the official recommendations from the “Guide to App Architecture” (link below). In part 1 we will learn what the Architecture Components are, how they work and why we need them. We will learn about the problems that arise from the Activity and Fragment lifecycle, configuration changes and bloated, tightly coupled cl...

DodgeInsetEdges

The layout_dodgeInsetEdges together with the layout_insetEdge attribute, to move views within a CoordinatorLayout out of the way of other views. This behavior is the default behavior for FloatingActionButtons and Snackbars , but we will also apply it to views like normal buttons and bottom sheets. In Mainactivity.java add the code below stated:- import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity {     private BottomSheetBehavior bottomSheetBehavior;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activ...