Kotlin Firebase Authentication – Send Reset Password Email / Forgot Password | Android

In previous post, we have known way to implement Sign up, Sign in/out, Verify Email. Today, we continue to take a look at way to send Reset Password Email in case User forgot Password.

*Note: This tutorial bases on code in related post:
Kotlin Firebase Authentication – How to Sign Up, Sign In, Sign Out, Verify Email | Android

We just add an Activity to App for handling Reset Password Email and some statements to old code for logic.

I. Way to do

1. Add Firebase Auth to Android App

Read Kotlin Firebase Authentication – How to Sign Up, Sign In, Sign Out, Verify Email | Android and follow steps to enable and implement Firebase Auth in your Android App.

2. Send a password reset email

Use sendPasswordResetEmail() method:


private var mAuth: FirebaseAuth? = null
//...
mAuth = FirebaseAuth.getInstance()

mAuth!!.sendPasswordResetEmail(email)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                // successful!
            } else {
                // failed!
            }
        }

We can customize the email template in Firebase console:
firebase-auth-email-password-mail-template-reset

II. Practice

1. Goal

We will build an Android App that can:
– create Account, sign in/sign out, send email verification.
– display current status/user information with verified email status.
(all things above are from previous tutorial)
– send reset password email in case user forgot password.

kotlin-email-reset-password-goal-2-screen

2. Technology

– Gradle 3.0.1
– Android Studio 3.x
– Firebase Android SDK 11.x

3. Project Structure

kotlin-email-reset-password-structure

4. Step by step

4.1 Create Android Project

– Generate new Android Project with package com.javasampleapproach.kotlin.firebase.auth.
– Follow these steps to add Firebase to Android Project.
– Don’t forget to enable Firebase Auth:
firebaseauth-enable-email

4.2 LoginActivity

<?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/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="3">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:gravity="center"
            android:text="grokonez.com"
            android:textSize="28sp" />

        <TextView
            android:id="@+id/tvStatus"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="4dp"
            android:text="Signed Out"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/tvDetail"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="4dp"
            android:textSize="14sp"
            tools:text="Firebase User ID: 123456789abc" />

    </LinearLayout>


    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#E0E0E0"
        android:gravity="center_vertical">

        <LinearLayout
            android:id="@+id/email_password_fields"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="16dp"
            android:paddingRight="16dp">

            <EditText
                android:id="@+id/edtEmail"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="Email"
                android:inputType="textEmailAddress" />

            <EditText
                android:id="@+id/edtPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="Password"
                android:inputType="textPassword" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/email_password_buttons"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/email_password_fields"
            android:orientation="horizontal"
            android:paddingLeft="16dp"
            android:paddingRight="16dp">

            <Button
                android:id="@+id/btn_email_sign_in"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="4dp"
                android:layout_marginRight="4dp"
                android:layout_weight="1"
                android:text="Sign In" />

            <Button
                android:id="@+id/btn_email_create_account"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="4dp"
                android:layout_marginRight="4dp"
                android:layout_weight="1"
                android:text="Create Account" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_forgot_password"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/email_password_buttons"
            android:orientation="horizontal"
            android:paddingLeft="16dp"
            android:paddingRight="16dp">

            <Button
                android:id="@+id/btn_forgot_password"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:text="Forgot your password?"
                android:textAllCaps="false"
                android:textColor="@android:color/holo_blue_dark" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_signed_in_buttons"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:orientation="horizontal"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:visibility="gone"
            android:weightSum="2.0">

            <Button
                android:id="@+id/btn_sign_out"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="4dp"
                android:layout_marginRight="4dp"
                android:layout_weight="1.0"
                android:text="Sign Out" />

            <Button
                android:id="@+id/btn_verify_email"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="4dp"
                android:layout_marginRight="4dp"
                android:layout_weight="1.0"
                android:text="Verify Email" />

        </LinearLayout>

    </RelativeLayout>

</LinearLayout>

package com.javasampleapproach.kotlin.firebase.auth

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import kotlinx.android.synthetic.main.activity_login.*
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import android.widget.Toast
import android.util.Log
import android.text.TextUtils

class LoginActivity : AppCompatActivity(), View.OnClickListener {

    private val TAG = "FirebaseEmailPassword"

    private var mAuth: FirebaseAuth? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        btn_email_sign_in.setOnClickListener(this)
        btn_email_create_account.setOnClickListener(this)
        btn_sign_out.setOnClickListener(this)
        btn_verify_email.setOnClickListener(this)
        btn_forgot_password.setOnClickListener(this)

        mAuth = FirebaseAuth.getInstance()
    }

    override fun onStart() {
        super.onStart()

        val currentUser = mAuth!!.currentUser
        updateUI(currentUser)
    }

    override fun onClick(view: View?) {
        val i = view!!.id

        if (i == R.id.btn_email_create_account) {
            createAccount(edtEmail.text.toString(), edtPassword.text.toString())
        } else if (i == R.id.btn_email_sign_in) {
            signIn(edtEmail.text.toString(), edtPassword.text.toString())
        } else if (i == R.id.btn_sign_out) {
            signOut()
        } else if (i == R.id.btn_verify_email) {
            sendEmailVerification()
        } else if (i == R.id.btn_forgot_password) {
            startActivity(Intent(applicationContext, ResetPasswordActivity::class.java))
        }
    }

    private fun createAccount(email: String, password: String) {
        Log.e(TAG, "createAccount:" + email)
        if (!validateForm(email, password)) {
            return
        }

        mAuth!!.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(this) { task ->
                    if (task.isSuccessful) {
                        Log.e(TAG, "createAccount: Success!")

                        // update UI with the signed-in user's information
                        val user = mAuth!!.currentUser
                        updateUI(user)
                    } else {
                        Log.e(TAG, "createAccount: Fail!", task.exception)
                        Toast.makeText(applicationContext, "Authentication failed!", Toast.LENGTH_SHORT).show()
                        updateUI(null)
                    }
                }
    }

    private fun signIn(email: String, password: String) {
        Log.e(TAG, "signIn:" + email)
        if (!validateForm(email, password)) {
            return
        }

        mAuth!!.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(this) { task ->
                    if (task.isSuccessful) {
                        Log.e(TAG, "signIn: Success!")

                        // update UI with the signed-in user's information
                        val user = mAuth!!.getCurrentUser()
                        updateUI(user)
                    } else {
                        Log.e(TAG, "signIn: Fail!", task.exception)
                        Toast.makeText(applicationContext, "Authentication failed!", Toast.LENGTH_SHORT).show()
                        updateUI(null)
                    }

                    if (!task.isSuccessful) {
                        tvStatus.text = "Authentication failed!"
                    }
                }
    }

    private fun signOut() {
        mAuth!!.signOut()
        updateUI(null)
    }

    private fun sendEmailVerification() {
        // Disable Verify Email button
        findViewById(R.id.btn_verify_email).isEnabled = false

        val user = mAuth!!.currentUser
        user!!.sendEmailVerification()
                .addOnCompleteListener(this) { task ->
                    // Re-enable Verify Email button
                    findViewById(R.id.btn_verify_email).isEnabled = true

                    if (task.isSuccessful) {
                        Toast.makeText(applicationContext, "Verification email sent to " + user.email!!, Toast.LENGTH_SHORT).show()
                    } else {
                        Log.e(TAG, "sendEmailVerification failed!", task.exception)
                        Toast.makeText(applicationContext, "Failed to send verification email.", Toast.LENGTH_SHORT).show()
                    }
                }
    }

    private fun validateForm(email: String, password: String): Boolean {

        if (TextUtils.isEmpty(email)) {
            Toast.makeText(applicationContext, "Enter email address!", Toast.LENGTH_SHORT).show()
            return false
        }

        if (TextUtils.isEmpty(password)) {
            Toast.makeText(applicationContext, "Enter password!", Toast.LENGTH_SHORT).show()
            return false
        }

        if (password.length < 6) {
            Toast.makeText(applicationContext, "Password too short, enter minimum 6 characters!", Toast.LENGTH_SHORT).show()
            return false
        }

        return true
    }

    private fun updateUI(user: FirebaseUser?) {

        if (user != null) {
            tvStatus.text = "User Email: " + user.email + "(verified: " + user.isEmailVerified + ")"
            tvDetail.text = "Firebase User ID: " + user.uid

            email_password_buttons.visibility = View.GONE
            email_password_fields.visibility = View.GONE
            layout_signed_in_buttons.visibility = View.VISIBLE

            btn_verify_email.isEnabled = !user.isEmailVerified

            layout_forgot_password.visibility = View.GONE
        } else {
            tvStatus.text = "Signed Out"
            tvDetail.text = null

            email_password_buttons.visibility = View.VISIBLE
            email_password_fields.visibility = View.VISIBLE
            layout_signed_in_buttons.visibility = View.GONE

            layout_forgot_password.visibility = View.VISIBLE
        }
    }
}

4.3 ResetPasswordActivity

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/reset_password_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingLeft="16dp"
    android:paddingRight="16dp">

    <TextView
        android:id="@+id/title_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:gravity="center"
        android:text="grokonez.com"
        android:textSize="24sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:padding="10dp"
        android:text="Forgot your password?"
        android:textSize="20dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:gravity="center_horizontal"
        android:padding="10dp"
        android:text="To reset password, enter your email, press the button and check mail to follow instruction."
        android:textSize="14dp" />

    <EditText
        android:id="@+id/edtResetEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginRight="20dp"
        android:layout_marginLeft="20dp"
        android:hint="Your email here"
        android:inputType="textEmailAddress" />

    <Button
        android:id="@+id/btnResetPassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Reset Password" />

    <Button
        android:id="@+id/btnBack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@null"
        android:text="BACK"
        android:textColor="@android:color/holo_blue_dark" />

</LinearLayout>

package com.javasampleapproach.kotlin.firebase.auth

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_reset_password.*
import com.google.firebase.auth.FirebaseAuth
import android.widget.Toast
import android.text.TextUtils


class ResetPasswordActivity : AppCompatActivity() {

    private var mAuth: FirebaseAuth? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_reset_password)

        mAuth = FirebaseAuth.getInstance()

        btnResetPassword.setOnClickListener {
            val email = edtResetEmail.text.toString().trim()

            if (TextUtils.isEmpty(email)) {
                Toast.makeText(applicationContext, "Enter your email!", Toast.LENGTH_SHORT).show()
            } else {
                mAuth!!.sendPasswordResetEmail(email)
                        .addOnCompleteListener { task ->
                            if (task.isSuccessful) {
                                Toast.makeText(this@ResetPasswordActivity, "Check email to reset your password!", Toast.LENGTH_SHORT).show()
                            } else {
                                Toast.makeText(this@ResetPasswordActivity, "Fail to send reset password email!", Toast.LENGTH_SHORT).show()
                            }
                        }
            }
        }

        btnBack.setOnClickListener {
            finish()
        }
    }
}

4.4 Set main launcher & new activity

Open AndroidManifest.xml:
- make the LoginActivity.java as launcher activity (set it as the first screen).
- add ResetPasswordActivity as activity.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.javasampleapproach.kotlin.firebase.auth">

    <application ...">
        <activity android:name=".LoginActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ResetPasswordActivity"
            android:label="Reset Password Activity"></activity>
    </application>

</manifest>

4.5 Run & Check result

- Use Android Studio, build and Run your Android App.

- Click on Forgot your password?, then fill in Email and click on RESET PASSWORD button:
kotlin-email-reset-password-goal-2

- Check your email:
kotlin-email-reset-password-email-result

- Follow instruction, click on the link inside, the browser shows a dialog, enter your new password:
firebase-auth-email-password-reset-mail-result-web-1

- The result:
firebase-auth-email-password-reset-mail-result-web-2

III. Source code

Kotlin-FirebaseAuth-reset-password-email



By grokonez | December 15, 2017.

Last updated on April 24, 2021.



Related Posts


1 thought on “Kotlin Firebase Authentication – Send Reset Password Email / Forgot Password | Android”

Got Something To Say:

Your email address will not be published. Required fields are marked *

*