Phone Number Verification using Firebase in Android
Phone number Firebase Authentication is used to sign in a user by sending an SMS message to the user’s phone. The user signs in using a one-time code contained in the SMS message. A sample video is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Kotlin language.
Note: To implement this in Java language refer to this article Firebase Authentication with Phone Number OTP in Android
Step by Step Implementation
Step 1: Create a new project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.
Step 2: Connect Project to Firebase.
Step 3: Add dependency to the build.gradle file and click “sync now”
implementation platform(‘com.google.firebase:firebase-bom:26.5.0’)
implementation ‘com.google.firebase:firebase-auth-ktx’
Step 4: Create two new activities.
Create two new activities. One PhoneNumberActivity.kt with the layout file activity_phone_number.xml for entering the phone number and starting the authentication process. Second OtpActivity.kt with the layout file activity_otp.xml for entering OTP received from firebase.
Step 5: Working with layout
Working with activity_phone_number.xml. Go to the activity_phone_number.xml file and write the following code.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < androidx.constraintlayout.widget.ConstraintLayout android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".PhoneNumberActivity" > <!--This will be used to enter the phone number--> < EditText android:id = "@+id/et_phone_number" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_marginStart = "20dp" android:layout_marginTop = "200dp" android:layout_marginEnd = "20dp" android:layout_marginBottom = "20dp" android:ems = "10" android:hint = "Enter Phone Number" android:inputType = "phone" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toTopOf = "parent" tools:layout_editor_absoluteY = "85dp" /> <!--On click of this button OTP will be send to phone--> < Button android:id = "@+id/button_otp" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "20dp" android:text = "Send OTP" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/et_phone_number" /> </ androidx.constraintlayout.widget.ConstraintLayout > |
Working with activity_otp.xml. Go to the activity_otp.xml file and write the following code.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < androidx.constraintlayout.widget.ConstraintLayout android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".OtpActivity" > < TextView android:id = "@+id/tv_otp" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "200dp" android:text = "Enter OTP" android:textSize = "20sp" app:layout_constraintLeft_toLeftOf = "parent" app:layout_constraintRight_toRightOf = "parent" app:layout_constraintTop_toTopOf = "parent" /> <!--We will use it to enter OTP after we receive OTP--> < EditText android:id = "@+id/et_otp" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_margin = "20dp" android:hint = "Enter OTP" app:layout_constraintLeft_toLeftOf = "parent" app:layout_constraintRight_toRightOf = "parent" app:layout_constraintTop_toBottomOf = "@id/tv_otp" /> <!--On click of this button final authentication will start--> < Button android:id = "@+id/login" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "Login" app:layout_constraintLeft_toLeftOf = "parent" app:layout_constraintRight_toRightOf = "parent" app:layout_constraintTop_toBottomOf = "@id/et_otp" /> </ androidx.constraintlayout.widget.ConstraintLayout > |
Working with activity_main.xml. Go to the activity_main.xml file and write the following code. This is the final activity where we reach after verification is completed.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < androidx.constraintlayout.widget.ConstraintLayout android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".MainActivity" > < TextView android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "Welcome To GFG!!" android:textSize = "22sp" android:textColor = "@color/black" app:layout_constraintBottom_toBottomOf = "parent" app:layout_constraintLeft_toLeftOf = "parent" app:layout_constraintRight_toRightOf = "parent" app:layout_constraintTop_toTopOf = "parent" /> </ androidx.constraintlayout.widget.ConstraintLayout > |
Step 6: Working with the PhoneNumberActivity.kt file
Go to the PhoneNumberActivity.kt file and refer to the following code. Below is the code for the PhoneNumberActivity.kt file. Comments are added inside the code to understand the code in more detail.
Kotlin
import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.widget.Button import android.widget.EditText import android.widget.Toast import com.google.firebase.FirebaseException import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.PhoneAuthCredential import com.google.firebase.auth.PhoneAuthOptions import com.google.firebase.auth.PhoneAuthProvider import java.util.concurrent.TimeUnit class PhoneNumberActivity : AppCompatActivity() { // this stores the phone number of the user var number : String = "" // create instance of firebase auth lateinit var auth: FirebaseAuth // we will use this to match the sent otp from firebase lateinit var storedVerificationId:String lateinit var resendToken: PhoneAuthProvider.ForceResendingToken private lateinit var callbacks: PhoneAuthProvider.OnVerificationStateChangedCallbacks override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_phone_number) auth=FirebaseAuth.getInstance() // start verification on click of the button findViewById<Button>(R.id.button_otp).setOnClickListener { login() } // Callback function for Phone Auth callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() { // This method is called when the verification is completed override fun onVerificationCompleted(credential: PhoneAuthCredential) { startActivity(Intent(applicationContext, MainActivity:: class .java)) finish() Log.d( "GFG" , "onVerificationCompleted Success" ) } // Called when verification is failed add log statement to see the exception override fun onVerificationFailed(e: FirebaseException) { Log.d( "GFG" , "onVerificationFailed $e" ) } // On code is sent by the firebase this method is called // in here we start a new activity where user can enter the OTP override fun onCodeSent( verificationId: String, token: PhoneAuthProvider.ForceResendingToken ) { Log.d( "GFG" , "onCodeSent: $verificationId" ) storedVerificationId = verificationId resendToken = token // Start a new activity using intent // also send the storedVerificationId using intent // we will use this id to send the otp back to firebase val intent = Intent(applicationContext,OtpActivity:: class .java) intent.putExtra( "storedVerificationId" ,storedVerificationId) startActivity(intent) finish() } } } private fun login() { number = findViewById<EditText>(R.id.et_phone_number).text.trim().toString() // get the phone number from edit text and append the country cde with it if (number.isNotEmpty()){ number = "+91$number" sendVerificationCode(number) } else { Toast.makeText( this , "Enter mobile number" , Toast.LENGTH_SHORT).show() } } // this method sends the verification code // and starts the callback of verification // which is implemented above in onCreate private fun sendVerificationCode(number: String) { val options = PhoneAuthOptions.newBuilder(auth) .setPhoneNumber(number) // Phone number to verify .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit .setActivity( this ) // Activity (for callback binding) .setCallbacks(callbacks) // OnVerificationStateChangedCallbacks .build() PhoneAuthProvider.verifyPhoneNumber(options) Log.d( "GFG" , "Auth started" ) } } |
Step 7: Working with the OtpActivity.kt file
Go to the OtpActivity.kt file and refer to the following code. Below is the code for the OtpActivity.kt file. Comments are added inside the code to understand the code in more detail.
Kotlin
import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.EditText import android.widget.Toast import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException import com.google.firebase.auth.PhoneAuthCredential import com.google.firebase.auth.PhoneAuthProvider class OtpActivity : AppCompatActivity() { // get reference of the firebase auth lateinit var auth: FirebaseAuth override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_otp) auth=FirebaseAuth.getInstance() // get storedVerificationId from the intent val storedVerificationId= intent.getStringExtra( "storedVerificationId" ) // fill otp and call the on click on button findViewById<Button>(R.id.login).setOnClickListener { val otp = findViewById<EditText>(R.id.et_otp).text.trim().toString() if (otp.isNotEmpty()){ val credential : PhoneAuthCredential = PhoneAuthProvider.getCredential( storedVerificationId.toString(), otp) signInWithPhoneAuthCredential(credential) } else { Toast.makeText( this , "Enter OTP" , Toast.LENGTH_SHORT).show() } } } // verifies if the code matches sent by firebase // if success start the new activity in our case it is main Activity private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) { auth.signInWithCredential(credential) .addOnCompleteListener( this ) { task -> if (task.isSuccessful) { val intent = Intent( this , MainActivity:: class .java) startActivity(intent) finish() } else { // Sign in failed, display a message and update the UI if (task.exception is FirebaseAuthInvalidCredentialsException) { // The verification code entered was invalid Toast.makeText( this , "Invalid OTP" , Toast.LENGTH_SHORT).show() } } } } } |
Step 8: Go to AndroidManifest.xml and add the following code
XML
<? xml version = "1.0" encoding = "utf-8" ?> package = "com.geeksforgeeks.phoneauth" > < uses-permission android:name = "android.permission.INTERNET" /> < 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.PhoneAuth" > < activity android:name = ".OtpActivity" ></ activity > < activity android:name = ".PhoneNumberActivity" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > < activity android:name = ".MainActivity" > </ activity > </ application > </ manifest > |
Step 9: Enable the Android DeviceCheck API for your project
In the Google Cloud Console, enable the Android DeviceCheck API for your project. The default Firebase API Key will be used and needs to be allowed to access the DeviceCheck API.
Step 10: Add SHA keys from Android Studio to Firebase
Copy SHA1 and SHA-256 keys from your project and paste them to the firebase console. Below is the screenshot to guide you.
Note: Please refer to this article How to Generate SHA1, MD5, and SHA-256 Keys in Android Studio?
On the Firebase console go to Project Overview -> Project Setting, and click add fingerprint button, and add your SHA keys copied from firebase
Step 11: Enable Phone Number sign-in for your Firebase project
In the Firebase console choose your project, open the Authentication section. On the Sign-in Method page, enable the Phone Number sign-in method.
Output:
Github repo here.
Please Login to comment...