Using Firebase Database (Android)


The Firebase database is a NoSQL, real-time, and cloud-hosted database. Data is stored as JSON and synchronized in real-time to every connected client. The following steps show how to use the Firebase database:
The Android and Firebase code given in this course is correct, but it may not work for current SDK or API because of the backward compatibility issue. You should be able to fix it by checking the error messages.
For the Web, check Using Firebase Database (Web).
  1. Open Android Studio and create a new project or open an existing project.

    Pick if Java is used.

  2. 🡆


    🡆


  3. In Android Studio, log in with your email address. You can find the login button at the top right corner of the Android Studio. (Remember the email address that you use here.)




  4. 🡆


    🡆

    🡆


    🡆


  5. Go to Google Firebase console and make an account to gain access to their console.


  6. Start creating your first Firebase project:


  7. 🡆


    🡆

    🡆


    🡆

    🡆


    🡆

    🡆


    🡆

    🡆


    🡆

    🡆


    If you select the “Test Mode,” your code has to include authentication, which you must update your security rules within 30 days to enable long-term client read/write access.


  8. Now, come back to your Android Studio project. Connect the Android Studio project to the Firebase project by clicking on 🡆 🡆 🡆 .


  9. After that click on , a list of projects will be shown to you. Select the project that you have created on the Firebase website and click on .

  10. 🡆


    🡆


  11. Next, you have to add the dependency of Firebase Database in your project by clicking on button and then .



  12. 🡇 (after checking )


    The build.gradle (Module: My_Firebase.app) file before adding the dependencies is

    MyFirebase\build.gradle (Module: My_Firebase.app)
     plugins {
       id 'com.android.application'
     }
     android {
       compileSdkVersion 30
       buildToolsVersion "30.0.2"
       defaultConfig {
         applicationId "com.wenchen.myfirebase"
         minSdkVersion 16
         targetSdkVersion 30
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
       }
       buildTypes {
         release {
         minifyEnabled false
         proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
           'proguard-rules.pro'
         }
       }
       compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
       }
     }
     dependencies {
       implementation 'androidx.appcompat:appcompat:1.2.0'
       implementation 'com.google.android.material:material:1.3.0'
       implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
       testImplementation 'junit:junit:4.+'
       androidTestImplementation 'androidx.test.ext:junit:1.1.2'
       androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
     }

    🡇 (after adding the dependencies)

    MyFirebase\build.gradle (Module: My_Firebase.app)
     plugins {
       id 'com.android.application'
       id 'com.google.gms.google-services'
     }
    
     android {
       compileSdkVersion 30
       buildToolsVersion "30.0.2"
       defaultConfig {
         applicationId "com.wenchen.myfirebase"
         minSdkVersion 16
         targetSdkVersion 30
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
       }
       buildTypes {
         release {
           minifyEnabled false
           proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 
             'proguard-rules.pro'
         }
       }
       compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
       }
     }
     dependencies {
       implementation 'androidx.appcompat:appcompat:1.2.0'
       implementation 'com.google.android.material:material:1.3.0'
       implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
       implementation 'com.google.firebase:firebase-database:19.6.0'
       testImplementation 'junit:junit:4.+'
       androidTestImplementation 'androidx.test.ext:junit:1.1.2'
       androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
     }
    If there is an error of 

      File google-services.json is missing from module root folder. The Google Services Plugin cannot function without it.” 

    Take the following actions: 

    1. Go to Firebase Console
    2. Select your project. 
    3. Go to “settings 🡆 project settings.” 
    4. Download and add the google-services.json file to the app folder of your app at 

      MyFirebase\app\google-services.json 
  13. The rest of the code is given as follows:
  14. The AndroidManifest.xml file does not need to be changed as follows:

    MyFirebase\app\manifests\AndroidManifest.xml
     <?xml version="1.0" encoding="utf-8"?>
     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.wenchen.myfirebase">
       <application
           android:allowBackup = "true"
           android:icon        = "@mipmap/ic_launcher"
           android:label       = "@string/app_name"
           android:roundIcon   = "@mipmap/ic_launcher_round"
           android:supportsRtl = "true"
           android:theme       = "@style/Theme.MyFirebase">
         <activity android:name=".MainActivity">
           <intent-filter>
             <action android:name   = "android.intent.action.MAIN" />
             <category android:name = "android.intent.category.LAUNCHER" />
           </intent-filter>
         </activity>
       </application>
     </manifest>

    Add code to the main_activity.xml file. This application updates and shows the user’s profile consisting of a name and an email address. So, we will have one TextView for showing the profile and two EditTexts for getting the new values from the user, and an update button. The code for the main_activity.xml file is given as follows:

    MyFirebase\app\res\layout\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.wenchen.myfirebase.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">
         <com.google.android.material.textfield.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" />
         </com.google.android.material.textfield.TextInputLayout>
         <com.google.android.material.textfield.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" />
         </com.google.android.material.textfield.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>
    If there is an inflate error because of com.google.android.material.textfield.TextInputLayout, add the following line to the gradle file: 

     implementation 'com.google.android.material:material:1.0.0'
    The strings.xml file is given as follows:

    MyFirebase\app\res\values\strings.xml
     <resources>
       <string name="app_name">My Firebase</string>
       <string name="hint_name">Full Name</string>
       <string name="hint_email">Email</string>
       <string name="action_save">Save</string>
       <string name="name">Name</string>
       <string name="email">Email</string>
     </resources>

    The dimens.xml file is given as follows:

    MyFirebase\app\res\values\dimens.xml
     <resources>
       <!-- Default screen margins, per the Android Design guidelines. -->
       <dimen name="activity_horizontal_margin">16dp</dimen>
       <dimen name="activity_vertical_margin">16dp</dimen>
     </resources>

    The styles.xml file is given as follows:

    MyFirebase\app\res\values\styles.xml
     <resources>
       <!-- Base application theme. -->
       <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
         <!-- Customize your theme here. -->
         <item name="colorPrimary">@color/colorPrimary</item>
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
         <item name="colorAccent">@color/colorAccent</item>
       </style>
     </resources>

    The colors.xml file is given as follows:

    MyFirebase\app\res\values\colors.xml
     <resources>
       <color name="colorPrimary">#00bcd4</color>
       <color name="colorPrimaryDark">#0097a7</color>
       <color name="colorAccent">#0097a7</color>
     </resources>

    The MainActivity.java program saves the name and email address of a user in the Firebase database when starts a new session (emulator). Afterwards, only the current user’s profile (name and email address) can be updated unless another session starts, and the previous profiles are not able to be updated.

    MyFirebase\app\java\com\wenchen\myfriebase\MainActivity.java
     package com.wenchen.myfirebase
    
     import android.os.Bundle;
     import androidx.appcompat.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
         // The action bar does not work, so they are commented out.
         androidx.appcompat.app.ActionBar actionBar = getSupportActionBar( );
         if ( actionBar != null ) {
           // You can safely call methods on the ActionBar now
           actionBar.setDisplayHomeAsUpEnabled( true );
           actionBar.setIcon( R.mipmap.ic_launcher );
         }
         else {
           // Handle the case where the ActionBar is not available
           // (e.g., log an error, use a different UI element, etc.)
           Log.e( "MyFirebase", "Action bar is null, cannot set properties");
         }
         // 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( );
         // Getting reference to 'users' node
         mFirebaseDatabase = mFirebaseInstance.getReference( "users" );
         // Storing 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 );
    
               // Updating toolbar title
               // The action bar does not work, so they are commented out.
               if ( actionBar != null ) {
                 // You can safely call methods on the ActionBar now
                 actionBar.setTitle( appTitle );
               }
               else {
                 // Handle the case where the ActionBar is not available
                 // (e.g., log an error, use a different UI element, etc.)
                 Log.e( "MyFirebase", "Action bar is null, cannot set properties" );
               }
               // getSupportActionBar( ).setTitle( appTitle );
             }
             @Override
             public void onCancelled( DatabaseError error ) {
               // Failed to read value
               Log.e( TAG, "Failed to read app title value.", error.toException( ) );
             }
           }
         );
         // Saving or updating the user
         btnSave.setOnClickListener( 
           new View.OnClickListener( ) {
             @Override
             public void onClick( View view ) {
               String name  = inputName.getText(  ).toString( );
               String email = inputEmail.getText( ).toString( );
               // Checking 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 using 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( ) {
         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 );
               // Displaying newly updated name and email
               txtDetails.setText( user.name + ", " + user.email );
               // Clearing 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 );
       }
     }

    In order to save a user profile, we use a model class called User.java file to store the properties of name and email address (you can add few more properties like address, phone number, etc.):

    MyFirebase\app\java\com\wenchen\myfriebase\User.java
     package com.wenchen.myfirebase
     import com.google.firebase.database.IgnoreExtraProperties;
    
     @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;
       }
     }

  15. Start testing the project:

  16. 🡆

    🡆

     

    🡆

    🡆

    🡆

     
    New
    session

    🡆

    🡆

     

    🡆

     
    New
    session

    🡆

    🡆





      Q: What’s the hottest letter in the alphabet?    
      A: ‘B’, because it makes oil…Boil!