
Hey guys! In this tutorial, I am covering user verification by phone number by sending OTP to the mobile using Firebase authentication.
You can use Firebase Authentication to enable a user to sign in to your app by sending an SMS to user’s device which contains a one-time-password. The user then enters this OTP in your app, if the OTP matches then sign in is successful and the user can then access your app.
Firebase Authentication
Firebase is a Google product which provides backend services, SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords, phone numbers, popular federated identity providers like Google, Facebook and Twitter, and more.
You may authenticate users of your app either by using Firebase UI which provides a complete user interface for sign in and authentication or you can integrate Firebase SDK manually into your app.
App overview
The “OTP Authentication” app will consist of two Activities MainActivity and SignedIn. MainActivity activity will have two edit texts, one for the phone number and the other for received OTP, Also it will have two buttons, one to generate OTP and other to verify OTP. If the OTP match is successful then it will open SignedIn activity via Intent. If the OTP does not match then it will pop a toast message, “Incorrect OTP”.
SignedIn activity will include a text view displaying number and a sign out button on click of which app sign-outs and go back to MainActivity activity.
Setting up the project
STEP1: SET UP A NEW ANDROID PROJECT
- Start Android Studio and Click on “new project”.
- Give your application a name, mine is “OTP Authentication”.
- click next and choose Target android device.
- next, choose an empty activity to keep things simple.
- next, name your Activity and click finish to build the project.
STEP2: Add Firebase to your app
- Goto Firebase Console
- Login with your Gmail ID
- On the welcome screen of Firebase click on Add project.
Add project window will open, there enter your project name and select your country, Project id will be automatically created and then click on CREATE PROJECT button.
After this, your app’s dashboard will open. click on Add Firebase to your Android app
Now you have to register your app by providing the app package name and SHA-1 signing certificate on below screen.
To find the App package name open AndroidManifest.xml and on the top, there is the package name
To get the SHA-1 signing certificate, click on Gradle tab on the right end of Android studio to open Gradle properties> then click on :app> android> double click on signingReport. In the Monitor pane, you will see SHA1.
- Copy and paste the package name and the SHA1 signing certificate in the firebase console register page. Then, click on REGISTER APP button.
- Now you have to download the google-services.json file from the download config page and paste it in app module.
After than in project pane, click on Gradle Scripts> open project level build.gradle file and add google service dependency in buildscript.
open app level build.gradle add firebase dependency along with firebase authentication dependency.
1 2 3 4 |
implementation 'com.google.firebase:firebase-core:11.8.0' implementation 'com.google.firebase:firebase-auth:11.8.0' note, for android studio below 3.0.1 use compile instead of implementation. |
and add the plugin for google service at the bottom of the file.
1 |
apply plugin: 'com.google.gms.google-services' |
- Click on Sync Now and let the Gradle build.
- Now go back to Firebase console and click on Project Overview. In Discover Firebase section there is a card named Authentication, click on GET STARTED on Authentication card.
On the next page click on SETUP SIGN-IN METHOD and enable phone authentication, then SAVE it. At this point, we are done with the initial setup.
step3: EDIT androidmanifest.XML
Our application needs internet for sending OTP. So, for this reason, we have to, first of all, give permission to our app to use the internet. Add the following line to your AndroidManifest.xml inside manifest tag.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.androindian.fcmotp"> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:usesCleartextTraffic="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".ProfileActivity"></activity> <activity android:name=".VerifyPhoneActivity" /> <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> |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?xml version="1.0" encoding="utf-8"?> <layout 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" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/mobile" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:inputType="phone" android:hint="Mobile"/> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout> </layout> |
MainActivity.Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
package com.androindian.fcmotp; import androidx.appcompat.app.AppCompatActivity; import androidx.databinding.DataBindingUtil; import android.content.Intent; import android.os.Bundle; import android.view.View; import com.androindian.fcmotp.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding= DataBindingUtil.setContentView( MainActivity.this,R.layout.activity_main); binding.button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String mobile = binding.mobile.getText().toString().trim(); if(mobile.isEmpty() || mobile.length() < 10){ binding.mobile.setError("Enter a valid mobile"); binding.mobile.requestFocus(); return; } Intent intent = new Intent(MainActivity.this, VerifyPhoneActivity.class); intent.putExtra("mobile", mobile); startActivity(intent); } }); } } |
VerifyPhoneActivity.Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
package com.androindian.fcmotp; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; 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.android.gms.tasks.TaskExecutors; import com.google.android.material.snackbar.Snackbar; import com.google.firebase.FirebaseException; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException; import com.google.firebase.auth.PhoneAuthCredential; import com.google.firebase.auth.PhoneAuthProvider; import java.util.concurrent.TimeUnit; public class VerifyPhoneActivity extends AppCompatActivity { private String mVerificationId; private EditText editTextCode; private FirebaseAuth mAuth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_verify_phone); //initializing objects mAuth = FirebaseAuth.getInstance(); editTextCode = findViewById(R.id.editTextCode); //getting mobile number from the previous activity //and sending the verification code to the number Intent intent = getIntent(); String mobile = intent.getStringExtra("mobile"); sendVerificationCode(mobile); //if the automatic sms detection did not work, user can also enter the code manually //so adding a click listener to the button findViewById(R.id.buttonSignIn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String code = editTextCode.getText().toString().trim(); if (code.isEmpty() || code.length() < 6) { editTextCode.setError("Enter valid code"); editTextCode.requestFocus(); return; } //verifying the code entered manually verifyVerificationCode(code); } }); } //the method is sending verification code //the country id is concatenated //you can take the country id as user input as well private void sendVerificationCode(String mobile) { PhoneAuthProvider.getInstance().verifyPhoneNumber( "+91" + mobile, 60, TimeUnit.SECONDS, TaskExecutors.MAIN_THREAD, mCallbacks); } //the callback to detect the verification status private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() { @Override public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) { //Getting the code sent by SMS String code = phoneAuthCredential.getSmsCode(); //sometime the code is not detected automatically //in this case the code will be null //so user has to manually enter the code if (code != null) { editTextCode.setText(code); //verifying the code verifyVerificationCode(code); } } @Override public void onVerificationFailed(FirebaseException e) { Toast.makeText(VerifyPhoneActivity.this, e.getMessage(), Toast.LENGTH_LONG).show(); } @Override public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) { super.onCodeSent(s, forceResendingToken); //storing the verification id that is sent to the user mVerificationId = s; } }; private void verifyVerificationCode(String code) { //creating the credential PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, code); //signing the user signInWithPhoneAuthCredential(credential); } private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) { mAuth.signInWithCredential(credential) .addOnCompleteListener(VerifyPhoneActivity.this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { //verification successful we will start the profile activity Intent intent = new Intent(VerifyPhoneActivity.this, ProfileActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); } else { //verification unsuccessful.. display an error message String message = "Somthing is wrong, we will fix it soon..."; if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) { message = "Invalid code entered..."; } Snackbar snackbar = Snackbar.make(findViewById(R.id.parent), message, Snackbar.LENGTH_LONG); snackbar.setAction("Dismiss", new View.OnClickListener() { @Override public void onClick(View v) { } }); snackbar.show(); } } }); } } |
activity_verify_phone.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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=".VerifyPhoneActivity"> <RelativeLayout android:id="@+id/relativeLayout" android:layout_width="match_parent" android:layout_height="200dp" android:background="@color/colorPrimary" android:orientation="horizontal"> <ImageView android:layout_width="120dp" android:layout_height="120dp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:background="@mipmap/ic_launcher" /> </RelativeLayout> <ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="120dp" android:layout_below="@id/relativeLayout" android:layout_marginTop="-50dp" android:background="@mipmap/ic_launcher" /> <RelativeLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/imageView" android:orientation="vertical" android:padding="20dp"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="25dp" android:text="Wait for the code I sent You" android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline" android:textColor="@color/colorPrimary" /> <ProgressBar android:id="@+id/progressbar" android:layout_below="@id/textView" android:layout_centerHorizontal="true" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/editTextCode" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_below="@id/progressbar" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:digits="0123456789" android:drawablePadding="10dp" android:hint="enter verification code" android:inputType="phone" android:maxLength="10" /> <Button android:id="@+id/buttonSignIn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/editTextCode" android:layout_centerHorizontal="true" android:layout_marginTop="15dp" android:background="@color/colorPrimaryDark" android:text="Sign In" android:textAllCaps="false" android:textColor="#cdd8f1" /> </RelativeLayout> </RelativeLayout> |
ProfileActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.androindian.fcmotp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; public class ProfileActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); } } |
activity_profile.xml
1 2 3 4 5 6 7 8 9 |
<?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=".ProfileActivity"> </androidx.constraintlayout.widget.ConstraintLayout> |
Output