Firebase Realtime Database

Firebase Realtime Database

Firebase Realtime database What is Firebase Database, is a cloud hosted databases that helps multiple platforms Android os, iOS and Web. All of the data is stored in JSON format (Checkout my article of json format or json parsing)and any changes in data, shows immediately by doing a sync across all the systems & devices. This enables us to create more adaptable realtime apps easily with reduced effort.

firebase realtime database

This article includes principles integration of firebase realtime database. The other principles like performs CRUD functions, data validations, firebase gain access to rules also protected. If you’re not used to firebase, It is advisable to check my other article about Firebase Auth and Firebase Analytics to boost your knowledge over firebase.

 The way the Data is Stored – JSON Structured

Firebase realtime database is a schemaless databases where the data is stored in JSON format. Fundamentally the whole repository is a huge JSON tree with multiple nodes. So when you intend your database, you will need to get ready the json composition in way that the info is obtainable in easier way by preventing nesting of child nodes.

Here is a good example of storing set of user information and articles in json tree. You could proceed through firebase Composition Your Repository guide to learn the best practises while determining the database framework.

{
  "users": [
    {
      "name": "Abdul Basit",
      "email": "abdulbasit@androdevelopment.com",
      "address": "XXX, XXXX, 1234"
    }
  ],
  "posts": [
    {
      "id": 100,
      "author": "Abdul Basit",
      "content": "This is awesome firebase realtime database...",
      "timestamp": "13892733894"
    }
  ]
}

 

Offline Data

Firebase provides great support when involves offline data. It automatically stores the info offline when there is absolutely no web connection. When these devices attaches to internet, all the info will be forced to firebasee realtime database. However enabling drive persistence stores the info offline when though app restarts. Drive persistence can be allowed by dialling below one series code. Here’s complete guide about firebase offline features.

FirebaseDatabase.getInstance().setPersistenceEnabled(true);

 

Performing CRUD Operations – Firebase Realtime Database

Before engaging in the android os app, I’d like to offer basic information about carrying out CRUD procedures to realtime data source. Later we’ll incorporate all these principles together to create a simple app with firebase realtime database as backend.

To be able to perform any procedure on to repository whether it could be read or write, you will need to receive the reference to databases first. The below code provides you mention of repository JSON top node. From here you should employ the child node names to traverse further.

private DatabaseReference mDatabase;
 
mDatabase = FirebaseDatabase.getInstance().getReference();

 

Inserting Data

To put in data, you may use setValue() method to database reference way. This will generate or update the worthiness on route provided. For a good example below code inserts a node called “copyright” in json top level.

DatabaseReference mRef = mDatabase.getReference("copyright");
 
mRef.setValue("©2017 androdevelopment. All rights Reserved");

 

The realtime data source allows multiple data types String, Long, Twin, Boolean, Map<String, Thing>, List<Thing> to store the info. You can even use custom java things to store the info which is very useful when storing model category directly in databases.

Suppose you want to store user profile in the databases. First you will need to create End user model with a clear constructor and other properties.

@IgnoreExtraProperties
public class User {
 
    public String name;
    public String email;
 
    // Default constructor required for calls to
    // DataSnapshot.getValue(User.class)
    public User() {
    }
 
    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
}

 

As every individual requires a unique Id, you will generate one by getting in touch with push() method which creates a clear node with original key. Then have the mention of ‘users’ node using child() method. Finally use setValue() solution to store an individual data.

DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference("users");
 
// Creating new user node, which returns the unique key value
// new user node would be /users/$userid/
String userId = mDatabase.push().getKey();
 
// creating user object
User user = new User("Abdul Basit", "abdulbasit@androdevelopment.com");
 
// pushing user to 'users' node using the userId
mDatabase.child(userId).setValue(user);

 

By running the above mentioned code, a fresh customer node will be put in database with a distinctive key value. Generally, the user id should be bought by utilizing Firebase Auth in your app gives you authId that works as user id.

{
  "users": [
    "-KTYWvZG4Qn9ZYTc47O6" : {
      "email" : "abdulbasit@androdevelopment.com",
      "name" : "Abdul Basit"
    },
    {
      ...
    }
  ]
}

 

Reading Data

To read the info, you need to add the ValueEventListener() to the databases reference point. This event will be brought on whenever there’s a change in data in realtime. In onDataChange() you is capable of doing the desired businesses onto new data.

Below is the function listener that is induced whenever there’s a change in account data that people created earlier.

mDatabase.child(userId).addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
 
        User user = dataSnapshot.getValue(User.class);
 
        Log.d(TAG, "User name: " + user.getName() + ", email " + user.getEmail());
    }
 
    @Override
    public void onCancelled(DatabaseError error) {
        // Failed to read value
        Log.w(TAG, "Failed to read value.", error.toException());
    }
});

 

Updating Data

To upgrade data, you may use the same setValue() method by transferring new value. You can even use updateChildren() by transferring the path to upgrade data without troubling other child nodes data.

For example if you need to revise only an individual email, you may use below code stop.

String newEmail = 'androdevelopment898@gmail.com';
 
mDatabase.child(userId).child("email").setValue(newEmail);

 

Learn How To Connect Php To Firebase

Deleting Data

To erase data, you can merely call removeValue() method to database reference. You can even go null to setValue() method which do the same delete procedure.

Security & Rules

Firebase realtime database rules offers a way to recognize customer role while executing read and write operations. These guidelines will operates a security part on the server before perform any CRUD procedure. By default the guidelines allows user to execute read & write procedure only after authentication.

The below guidelines allow authenticated users and then read or write data.

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

 

Below guidelines allows everyone to learn & write data without authentication.

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

You can even use these guidelines to validate data before placing into database. For instance below guidelines validates the name to be significantly less than 50 chars and email to be valid using email regular expression.

{
    "rules": {
        ".read": true,
        ".write": true,
        "users": {
            "$user": {
                "name": {
                    ".validate": "newData.isString() && newData.val().length < 50"
                },
                "email": {
                    ".validate": "newData.isString() && newData.val().matches(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$/i)"
                }
            }
        }
    }
}

We now have enough knowledge to begin with with an android task. Let’s create one and observe how to incorporate the firebase realtime database with a good example app.

Creating Android os Project – Firebase Realtime Database

We Have Already Meantioned Creating Android Project In Our Previous Article Firebase Auth.

  1. First thing you must do is go to https://firebase.google.com/ and make a merchant account to gain usage of their console. Once you access the console you can begin by creating your first task.
  2. Give the program name of assembling your project (mine is com.androdevelopment.firebase) where you will incorporate the Firebase. Here the google-services.json document will be downloaded when you press add software button.

1

  1. Create a fresh project in Android os Studio from File => New Project. While filling up the task details, use the same program name that you offered in firebase system. In my circumstance I am using same com.androdevelopment.firebase.
  2. Paste the google-services.json data file to your project’s app folder. This task is vital as assembling your project won’t build without this document.
  3. Now open up the build.gradle positioned in project’s home directory website and add google playstore dependency.
build.gradle
dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
        classpath 'com.google.gms:google-services:3.0.0'
 
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }

 

  1. Start app/build.gradle and add firebase databases dependency. At the lower part of the data file, add apply plugin: ‘com.google.gms.google-services’
app/build.gradle
dependencies {
    // Adding support library for this demo app
    compile 'com.android.support:design:24.2.1'
 
    compile 'com.google.firebase:firebase-database:9.6.1'
}
 
apply plugin: 'com.google.gms.google-services'

 

  1. To be able to store account, we desire a model school called Consumer.java. Build a class named End user.java and add below course properties. If you’d like you can include few more properties like address, mobile etc.,
User.java
package com.androdevelopment.firebase;
 
import com.google.firebase.database.IgnoreExtraProperties;
 
/**
 * Created by Abdul Basit on 03/19/17.
 * www.androdevelopment.com
 */
 
@IgnoreExtraProperties
public class User {
 
    public String name;
    public String email;
 
    // Default constructor required for calls to
    // DataSnapshot.getValue(User.class)
    public User() {
    }
 
    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
}

 

  1. Open the structure record of main activity activity_main.xml and add the below structure. This design creates a straightforward form where you can type in the account data to store in databases.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.androdevelopment.firebase.MainActivity">
 
    <TextView
        android:id="@+id/txt_user"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_horizontal_margin"
        android:textSize="20dp" />
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
 
        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
 
            <EditText
                android:id="@+id/name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/name"
                android:inputType="textCapWords"
                android:maxLines="1" />
 
        </android.support.design.widget.TextInputLayout>
 
        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
 
            <EditText
                android:id="@+id/email"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/email"
                android:inputType="textEmailAddress"
                android:maxLines="1" />
 
        </android.support.design.widget.TextInputLayout>
 
        <Button
            android:id="@+id/btn_save"
            style="?android:textAppearanceSmall"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:background="@color/colorPrimary"
            android:text="@string/action_save"
            android:textColor="@android:color/white"
            android:textStyle="bold" />
 
    </LinearLayout>
 
</LinearLayout>

 

  1. Start MainActivity.java and do the below necessary changes. The code is simple and easily understandable.

Our goal is to build the json framework as below where ‘app_name’ stores the software subject. ‘users’ stores customer profiles as a range of nodes.

{
  "app_title" : "Realtime Database",
  "users" : {
    "-KTYWvZG4Qn9ZYTc47O6" : {
      "email" : "abdulbasit@androdevelopment.com",
      "name" : "Abdul Basit"
    }
  }
}

 

  •  getReference(“app_name”) generate a node known as app_subject which stores the toolbar name.
  • getReference(“users”) gets mention of users node.
  • createUser() method stores a fresh consumer in realtime database
  • updateUser() method improvements user information like name and email.
MainActivity.java
package com.androdevelopment.firebase;
 
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
 
public class MainActivity extends AppCompatActivity {
 
    private static final String TAG = MainActivity.class.getSimpleName();
    private TextView txtDetails;
    private EditText inputName, inputEmail;
    private Button btnSave;
    private DatabaseReference mFirebaseDatabase;
    private FirebaseDatabase mFirebaseInstance;
 
    private String userId;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // Displaying toolbar icon
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setIcon(R.mipmap.ic_launcher);
 
        txtDetails = (TextView) findViewById(R.id.txt_user);
        inputName = (EditText) findViewById(R.id.name);
        inputEmail = (EditText) findViewById(R.id.email);
        btnSave = (Button) findViewById(R.id.btn_save);
 
        mFirebaseInstance = FirebaseDatabase.getInstance();
 
        // get reference to 'users' node
        mFirebaseDatabase = mFirebaseInstance.getReference("users");
 
        // store app title to 'app_title' node
        mFirebaseInstance.getReference("app_title").setValue("Realtime Database");
 
        // app_title change listener
        mFirebaseInstance.getReference("app_title").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.e(TAG, "App title updated");
 
                String appTitle = dataSnapshot.getValue(String.class);
 
                // update toolbar title
                getSupportActionBar().setTitle(appTitle);
            }
 
            @Override
            public void onCancelled(DatabaseError error) {
                // Failed to read value
                Log.e(TAG, "Failed to read app title value.", error.toException());
            }
        });
 
        // Save / update the user
        btnSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String name = inputName.getText().toString();
                String email = inputEmail.getText().toString();
 
                // Check for already existed userId
                if (TextUtils.isEmpty(userId)) {
                    createUser(name, email);
                } else {
                    updateUser(name, email);
                }
            }
        });
 
        toggleButton();
    }
 
    // Changing button text
    private void toggleButton() {
        if (TextUtils.isEmpty(userId)) {
            btnSave.setText("Save");
        } else {
            btnSave.setText("Update");
        }
    }
 
    /**
     * Creating new user node under 'users'
     */
    private void createUser(String name, String email) {
        // TODO
        // In real apps this userId should be fetched
        // by implementing firebase auth
        if (TextUtils.isEmpty(userId)) {
            userId = mFirebaseDatabase.push().getKey();
        }
 
        User user = new User(name, email);
 
        mFirebaseDatabase.child(userId).setValue(user);
 
        addUserChangeListener();
    }
 
    /**
     * User data change listener
     */
    private void addUserChangeListener() {
        // User data change listener
        mFirebaseDatabase.child(userId).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                User user = dataSnapshot.getValue(User.class);
 
                // Check for null
                if (user == null) {
                    Log.e(TAG, "User data is null!");
                    return;
                }
 
                Log.e(TAG, "User data is changed!" + user.name + ", " + user.email);
 
                // Display newly updated name and email
                txtDetails.setText(user.name + ", " + user.email);
 
                // clear edit text
                inputEmail.setText("");
                inputName.setText("");
 
                toggleButton();
            }
 
            @Override
            public void onCancelled(DatabaseError error) {
                // Failed to read value
                Log.e(TAG, "Failed to read user", error.toException());
            }
        });
    }
 
    private void updateUser(String name, String email) {
        // updating the user via child nodes
        if (!TextUtils.isEmpty(name))
            mFirebaseDatabase.child(userId).child("name").setValue(name);
 
        if (!TextUtils.isEmpty(email))
            mFirebaseDatabase.child(userId).child("email").setValue(email);
    }
}

 

Run & test the firebase realtime databse app once. You ought to be able to start to see the changes in realtime in your firebase console.

firebase realtime database

See Also:

Firebase Cloud Messaging Tutorial Android

Firebase Facebook Authentication