Hire the author: Moses N
Image Source https://blog.scalefusion.com/wp-content/uploads/2FA-fb@2x-768×497.png
Here is the GitHub – android-2step authentication-Firebase link for this project.
Introduction
Firebase authentication adds one layer of security while Android two-step authentication henceforth will add an extra layer of security to your application. In this blog, we are going to follow a step by step tutorial on how to create an android two-step authentication signup system using Firebase and as a result, it will add a second layer of authentication”two-factor authentication (2FA)”.
Firebase is Google’s mobile platform that helps you quickly develop high-quality apps because it provides a real-time database and backend as a service and in the two-step authentication signup system we will use Firebase services such as Firebase real-time database and Firebase authentication.
What motivated me in doing this project “android two-step authentication signup system using Firebase” is because security is the key thing in each and every application more so allowing a two-step authentication will add another layer of security before a user manages to access the application. In Addition, Android technology is on the rise such that each and every person finds it easy to own, hence most of the system is shifting to having an android application, and applying this two-step authentication for users will increase security.
How to Get Started
This project is a starting point for Firebase application development and below are a few resources to get you prepared before starting this project:
- Add Firebase to your Android project.
- Guide to Firebase Authentication.
- Firebase Realtime Database.
- Guide to Firebase Storage.
Online documentation is essential and it offers tutorials, samples, guidance on mobile development, and a full API reference. However, You can check on the Firebase documentation.
Photo Preview



Glossary
- Firebase – is a Backend-as-a-Service (Baas) because It provides developers with a variety of tools. Also, services to help them develop quality apps, grow their user base, and earn a profit.
- Authentication – Authentication is the process of determining whether someone or something is, in fact, who or what it declares itself to be. For instance, Authentication technology provides access control for systems. Checking to see if a user’s credentials match the credentials in a database of authorized users or in a data authentication server
- Verification – is the process of checking user details are correct. For instance, the password field and confirming the password is correct.
- A Reference – represents a specific location in your Database. It can be used for reading or writing data to that Database location.
- Intent – In android, an intent is a software mechanism that allows users to coordinate the functions of different activities to achieve a task. As a result, It allows one to navigate within activities easily.
Steps:
Step 1: Connecting android studio project to Firebase
Firstly, let’s connect the android studio to Firebase and we will be using user email. We will then connect our project to the Firebase. Since we will be using Firebase services such as Firebase Authentication, Firebase real-time database, and Firebase storage.
To connect with your email.
- On the top left of the menu, toolbar click on it. Click “add account”.
- You will be directed to log in to your email.
- Enter the email and password.
- Click on Firebase console.
Once connected your project should have your email as shown below in the image.

To connect to Firebase services.
- On the android studio, click on the Tools menu.
- Then click on Firebase.
- A menu containing Firebase services will appear on your right.
- Click on Firebase Authentication. Connect to Firebase.
- Enter the name of your project and click on email and password to add Firebase authentication dependencies.
- Click on the real-time database, then on save and retrieve data.
- Lastly, click on storage “upload and download a file with cloud storage”
As a result, all Firebase dependencies are added to your project.

//firebase dependencies
implementation 'com.google.firebase:firebase-auth:16.0.5'
implementation 'com.google.firebase:firebase-storage:16.0.4'
implementation 'com.google.firebase:firebase-database:16.0.4'
//firebase dependencies
The first is used for Firebase authentication and more so the version will depend on the version android studio you are using. Moreover, you can use a higher version or stick to this.
To allow a user to sign in with email and password.
- Go to Firebase console.
- Choose your application
- Click on authentication on the left side menu.
- Sign-in method.
- Enable email/password.

By default, your database rules require Firebase Authentication while Grant full read and write permissions only to authenticated users. The default rules ensure your database isn’t accessible by just anyone. Once you’re set-up, you can customize your rules to your needs. In this case, in order to write and read from Firebase. We will allow full user permission.
- On the Firebase console right menu.
- Click on the database.
- Then User and permissions.
- Write this code shown below to allow permissions.
// These rules allow anyone read or write access to your database
{
"rules": {
".read": true,
".write": true
}
}
build.gradle(Module: app) project dependencies.
dependencies { | |
implementation fileTree(dir: 'libs', include: ['*.jar']) | |
implementation 'androidx.appcompat:appcompat:1.1.0' | |
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' | |
//firebase dependencies | |
implementation 'com.google.firebase:firebase-auth:16.0.5' | |
implementation 'com.google.firebase:firebase-storage:16.0.4' | |
implementation 'com.google.firebase:firebase-database:16.0.4' | |
//firebase dependencies | |
testImplementation 'junit:junit:4.12' | |
androidTestImplementation 'androidx.test.ext:junit:1.1.1' | |
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' | |
//User design dependencies | |
implementation 'com.google.android.material:material:1.0.0' | |
implementation 'androidx.recyclerview:recyclerview:1.1.0' | |
implementation 'de.hdodenhof:circleimageview:3.0.2' | |
//User design dependencies | |
} |
We are going to add some dependencies purposely for designing a good user interface.
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'de.hdodenhof:circleimageview:3.0.2'
Step 2: Designing the home Activity
This will be the final page. “Home”. Because we will land here after the two-step authentication. In order to complete our stages, we will first design this page so that after completing the second step of authentication we will land here.
<?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" | |
tools:context=".MainActivity"> | |
<com.google.android.material.appbar.AppBarLayout | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:theme="@style/AppTheme.AppBarOverlay"> | |
<androidx.appcompat.widget.Toolbar | |
android:id="@+id/main_toolbar" | |
android:layout_width="match_parent" | |
android:layout_height="?attr/actionBarSize" | |
android:background="?attr/colorPrimary" | |
app:popupTheme="@style/AppTheme.PopupOverlay" /> | |
</com.google.android.material.appbar.AppBarLayout> | |
<com.google.android.material.card.MaterialCardView | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_margin="20dp" | |
android:layout_marginTop="50dp" | |
android:background="@drawable/button" | |
android:layout_centerInParent="true" | |
app:cardElevation="5dp" | |
app:cardCornerRadius="8dp"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:orientation="vertical"> | |
<RelativeLayout | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="5dp" | |
android:layout_marginLeft="5dp" | |
android:layout_marginTop="20dp" | |
> | |
<TextView | |
android:id="@+id/title" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="8dp" | |
android:text="Two Step Authentication" | |
android:textAlignment="center" | |
android:textColor="@color/colorRed" | |
android:textSize="24sp" | |
android:textStyle="bold" /> | |
<View | |
android:layout_width="match_parent" | |
android:layout_height="2dp" | |
android:layout_below="@id/logo" | |
android:layout_marginLeft="8dp" | |
android:layout_marginRight="24dp" | |
android:layout_marginTop="-20dp" | |
android:background="@color/colorPrimaryDark" | |
android:layout_marginStart="8dp" | |
android:layout_marginEnd="24dp" /> | |
<de.hdodenhof.circleimageview.CircleImageView | |
android:id="@+id/logo" | |
android:elevation="5dp" | |
android:layout_width="100dp" | |
android:layout_height="100dp" | |
android:layout_centerVertical="true" | |
android:layout_gravity="center" | |
android:layout_marginLeft="20dp" | |
android:layout_marginTop="60dp" | |
android:layout_toEndOf="@+id/title" | |
android:layout_toRightOf="@+id/title" | |
android:src="@mipmap/ic_launcher" /> | |
</RelativeLayout> | |
<TextView | |
android:id="@+id/welcome" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="Thank you for Completing the two step authentication with Firebase, Happy Coding" | |
android:textColor="@color/deepBlue" | |
android:textAlignment="center" | |
android:layout_gravity="center" | |
android:textSize="20sp" | |
android:layout_margin="20dp" | |
android:textStyle="italic"/> | |
</LinearLayout> | |
</com.google.android.material.card.MaterialCardView> | |
</LinearLayout> |
Step 3: Designing First step Authentication
It will involve registering user information via email and password. Create a step_one_authentication activity to hold the user registration information.
It contains three edit texts, three text views, and one button, and most importantly these fields, “email, password and confirm password”.
<?xml version="1.0" encoding="utf-8"?> | |
<ScrollView | |
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" | |
tools:context=".Register"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:orientation="vertical"> | |
<RelativeLayout | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="5dp" | |
android:layout_marginLeft="5dp" | |
android:layout_marginTop="2dp"> | |
<TextView | |
android:id="@+id/title" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="8dp" | |
android:text="Two Step Authentication" | |
android:textAlignment="center" | |
android:textColor="@color/colorRed" | |
android:textSize="24sp" | |
android:textStyle="bold" /> | |
<View | |
android:layout_width="match_parent" | |
android:layout_height="2dp" | |
android:layout_below="@id/logo" | |
android:layout_marginLeft="8dp" | |
android:layout_marginRight="24dp" | |
android:layout_marginTop="-20dp" | |
android:background="@color/colorPrimaryDark" | |
android:layout_marginStart="8dp" | |
android:layout_marginEnd="24dp" /> | |
<de.hdodenhof.circleimageview.CircleImageView | |
android:id="@+id/logo" | |
android:elevation="5dp" | |
android:layout_width="50dp" | |
android:layout_height="50dp" | |
android:layout_centerVertical="true" | |
android:layout_gravity="center" | |
android:layout_marginLeft="20dp" | |
android:layout_marginTop="60dp" | |
android:layout_toEndOf="@+id/title" | |
android:layout_toRightOf="@+id/title" | |
android:src="@mipmap/ic_launcher" /> | |
</RelativeLayout> | |
<TextView | |
android:id="@+id/personalInformation" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="Step one Authentication" | |
android:textColor="@color/colorRed" | |
android:textAlignment="center" | |
android:layout_gravity="center" | |
android:textSize="20sp" | |
android:textStyle="italic"/> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="Email Address" | |
android:textSize="18sp" | |
android:layout_marginLeft="10dp" | |
/> | |
<EditText | |
android:id="@+id/editemail" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:hint="Enter your email adress" | |
android:background="@drawable/input_field" | |
android:padding="15dp" | |
android:drawableLeft="@drawable/ic_email" | |
android:inputType="textEmailAddress" | |
android:layout_margin="10dp"/> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="Password" | |
android:textSize="18sp" | |
android:layout_marginLeft="10dp" | |
/> | |
<EditText | |
android:id="@+id/editPassword" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:hint="Password" | |
android:inputType="textPassword" | |
android:background="@drawable/input_field" | |
android:drawableLeft="@drawable/ic_lock" | |
android:padding="15dp" | |
android:layout_margin="10dp"/> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="Confirm Password" | |
android:textSize="18sp" | |
android:layout_marginLeft="10dp" | |
/> | |
<EditText | |
android:id="@+id/editPasswordConfirm" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:hint="Password" | |
android:background="@drawable/input_field" | |
android:drawableLeft="@drawable/ic_lock" | |
android:padding="15dp" | |
android:inputType="textPassword" | |
android:layout_margin="10dp"/> | |
<Button | |
android:id="@+id/register_button" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginBottom="5dp" | |
android:layout_marginLeft="15dp" | |
android:layout_marginRight="15dp" | |
android:background="@drawable/input" | |
android:padding="10dp" | |
android:textSize="18dp" | |
android:textAllCaps="false" | |
android:layout_marginTop="24dp" | |
android:layout_gravity="center" | |
android:textColor="@android:color/white" | |
android:text="Register" | |
/> | |
</LinearLayout> | |
On the stepOneAuthentication let’s allow the user to register via email and password. We will also make sure that the user does not leave any of the fields blank and also confirm that the password and password confirm matches.
if (TextUtils.isEmpty(Email)){
Toast.makeText(Register.this, "Please enter your email...", Toast.LENGTH_SHORT).show();
}
else if(TextUtils.isEmpty(Password)){
Toast.makeText(Register.this, "Please enter your password...", Toast.LENGTH_SHORT).show();
}
else if (TextUtils.isEmpty(PasswordConfirm)){
Toast.makeText(Register.this, "PLease confirm your password...", Toast.LENGTH_SHORT).show();
}
else if(!Password.equals(PasswordConfirm)){
Toast.makeText(Register.this, "Password do no match...", Toast.LENGTH_SHORT).show();
}
We will use a Firebase method as shown below to allow registering through email and password and if the task is successful, the user is directed to second step authentication. If not an error message pops up.
mAuth.createUserWithEmailAndPassword(Email,Password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
//checking if the task is sucessful
if(task.isSuccessful()){ SenduserToSTepTwoAuthentication(); Toast.makeText(Register.this, "You have passed the first step authentication...", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
else{
String message = task.getException().getMessage(); Toast.makeText(Register.this, "error occured" + message, Toast.LENGTH_SHORT).show(); }
loadingBar.dismiss();
}
});
package com.example.twostepauthentication; | |
import androidx.annotation.NonNull; | |
import androidx.appcompat.app.AppCompatActivity; | |
import android.app.ProgressDialog; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.text.TextUtils; | |
import android.view.View; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.ProgressBar; | |
import android.widget.Toast; | |
import com.google.android.gms.tasks.OnCompleteListener; | |
import com.google.android.gms.tasks.Task; | |
import com.google.firebase.auth.AuthResult; | |
import com.google.firebase.auth.FirebaseAuth; | |
import com.google.firebase.auth.FirebaseUser; | |
public class Register extends AppCompatActivity { | |
private EditText edit_email,edit_password,edit_confirmPassword; | |
private Button register; | |
private FirebaseAuth mAuth; | |
//adding a progress dialog box | |
private ProgressDialog loadingBar; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_register); | |
mAuth = FirebaseAuth.getInstance(); | |
edit_email = findViewById(R.id.editemail); | |
edit_password =findViewById(R.id.editPassword); | |
edit_confirmPassword = findViewById(R.id.editPasswordConfirm); | |
loadingBar = new ProgressDialog(this); | |
register = findViewById(R.id.register_button); | |
register.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) | |
{ | |
//creating account for users | |
CreateNewAccount(); | |
} | |
}); | |
} | |
@Override | |
protected void onStart() { | |
super.onStart(); | |
FirebaseUser currentUser = mAuth.getCurrentUser(); | |
if (currentUser !=null) | |
{ | |
SendUserToMainActivity(); | |
} | |
} | |
private void SendUserToMainActivity() | |
{ | |
Intent mainIntent = new Intent(Register.this,MainActivity.class); | |
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); | |
startActivity(mainIntent); | |
finish(); | |
} | |
private void CreateNewAccount() | |
{ | |
//getting the values from the input fields | |
String Email = edit_email.getText().toString(); | |
String Password = edit_password.getText().toString(); | |
String PasswordConfirm = edit_confirmPassword.getText().toString(); | |
//adding validation if user left any of the fields empty | |
if (TextUtils.isEmpty(Email)){ | |
Toast.makeText(Register.this, "Please enter your email...", Toast.LENGTH_SHORT).show(); | |
} | |
else if(TextUtils.isEmpty(Password)){ | |
Toast.makeText(Register.this, "Please enter your password...", Toast.LENGTH_SHORT).show(); | |
} | |
else if (TextUtils.isEmpty(PasswordConfirm)){ | |
Toast.makeText(Register.this, "PLease confirm your password...", Toast.LENGTH_SHORT).show(); | |
} | |
else if(!Password.equals(PasswordConfirm)){ | |
Toast.makeText(Register.this, "Password do no match...", Toast.LENGTH_SHORT).show(); | |
} | |
else{ | |
//progress bar | |
loadingBar.setTitle("Creating new Account"); | |
loadingBar.setMessage("please wait..."); | |
loadingBar.show(); | |
loadingBar.setCanceledOnTouchOutside(true); | |
//creating account for user | |
mAuth.createUserWithEmailAndPassword(Email,Password) | |
.addOnCompleteListener(new OnCompleteListener<AuthResult>() { | |
@Override | |
public void onComplete(@NonNull Task<AuthResult> task) { | |
//checking if the task is sucessful | |
if (task.isSuccessful()){ | |
SenduserToSTepTwoAuthentication(); | |
Toast.makeText(Register.this, "You have passed the first step authentication...", Toast.LENGTH_SHORT).show(); | |
loadingBar.dismiss(); | |
} | |
else{ | |
String message = task.getException().getMessage(); | |
Toast.makeText(Register.this, "error occured" + message, Toast.LENGTH_SHORT).show(); } | |
loadingBar.dismiss(); | |
} | |
}); | |
} | |
} | |
private void SenduserToSTepTwoAuthentication() | |
{ | |
Intent setupIntent = new Intent(Register.this,StepTwoAuthentication.class); | |
setupIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); | |
startActivity(setupIntent); | |
finish(); | |
} | |
{ | |
} | |
} |
Step 4: Designing Login Activity
Only users who have passed the first step authentication can log in to the system. For instance, if you enter your email and password, these fields are authenticated. If they exist in the Firebase authentication real-time database, the user is directed to the second step authentication.

Login user interface code looks like:
<?xml version="1.0" encoding="utf-8"?> | |
<androidx.constraintlayout.widget.ConstraintLayout 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" | |
tools:context=".Login"> | |
<RelativeLayout | |
android:id="@+id/relativeLayout" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="16dp" | |
android:layout_marginLeft="16dp" | |
android:layout_marginTop="16dp" | |
android:layout_marginEnd="16dp" | |
android:layout_marginRight="16dp" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toTopOf="parent"> | |
<TextView | |
android:id="@+id/title" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="8dp" | |
android:text="Two Step Authentication" | |
android:textAlignment="center" | |
android:textColor="@color/colorRed" | |
android:textSize="24sp" | |
android:textStyle="bold" /> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="8dp" | |
android:text="Login" | |
android:typeface="serif" | |
android:padding="3dp" | |
android:layout_above="@+id/view" | |
android:layout_marginBottom="20dp" | |
android:textAlignment="center" | |
android:textColor="@color/colorPrimaryDark" | |
android:textSize="24sp" | |
android:textStyle="bold" /> | |
<View | |
android:id="@+id/view" | |
android:layout_width="match_parent" | |
android:layout_height="2dp" | |
android:layout_below="@id/logo" | |
android:layout_marginStart="8dp" | |
android:layout_marginLeft="8dp" | |
android:layout_marginTop="-20dp" | |
android:layout_marginEnd="24dp" | |
android:layout_marginRight="24dp" | |
android:background="@color/colorPrimaryDark" /> | |
<de.hdodenhof.circleimageview.CircleImageView | |
android:id="@+id/logo" | |
android:layout_width="100dp" | |
android:layout_height="100dp" | |
android:layout_centerVertical="true" | |
android:layout_gravity="center" | |
android:layout_marginLeft="20dp" | |
android:layout_marginTop="60dp" | |
android:layout_toEndOf="@+id/title" | |
android:layout_toRightOf="@+id/title" | |
android:elevation="5dp" | |
android:src="@mipmap/ic_launcher" /> | |
</RelativeLayout> | |
<EditText | |
android:id="@+id/editemail" | |
android:layout_width="0dp" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="24dp" | |
android:layout_marginTop="16dp" | |
android:layout_marginEnd="24dp" | |
android:layout_marginRight="24dp" | |
android:background="@drawable/input_field" | |
android:ems="10" | |
android:inputType="textEmailAddress" | |
android:hint="Email" | |
android:drawableLeft="@drawable/ic_email" | |
android:padding="16dp" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/relativeLayout" /> | |
<EditText | |
android:id="@+id/editpassword" | |
android:layout_width="0dp" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="24dp" | |
android:layout_marginTop="16dp" | |
android:layout_marginEnd="24dp" | |
android:layout_marginRight="24dp" | |
android:ems="10" | |
android:padding="16dp" | |
android:background="@drawable/input_field" | |
android:inputType="textPassword" | |
android:hint="Password" | |
android:drawableLeft="@drawable/ic_lock" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/editemail" /> | |
<CheckBox | |
android:id="@+id/checkBox" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="24dp" | |
android:layout_marginTop="16dp" | |
android:textSize="16sp" | |
android:text="Remember me" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/editpassword" /> | |
<TextView | |
android:id="@+id/textView" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="18dp" | |
android:layout_marginEnd="24dp" | |
android:layout_marginRight="24dp" | |
android:text="Forgot Password?" | |
android:textSize="16sp" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintHorizontal_bias="1.0" | |
app:layout_constraintStart_toEndOf="@+id/checkBox" | |
app:layout_constraintTop_toBottomOf="@+id/editpassword" /> | |
<Button | |
android:id="@+id/loginbutton" | |
android:layout_width="0dp" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="24dp" | |
android:layout_marginTop="16dp" | |
android:layout_marginEnd="24dp" | |
android:layout_marginRight="24dp" | |
android:text="Login" | |
android:textColor="@android:color/white" | |
android:textAllCaps="false" | |
android:background="@drawable/input" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/textView" /> | |
<TextView | |
android:id="@+id/textView4" | |
android:layout_width="0dp" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center" | |
android:layout_marginTop="24dp" | |
android:padding="10dp" | |
android:text="Don't have an Account?" | |
android:textAlignment="center" | |
android:textAllCaps="false" | |
android:textColor="@color/colorPrimaryDark" | |
android:textSize="18dp" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintHorizontal_bias="0.0" | |
app:layout_constraintStart_toStartOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/loginbutton" /> | |
<TextView | |
android:id="@+id/RegisterText" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center" | |
android:layout_marginBottom="168dp" | |
android:onClick="RegisteActivity" | |
android:text="Register" | |
android:textAlignment="center" | |
android:textAllCaps="false" | |
android:textColor="@color/colorRed" | |
android:textSize="18dp" | |
android:textStyle="bold" | |
app:layout_constraintBottom_toBottomOf="parent" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintStart_toStartOf="parent" /> | |
</androidx.constraintlayout.widget.ConstraintLayout> |
FirebaseUser currentUser = mAuth.getCurrentUser();
Gets the current User. For instance, the user who has just has registered
currentUser !=null
Ensures that the user is not equal to null. If a user is null. He is prompted to register.
package com.example.twostepauthentication; | |
import androidx.annotation.NonNull; | |
import androidx.appcompat.app.AppCompatActivity; | |
import android.app.ProgressDialog; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.text.TextUtils; | |
import android.view.View; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.Toast; | |
import com.google.android.gms.tasks.OnCompleteListener; | |
import com.google.android.gms.tasks.Task; | |
import com.google.firebase.auth.AuthResult; | |
import com.google.firebase.auth.FirebaseAuth; | |
import com.google.firebase.auth.FirebaseUser; | |
public class Login extends AppCompatActivity { | |
private EditText edit_email,edit_password; | |
private Button login_Button; | |
private FirebaseAuth mAuth; | |
private ProgressDialog loadingBar; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_login); | |
mAuth = FirebaseAuth.getInstance(); | |
edit_email =findViewById(R.id.editemail); | |
edit_password = findViewById(R.id.editpassword); | |
login_Button = findViewById(R.id.loginbutton); | |
//logging the user in | |
loadingBar =new ProgressDialog(this); | |
login_Button.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) | |
{ | |
AllowUserToLogin(); | |
FirebaseUser currentUser = mAuth.getCurrentUser(); | |
if (currentUser !=null) | |
{ | |
SendUserToMainActivity(); | |
} | |
} | |
}); | |
} | |
@Override | |
protected void onStart() { | |
super.onStart(); | |
} | |
private void AllowUserToLogin() | |
{ | |
String email = edit_email.getText().toString().trim(); | |
String password = edit_password.getText().toString().trim(); | |
if (TextUtils.isEmpty(email)) | |
{ | |
Toast.makeText(this, "Please write your email...", Toast.LENGTH_SHORT).show(); | |
} | |
else if(TextUtils.isEmpty(password)){ | |
Toast.makeText(this, "Please write your password", Toast.LENGTH_SHORT).show(); | |
} | |
else | |
{ | |
//progress bar | |
loadingBar.setTitle("Log In"); | |
loadingBar.setMessage("please wait..."); | |
loadingBar.show(); | |
loadingBar.setCanceledOnTouchOutside(true); | |
mAuth.signInWithEmailAndPassword(email,password) | |
.addOnCompleteListener(new OnCompleteListener<AuthResult>() { | |
@Override | |
public void onComplete(@NonNull Task<AuthResult> task) { | |
if (task.isSuccessful()){ | |
SendUserToMainActivity(); | |
Toast.makeText(Login.this, "You are logged in successful", Toast.LENGTH_SHORT).show(); | |
loadingBar.dismiss(); | |
} | |
else | |
{ | |
String message = task.getException().getMessage(); | |
Toast.makeText(Login.this, "error occurred" +message, Toast.LENGTH_SHORT).show(); | |
loadingBar.dismiss(); | |
} | |
} | |
}); | |
} | |
} | |
private void SendUserToMainActivity() | |
{ | |
Intent mainIntent = new Intent(Login.this,MainActivity.class); | |
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); | |
startActivity(mainIntent); | |
finish(); | |
} | |
//if user has no account will be directed to register | |
public void RegisteActivity(View view) | |
{ | |
Intent registerIntent = new Intent(Login.this,Register.class); | |
startActivity(registerIntent); | |
} | |
} |
Step 5: Step-two Authentication
After successful verification of email and password, a user is directed to step-two authentication. This step will involve providing more information about the user before heading to the home activity of the system. For instance, in our case will do this by allowing the user to provide his/her first name, other names, and his/her phone number.
We will use the shown below method to store data in the Firebase database. It holds two variables. The first one is the name of the field such as the “the heading”. Second is the value stored.
HashMap userMap = new HashMap();
userMap.put("FirstName",firstname);
userMap.put("OtherName",othernames);
userMap.put("Phone",phonenumber);
<?xml version="1.0" encoding="utf-8"?> | |
<ScrollView | |
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" | |
tools:context=".StepTwoAuthentication"> | |
<com.google.android.material.card.MaterialCardView | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_margin="20dp" | |
android:layout_centerInParent="true" | |
app:cardElevation="5dp" | |
android:background="@drawable/button" | |
app:cardCornerRadius="8dp"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:orientation="vertical"> | |
<RelativeLayout | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginStart="5dp" | |
android:layout_marginLeft="5dp" | |
android:layout_marginTop="2dp"> | |
<TextView | |
android:id="@+id/title" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerVertical="true" | |
android:layout_marginStart="24dp" | |
android:layout_marginLeft="8dp" | |
android:text="Two Step Authentication" | |
android:textAlignment="center" | |
android:textColor="@color/colorRed" | |
android:textSize="24sp" | |
android:textStyle="bold" /> | |
<View | |
android:layout_width="match_parent" | |
android:layout_height="2dp" | |
android:layout_below="@id/logo" | |
android:layout_marginLeft="8dp" | |
android:layout_marginRight="24dp" | |
android:layout_marginTop="-20dp" | |
android:background="@color/colorPrimaryDark" | |
android:layout_marginStart="8dp" | |
android:layout_marginEnd="24dp" /> | |
<de.hdodenhof.circleimageview.CircleImageView | |
android:id="@+id/logo" | |
android:elevation="5dp" | |
android:layout_width="100dp" | |
android:layout_height="100dp" | |
android:layout_centerVertical="true" | |
android:layout_gravity="center" | |
android:layout_marginLeft="20dp" | |
android:layout_marginTop="60dp" | |
android:layout_toEndOf="@+id/title" | |
android:layout_toRightOf="@+id/title" | |
android:src="@mipmap/ic_launcher" /> | |
</RelativeLayout> | |
<TextView | |
android:id="@+id/personalInformation" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="Step two Setup Information" | |
android:textColor="@color/colorRed" | |
android:textAlignment="center" | |
android:layout_gravity="center" | |
android:textSize="20sp" | |
android:textStyle="italic"/> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="First Name" | |
android:textSize="18sp" | |
android:layout_marginLeft="10dp" | |
/> | |
<EditText | |
android:id="@+id/editfirstname" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:hint="Enter your name" | |
android:background="@drawable/input_field" | |
android:padding="15dp" | |
android:inputType="textPersonName" | |
android:layout_margin="10dp"/> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="Other names" | |
android:textSize="18sp" | |
android:layout_marginLeft="10dp" | |
/> | |
<EditText | |
android:id="@+id/editothernames" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:hint="Enter your other names" | |
android:inputType="textPersonName" | |
android:background="@drawable/input_field" | |
android:padding="15dp" | |
android:layout_margin="10dp"/> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="Phone Number" | |
android:textSize="18sp" | |
android:layout_marginLeft="10dp" | |
/> | |
<EditText | |
android:id="@+id/editphonenumber" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:hint="+254" | |
android:background="@drawable/input_field" | |
android:padding="15dp" | |
android:inputType="number" | |
android:layout_margin="10dp"/> | |
<Button | |
android:id="@+id/save_button" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginBottom="5dp" | |
android:layout_marginLeft="15dp" | |
android:layout_marginRight="15dp" | |
android:background="@drawable/input" | |
android:padding="10dp" | |
android:textSize="18dp" | |
android:textAllCaps="false" | |
android:layout_marginTop="24dp" | |
android:layout_gravity="center" | |
android:textColor="@android:color/white" | |
android:text="Save" | |
/> | |
</LinearLayout> | |
</com.google.android.material.card.MaterialCardView> | |
</ScrollView> |
package com.example.twostepauthentication; | |
import androidx.annotation.NonNull; | |
import androidx.appcompat.app.AppCompatActivity; | |
import android.app.ProgressDialog; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.text.TextUtils; | |
import android.view.View; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.Toast; | |
import com.google.android.gms.tasks.OnCompleteListener; | |
import com.google.android.gms.tasks.Task; | |
import com.google.firebase.auth.FirebaseAuth; | |
import com.google.firebase.database.DatabaseReference; | |
import com.google.firebase.database.FirebaseDatabase; | |
import java.util.HashMap; | |
public class StepTwoAuthentication extends AppCompatActivity { | |
private EditText edit_firstname, edit_othernames,edit_phonenumber; | |
private Button save; | |
private FirebaseAuth mAuth; | |
private DatabaseReference userRef; | |
private ProgressDialog loadingBar; | |
String currentUserID; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_step_two_authentication); | |
mAuth = FirebaseAuth.getInstance(); | |
currentUserID = mAuth.getCurrentUser().getUid(); | |
userRef = FirebaseDatabase.getInstance().getReference().child("Users").child(currentUserID); | |
edit_firstname = findViewById(R.id.editfirstname); | |
edit_othernames = findViewById(R.id.editothernames); | |
edit_phonenumber = findViewById(R.id.editphonenumber); | |
save = findViewById(R.id.save_button); | |
loadingBar = new ProgressDialog(this); | |
save.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
SaveInformation(); | |
} | |
}); | |
} | |
private void SaveInformation() | |
{ | |
String firstname = edit_firstname.getText().toString().trim(); | |
String othernames = edit_othernames.getText().toString().trim(); | |
String phonenumber = edit_phonenumber.getText().toString().trim(); | |
if (TextUtils.isEmpty(firstname)) | |
{ | |
Toast.makeText(this, "plese write your first name", Toast.LENGTH_SHORT).show(); | |
} | |
if (TextUtils.isEmpty(othernames)) | |
{ | |
Toast.makeText(this, "plese write your other name", Toast.LENGTH_SHORT).show(); | |
} | |
if (TextUtils.isEmpty(phonenumber)) | |
{ | |
Toast.makeText(this, "plese write your phone number", Toast.LENGTH_SHORT).show(); | |
} | |
else { | |
loadingBar.setTitle("Saving Information"); | |
loadingBar.setMessage("please wait..."); | |
loadingBar.show(); | |
loadingBar.setCanceledOnTouchOutside(true); | |
//saving information on the databse | |
HashMap userMap = new HashMap(); | |
userMap.put("FirstName",firstname); | |
userMap.put("OtherName",othernames); | |
userMap.put("Phone",phonenumber); | |
//store | |
userRef.updateChildren(userMap).addOnCompleteListener(new OnCompleteListener() { | |
@Override | |
public void onComplete(@NonNull Task task) { | |
if (task.isSuccessful()){ | |
SendUserToMainActivity(); | |
Toast.makeText(StepTwoAuthentication.this, "Your account is created successfully", Toast.LENGTH_LONG).show(); | |
loadingBar.dismiss(); | |
} | |
else { | |
String message = task.getException().getMessage(); | |
Toast.makeText(StepTwoAuthentication.this, "error corred" + message, Toast.LENGTH_SHORT).show(); | |
loadingBar.dismiss(); | |
} | |
} | |
}); | |
} | |
} | |
private void SendUserToMainActivity() | |
{ | |
Intent mainIntent = new Intent(StepTwoAuthentication.this,MainActivity.class); | |
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); | |
startActivity(mainIntent); | |
finish(); | |
} | |
} |
Step 6: Home Activity Authentication
Here we have to check the User Existence in the Firebase database. For instance, if the user provides both email and password in the first step authentication. Additional information in the second step authentication, he accesses the home activity. Otherwise, access is denied.
To check user existence in the Firebase database. We are going to use “DataSnapshot”. DataSnapshot is used to fetch data from the node whenever a listener event is triggered by the database. In this case, we will use it to check if the user exists in the database.
Since the first method of authentication, email, and password are not stored in the Firebase database. Therefore, we get the current user Id and use DataSnapshot to check if he has registered.
If a user exists in the Firebase database, that is he has already registered via email and password and has provided step two authentication information. He is directed to the home page else he is directed to step two authentication.
private void CheckUserExistence()
{
//get the user id
final String currentUserId =mAuth.getCurrentUser().getUid();
userRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
{
if (!dataSnapshot.hasChild(currentUserId)){
//user is authenticated but but his record is not present in real time firebase database
SendUserToStepTwoAuthentication();
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
package com.example.twostepauthentication; | |
import androidx.annotation.NonNull; | |
import androidx.appcompat.app.AppCompatActivity; | |
import androidx.appcompat.widget.Toolbar; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import com.google.firebase.auth.FirebaseAuth; | |
import com.google.firebase.auth.FirebaseUser; | |
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 { | |
//firebase auth to check if user is authenticated. | |
private FirebaseAuth mAuth; | |
private DatabaseReference userRef; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
Toolbar toolbar = findViewById(R.id.main_toolbar); | |
setSupportActionBar(toolbar); | |
getSupportActionBar().setTitle("Home"); | |
mAuth = FirebaseAuth.getInstance(); | |
userRef = FirebaseDatabase.getInstance().getReference().child("Users"); | |
} | |
//onstart method used to check if the user is registered or not | |
@Override | |
protected void onStart() | |
{ | |
super.onStart(); | |
FirebaseUser currentUser = mAuth.getCurrentUser(); | |
if (currentUser ==null){ | |
SendUserToLoginActivity(); | |
} | |
else{ | |
//checking if the user exists in the firebase database | |
CheckUserExistence(); | |
} | |
} | |
private void CheckUserExistence() | |
{ | |
//get the user id | |
final String currentUserId = mAuth.getCurrentUser().getUid(); | |
userRef.addValueEventListener(new ValueEventListener() { | |
@Override | |
public void onDataChange(@NonNull DataSnapshot dataSnapshot) | |
{ | |
if (!dataSnapshot.hasChild(currentUserId)){ | |
//user is authenticated but but his record is not present in real time firebase database | |
SendUserToStepTwoAuthentication(); | |
} | |
} | |
@Override | |
public void onCancelled(@NonNull DatabaseError databaseError) { | |
} | |
}); | |
} | |
private void SendUserToStepTwoAuthentication() | |
{ | |
Intent steptwoIntent = new Intent(MainActivity.this, StepTwoAuthentication.class); | |
steptwoIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); | |
startActivity(steptwoIntent); | |
finish(); | |
} | |
private void SendUserToLoginActivity() | |
{ | |
Intent loginIntent = new Intent(MainActivity.this, Login.class); | |
loginIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); | |
startActivity(loginIntent); | |
finish(); | |
} | |
} |
Explanation of methods.
mAuth = FirebaseAuth.getInstance(); |
mAuth = FirebaseAuth.getInstance();
userRef =FirebaseDatabase.getInstance().getReference().child("Users");
Gets the default Firebase Database instance. In this case it creates an instance once a user registers.
//get reference
//import statement
import com.google.firebase.database.DatabaseReference;
//crating an object of the method
userRef = FirebaseDatabase.getInstance().getReference()
Database Reference for the database root node.
//get current user
FirebaseUser currentUser = mAuth.getCurrentUser();
This method gets the user who have just logged in.
//createUserWithEmailAndPassword
mAuth.createUserWithEmailAndPassword(Email,Password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
//checking if the task is sucessful
if (task.isSuccessful()){
SenduserToSTepTwoAuthentication();
Toast.makeText(Register.this, "You have passed the first step authentication...", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
else{
String message = task.getException().getMessage();
Toast.makeText(Register.this, "error occured" + message, Toast.LENGTH_SHORT).show(); }
loadingBar.dismiss();
}
});
Creates a new user. Uses email and password.
//sign in with email and password
mAuth.signInWithEmailAndPassword(email,password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
SendUserToMainActivity();
Toast.makeText(Login.this, "You are logged in successful", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
else
{
String message = task.getException().getMessage();
Toast.makeText(Login.this, "error occurred" +message, Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
}
});
Allow user to login. Uses email and password.
Intents
We are going to use intents to navigate through project activities. Check more about Implicit Intent and Explicit Intents.
Import statement for intent is as shown below.
import android.content.Intent;
Creating the intent.
Intent mainIntent = new Intent(Register.this,MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(mainIntent);
Adding a Progress bar
Let’s add a progress bar. This is to allow a user to know what’s happening as he waits to login.
Import statement.
import android.app.ProgressDialog;
Initializing and creating an instance
loadingBar =new ProgressDialog(this);
setting the loading bar details and dismissing it.
//progress bar
loadingBar.setTitle("Log In");
loadingBar.setMessage("please wait...");
loadingBar.show();
loadingBar.setCanceledOnTouchOutside(true);
//dismissing progress bar
loadingBar.dismiss();
By this we have completed our two-step authentication signup system with Firebase. Click on the Run button and Run the application on your android phone but you can also install an android emulator on the android studio.
Reflective Analysis
After doing this project, I learned more about how Firebase services. It has very strong services. It can help you create real-time quality apps. It’s very easy to store user sessions.
Future Directions
- Add Phone Number Authentication allowing you to receive a text message to verify your phone number.
- Add email link authentication. To enable the validity of user emails we can allow Firebase to send an email verification link.
Learning Strategies and Tools
There are a lot of learning tools online, I would recommend the following:
- Connect to Firebase | Android Developers
- A crash course on you-tube covering how to make Android App like Amazon & Ali-express
I used the learning tools above. I also used PDF documentations to achieve this. Anytime I faced some bugs, I would use stack overflow to check for solutions. I was able to work with Intents.
Make sure you have an active internet connection since Firebase is an online database.
It took me a total of 12 hours to finish the project and the blog.
Get the complete project from GitHub
Happy Coding!!
Biwot Kiptoo Benard
Moses, Very nice work on the firebase two system authentication article. This is great work.Very simple english and understandable. Explanation of methods makes one understand everything clearly. Had seen two factor authentication in facebook but thanks to you for writing one in firebase also.
This article is also up to date in terms of technology, currently we need real time databases and firebase is one of them Databases that update immediately. The current direction of this project is allowing sending of verification email link addresses to the link provided. Also allowing phone verification by sending a code.
Great Job Moses i like the order in which this code is arranged it gives a better understanding of the project
Alex, thanks and also hope the blog educated you.
Good job done Moses,keep it up, coders are the source of the new technology, with dual respect, keep the pot boiling in coding, u are such a good programmer!!
Thank you,Wachie Rodgers.
An ideological approach
Hi Moses, I tried and followed the step by step guideline of your blog. kindly help me solve this error, have an error in firebase database when i try to register.
Hi Emmanuel this could be as a result of two things.
1. You have not given the internet permission in your manifest file.
2.You have not set the firebase read and write rules to true.
// These rules allow anyone read or write access to your database
{
“rules”: {
“.read”: true,
“.write”: true
}
}
for internet permission.
Kudos bro
Good work sir!! I like how you have explained everything in this project, its easy for me to understand everything. Once again Good Work!!