Firebase Authentication - 4 - Reset password

Index

  1. Firebase setup
  2. Layout
  3. Register and Login
  4. Reset password
  5. Verify email
  6. Change profile picture
  7. Change display name
  8. Change email
  9. Change password
  10. Delete account

 

Welcome to the fourth part of the Firebase Authentication series. In the previous part I showed you how to register users and let them log in and log out. In this part we will make it possible for users to reset their password. When a user clicks on the TextView in the login fragment that says "Forgot your password? Click here to reset it", a popup will show up with an EditText where the user will be able to input his or her email. It will look something like this:

The AlertDialog will inflate a view that only consists of one element, an EditText. Create a new xml file in res/layout and name it dialog_reset_password.xml. Fill it with the code below.

 

dialog_reset_password.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <EditText
        android:id="@+id/email_txt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Email..."
        android:inputType="textEmailAddress"
        android:layout_marginTop="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:layout_marginBottom="5dp"/>

</LinearLayout>

 

Now create a new Java file in the DialogFragments folder and name it ResetPasswordDialog.java.

 

ResetPasswordDialog.java

package com.frogitecture.authenticatedgoose.DialogFragments;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;

import com.frogitecture.authenticatedgoose.R;

import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;

public class ResetPasswordDialog extends DialogFragment {

    public interface ResetPasswordListener {
        void onResetPassword(String email);
    }

    public ResetPasswordListener listener;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        LayoutInflater inflater = requireActivity().getLayoutInflater();

        View view = inflater.inflate(R.layout.dialog_reset_password, null);
        final EditText emailTxt = view.findViewById(R.id.email_txt);

        builder.setView(view)
                .setTitle("Send Reset Password Email")
                .setPositiveButton("Send", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        String email = emailTxt.getText().toString();
                        listener.onResetPassword(email);
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {}
                });
        return builder.create();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        try {
            listener = (ResetPasswordListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(getActivity().toString() + " must implement the listener you silly goose");
        }
    }
}

If you're not familiar with AlertDialog you can read more about it here. This class have a public interface ResetPasswordListener with the method onResetPassword(String email) which is called when the user click on the send button. The argument email will be the text from the EditText we just created. Notice that the onClick method connected to the cancel button is empty. This is because when cancel is clicked, the popup is automatically dismissed. It's ime to open up LoginFragment.

 

LoginFragment.java

package com.frogitecture.authenticatedgoose.Fragments;

import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.frogitecture.authenticatedgoose.AuthActivity;
import com.frogitecture.authenticatedgoose.DialogFragments.LoadingDialog;
import com.frogitecture.authenticatedgoose.DialogFragments.ResetPasswordDialog;
import com.frogitecture.authenticatedgoose.MainActivity;
import com.frogitecture.authenticatedgoose.R;
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 androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class LoginFragment extends Fragment {

    private LoadingDialog loadingDialog;
    private FirebaseAuth firebaseAuth;

    private TextView emailTxt;
    private TextView passwordTxt;
    private TextView registerTxt;
    private Button signInBtn;

    // Add this line
    private TextView forgotPasswordTxt;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View parentView = inflater.inflate(R.layout.fragment_login, container, false);

        loadingDialog = new LoadingDialog();
        firebaseAuth = FirebaseAuth.getInstance();

        emailTxt = parentView.findViewById(R.id.email_txt);
        passwordTxt = parentView.findViewById(R.id.password_txt);
        registerTxt = parentView.findViewById(R.id.not_registered_txt);
        signInBtn = parentView.findViewById(R.id.login_btn);

        // And this line
        forgotPasswordTxt = parentView.findViewById(R.id.forgot_password_txt);

        registerTxt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((AuthActivity)getActivity()).changeFragment(new RegisterFragment());
            }
        });

        signInBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String email = emailTxt.getText().toString();
                String password = passwordTxt.getText().toString();
                signIn(email, password);
                loadingDialog.setMessage("Signing in...");
                loadingDialog.show(getActivity().getSupportFragmentManager(),"Signing In");
            }
        });

        // And these lines
        forgotPasswordTxt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ResetPasswordDialog resetPasswordDialog = new ResetPasswordDialog();
                resetPasswordDialog.show(getActivity().getSupportFragmentManager(),"Change Display Name");
            }
        });

        return parentView;
    }

    private void signIn(String email, String password) {
        firebaseAuth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            getActivity().finish();
                            startActivity(new Intent(getActivity(), MainActivity.class));
                        } else {
                            Toast.makeText(getActivity(), "Authentication failed.", Toast.LENGTH_SHORT).show();
                        }
                        loadingDialog.dismiss();
                    }
                });
    }
}

A variable is added for for the reset password TextView:

private TextView forgotPasswordTxt;

We connect it to the xml element in onCreateView:

forgotPasswordTxt = parentView.findViewById(R.id.forgot_password_txt);

Then we add a click listener to that TextView. When it is clicked, the popup is created and displayed:

forgotPasswordTxt.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ResetPasswordDialog resetPasswordDialog = new ResetPasswordDialog();
        resetPasswordDialog.show(getActivity().getSupportFragmentManager(),"Change Display Name");
    }
});

That is all for the LoginFragment. Since this is a fragment, ResetPasswordListener needs to be implemented in the base class, AuthActivity.

 

AuthActivity.java

package com.frogitecture.authenticatedgoose;

import android.os.Bundle;
import android.widget.Toast;

import com.frogitecture.authenticatedgoose.DialogFragments.ResetPasswordDialog;
import com.frogitecture.authenticatedgoose.Fragments.LoginFragment;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;

// Implement ResetPasswordListener
public class AuthActivity extends AppCompatActivity implements ResetPasswordDialog.ResetPasswordListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auth);

        if (savedInstanceState != null) {
            return;
        }

        LoginFragment loginFragment = new LoginFragment();
        getSupportFragmentManager().beginTransaction().add(R.id.container, loginFragment).commit();

    }

    public void changeFragment(Fragment fragment) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.container, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }

    // Implement the listeners method onResetPassword
    @Override
    public void onResetPassword(String email) {
        FirebaseAuth auth = FirebaseAuth.getInstance();

        auth.sendPasswordResetEmail(email)
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        if (task.isSuccessful()) {
                            Toast.makeText(AuthActivity.this, "Email sent! Check your inbox", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }
}

ResetPasswordListener is implemented:

public class AuthActivity extends AppCompatActivity implements ResetPasswordDialog.ResetPasswordListener

And the listeners method onResetPassword(String email) is implemented:

@Override
public void onResetPassword(String email) {
    FirebaseAuth auth = FirebaseAuth.getInstance();

    auth.sendPasswordResetEmail(email)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Toast.makeText(AuthActivity.this, "Email sent! Check your inbox", Toast.LENGTH_SHORT).show();
                    }
                }
            });
}

In this method, an instance of FirebaseAuth is created, then we use that variable to call sendPasswordResetEmail, along with a complete listener. When an email is sent, we show the users a Toast message to inform them to check their inbox.

In the next part I will show you how to verify an email.

Author

authors profile photo

Articles with similar tags

thumbnail
Firebase Authentication - 7 - Change display name

Changing a display name in Android Studio with firebase auth

By Frogitecture

thumbnail
Firebase Authentication - 8 - Change email

Changing email in Android with Firebase Authentication

By Frogitecture

thumbnail
Firebase Authentication - 9 - Change password

Changing a password in Android with Firebase Authentication

By Frogitecture

thumbnail
Firebase Authentication - 10 - Delete account

Deleting an account in Android with Firebase Authentication

By Frogitecture