In this guest post by Ashok Kumar S, the author of Mastering Firebase for Android Development, you’ll learn how to build a small application using Realtime Database.

This tutorial describes how to build an Android realtime database app using Firebase. Ideating on the health and medical field is something that helps in the long term. This tutorial will show you how to build an Android mobile application that is crowdsourced to fetch email addresses of blood donors.

Android app with realtime database User interface design

It’s better to keep the user interface simple and informative in such applications. All you have is one RecyclerView and two buttons for adding and loading the data. The following XML layout code dictates the UI design:

<?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">
  <TextView android:textColor="@color/colorPrimaryDark" android:textStyle="bold" android:textSize="25dp" android:gravity="center" android:text="Packt Blood Bank" android:layout_width="match_parent" android:layout_height="wrap_content" />
  <View android:layout_marginLeft="50dp" android:layout_marginRight="50dp" android:layout_width="match_parent" android:layout_height="5dp" android:background="@color/colorAccent" />

The following code adds the vertical LinearLayout to support the DynamicData:

<LinearLayout android:layout_marginTop="10dp" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
  <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical">
   <android.support.v7.widget.RecyclerView android:id="@+id/peopleList" android:layout_width="match_parent" android:layout_height="match_parent" />
  </LinearLayout>

The above code sets the dynamic lists that load the data from RecyclerView. Continue updating the same layout to make the UI complete:

<View android:layout_width="match_parent" android:layout_height="5dp" android:background="@color/colorPrimary" />
  <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical">

The following layout adds a scrollable layout for the input controls:

<ScrollView android:scrollIndicators="right" android:scrollbarStyle="insideOverlay" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical">
  <LinearLayout android:layout_width="match_parent" android:layout_height="150px" android:layout_marginTop="40px" android:gravity="center" android:orientation="vertical">
   <LinearLayout android:layout_width="match_parent" android:layout_height="150px" android:layout_marginTop="40px" android:gravity="center" android:orientation="horizontal">
    <EditText android:id="@+id/donorNameInput" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:hint="Full name" android:textColor="#000000" android:textSize="16dp" />
   <EditText android:id="@+id/donorCityInput" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:hint="City" android:textColor="#000000" />
   </LinearLayout>

The following code adds the donor blood group type and email address:

<LinearLayout android:layout_width="match_parent" android:layout_height="150px" android:layout_marginTop="40px" android:gravity="center" android:orientation="horizontal">
  <EditText android:id="@+id/donorBloodGroupInput" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:hint="Blood Group" android:textColor="#000000" android:textSize="16dp" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="150px" android:layout_marginTop="40px" android:gravity="center" android:orientation="horizontal">
  <EditText android:id="@+id/donorEmailInput" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:hint="Email address" android:textColor="#000000" android:textSize="16dp" />
</LinearLayout>

The following code adds the buttons to act on the data received from the input fields:

<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#36FFFFFF">
  <Button android:id="@+id/loadBtn" android:layout_width="500px" android:layout_height="150px" android:text="Load Donors info" android:textColor="#000000" android:textStyle="bold" />
 <Button android:id="@+id/addBtn" android:layout_width="500px" android:layout_height="150px" android:layout_marginLeft="30px" android:layout_toRightOf="@id/loadBtn" android:text="Add Donor info" android:textColor="#000000" android:textStyle="bold" />
</RelativeLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
</LinearLayout>
</LinearLayout>

You also need each item layout for the RecyclerView, which is defined as follows. In this layout, all you have is four TextView objects:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">
   <TextView android:id="@+id/donorName" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:padding="10px" android:textColor="@color/colorPrimary" android:textSize="25dp" android:textStyle="bold" />
    <TextView android:id="@+id/donorCity" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:padding="10px" android:text="+216 54 821 200" android:textSize="14dp" android:textStyle="italic" />
   <TextView android:id="@+id/donorBloodGroup" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:padding="10px" android:text="+216 54 821 200" android:textSize="14dp" android:textStyle="italic" />
   <TextView android:id="@+id/donorEmail" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:padding="10px" android:text="+216 54 821 200" android:textSize="14dp" android:textStyle="italic" />
</LinearLayout>

Now that you have your user interface in place, it’s time to dive deep into the Java part. Create a class called Donor. This class is a Plain Old Java Object (POJO) class that you’ll use throughout the application since the POJO class dictates the structure of the data.

Android app Logic

The following POJO class expresses the idea and the data format that you’ve to save in Firebase. Using the POJO class, pass the data to the adapter:

package com.ashok.packt.realtime.database.model;


/**
* Created by ashok.kumar on 20/10/17.
*/
public class Donor {
  private String FullName;
  private String Email;
  private String City;
  private String BloodGroup;
  public Donor(){}

Now within the same class, create a constructor for passing the data to the POJO:

public Donor(String fullName, String email, String city, String bloodGroup) {
  FullName = fullName;
  Email = email;
  City = city;
  BloodGroup = bloodGroup;
}

public String getFullName() {
  return FullName;
}

public void setFullName(String fullName) {
  FullName = fullName;
}

public String getEmail() {
  return Email;
}

public void setEmail(String email) {
  Email = email;
}

public String getCity() {
  return City;
}

public void setCity(String city) {
  City = city;
}

public String getBloodGroup() {
  return BloodGroup;
}

public void setBloodGroup(String bloodGroup) {
  BloodGroup = bloodGroup;
}

}

Now write the Adapter class. The Adapter class requires POJO, view holder, and row layout. Consider spending some time on understanding the RecyclerView adapter:

package com.ashok.packt.realtime.database.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.ashok.packt.realtime.database.R;
import com.ashok.packt.realtime.database.model.Donor;
import java.util.List;
/**
* Created by ashok.kumar on 20/05/18.
*/
public class RecyclerViewAdapter extends 
   RecyclerView.Adapter<RecyclerViewAdapter.View_Holder>{
  private Context mContext;
  private List&lt;Donor&gt; ItemList;
  public RecyclerViewAdapter(Context mContext, List<Donor> itemList) {
    this.mContext = mContext;
    ItemList = itemList;
  }

The constructors require context and a list of donor objects for setting the data in RecyclerView callbacks.

@Override
public View_Holder onCreateViewHolder(ViewGroup parent, int viewType) {
  View itemView = LayoutInflater.from(parent.getContext())
     .inflate(R.layout.donor_list_row, parent, false);
  return new View_Holder(itemView);
}

The above Override method will be responsible for inflating the donor list item row.

@Override
public void onBindViewHolder(View_Holder holder, int position) {
  Donor Item = ItemList.get(position);
  holder.Name.setText(Item.getFullName());
  holder.City.setText(Item.getCity());
  holder.BloodGroup.setText(Item.getBloodGroup());
  holder.Email.setText(Item.getEmail());
}

@Override
public int getItemCount() {
  return ItemList.size();
}

public class View_Holder extends RecyclerView.ViewHolder {
  TextView Name;
  TextView City;
  TextView BloodGroup;
  TextView Phone;
  TextView Email;
  View_Holder(View itemView) {
    super(itemView);
    Name = (TextView) itemView.findViewById(R.id.donorName);
    City = (TextView) itemView.findViewById(R.id.donorCity);
    BloodGroup = (TextView) itemView.findViewById(R.id.donorBloodGroup);
    Email = (TextView) itemView.findViewById(R.id.donorEmail);
  }
 }
}

Now, MainActivity holds the complete logic for the application by adding the data to Firebase, fetching the data from Firebase, and loading it in RecyclerView. Here are methods to update, find, and delete for your future reference:

package com.ashok.packt.realtime.database;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import com.ashok.packt.realtime.database.adapter.RecyclerViewAdapter;
import com.ashok.packt.realtime.database.model.Donor;
import com.google.firebase.database.ChildEventListener;
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.Query;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MainActivity extends AppCompatActivity {
  private DatabaseReference myDatabaseReference;
  private String personId;
  private List&lt;Donor&gt; ItemList;

  private RecyclerView mRecyclerview;
  private RecyclerViewAdapter mAdapter;

Initialize all the above code in the onCreate method as shown below:

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  mRecyclerview = (RecyclerView) findViewById(R.id.peopleList); 
  RecyclerView.LayoutManager mLayoutManager = 
      new LinearLayoutManager(this);
  
  mRecyclerview.setLayoutManager(mLayoutManager);
  // for data persistence 
  FirebaseDatabase.getInstance().setPersistenceEnabled(true);
  myDatabaseReference=FirebaseDatabase.getInstance().getReference("Donor");
  personId= myDatabaseReference.push().getKey();
  (findViewById(R.id.addBtn)).setOnClickListener(
     new View.OnClickListener() {
        @Override
        public void onClick(View view) {
          String FullName = ((EditText)findViewById(R.id.donorNameInput))
              .getText().toString();
          String Email = ((EditText)findViewById(R.id.donorEmailInput))
              .getText().toString();
          String City = ((EditText)findViewById(R.id.donorCityInput))
              .getText().toString();
          String BloodGroup = ((EditText)findViewById(R.id.donorBloodGroupInput))
              .getText().toString();
          addPerson(FullName,Email, City, BloodGroup);
        }
   });
   (findViewById(R.id.loadBtn)).setOnClickListener(
      new View.OnClickListener() {
         @Override
         public void onClick(View view) {
            readData();
         }
    });
}

After adding the views, it’s now time to work on adding and retrieving data:

private void addPerson(String name, String Email, 
                       String city, String Bloodgroup){
    personId= myDatabaseReference.push().getKey();
    Donor person = new Donor(name, Email, city, Bloodgroup);
    myDatabaseReference.child(personId).setValue(person);
}

private void updatePerson(String name,int phoneNumber){
   myDatabaseReference.child(personId).child("fullName").setValue(name);
   myDatabaseReference.child(personId).child("phoneNumber").setValue(phoneNumber);
}

 private void removePerson(String name){
   myDatabaseReference.child(personId).removeValue();
 }

private void readData(){
  ItemList = new ArrayList<>();  
  myDatabaseReference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) { 
      Iterable&lt;DataSnapshot&gt; snapshotIterator = dataSnapshot.getChildren();
      Iterator&lt;DataSnapshot&gt; iterator = snapshotIterator.iterator();
      while((iterator.hasNext())){
        Donor donor = iterator.next().getValue(Donor.class);
        ItemList.add(donor);
        mAdapter.notifyDataSetChanged();
    }
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
  }
 });

  mAdapter = new RecyclerViewAdapter(this, ItemList);
  mRecyclerview.setAdapter(mAdapter);
}

You can also search for the specific as shown below:

private void findPerson(String name){
  Query deleteQuery = myDatabaseReference.orderByChild("fullName").equalTo(name);
  deleteQuery.addChildEventListener(new ChildEventListener() {

  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String s) {
   Iterable<DataSnapshot> snapshotIterator = dataSnapshot.getChildren();
   Iterator<DataSnapshot> iterator = snapshotIterator.iterator();

   while((iterator.hasNext())){
    Log.d("Item found: ",iterator.next().getValue().toString()+"---");
   }
}

@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}

@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}

@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}

@Override
public void onCancelled(DatabaseError databaseError) {
  Log.d("Item not found: ","this item is not in the list");
}
});
}
}

When you compile and run the program in your Android device, the output will have the following look and feel:

Realtime database Android app

You’ve now successfully created an app that collects information related to blood donors. If you found this tutorial interesting and want to learn more about Firebase, you can explore Mastering Firebase for Android Development. The book follows a step-by-step practical approach to get you up to speed with the different features of Firebase, enabling you to develop scalable and efficient Android applications.

LEAVE A REPLY

Please enter your comment!
Please enter your name here