[Android Studio] Firebase를 이용한 아이디찾기/비밀번호찾기 구현

지우개·2024년 2월 29일
0

Android Studio

목록 보기
3/3

Firebase를 이용하여 아이디찾기와 비밀번호 찾기도 구현해보았다.

비밀번호 찾기라고 했지만 사실상은 비밀번호 재설정이다...


세부 구현 내용

  • 로그인 화면에서 아이디 찾기와 비밀번호 찾기를 누르면 그에 해당하는 액티비티로 이동
  • 아이디 찾기의 경우 앞서 회원가입을 할때 RealtimeDatabase에 저장해둔 사용자 정보(이름, 전화번호, 이메일)를 사용해서 기능을 구현.
  • 비밀번호 찾기의 경우 Firebase auth에 이메일을 통해 비밀번호를 재설정 할 수 있는 기능이 있어서 이를 활용.
  • 이때 아이디 찾기와 비밀번호 찾기는 로그인이 된 상태에서 사용자의 정보를 가져오는 것이 아니기때문에 이 점을 유의해서 구현해야함.

아이디 찾기 UI

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_marginStart="20dp"
    android:layout_marginEnd="20dp"
    tools:context=".FindIdActivity">

    <TextView
        android:id="@+id/findIdTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:textSize="32dp"
        android:text="아이디 찾기"
        android:textStyle="bold"
        android:textColor="#000000"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"></TextView>
    <LinearLayout
        android:id="@+id/findId_linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/findIdTextView">
        <TextView
            android:id="@+id/findId_nameTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="이름"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/findId_nameEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="예) 홍길동"></EditText>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/findId_linearLayout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/findId_linearLayout1">
        <TextView
            android:id="@+id/findId_numberTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="전화번호"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/findId_numberEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="예) 01012345678"></EditText>
    </LinearLayout>
    <android.widget.Button
        android:id="@+id/findIdBtn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginTop="15dp"
        android:text="찾기"
        android:textColor="#000000"
        android:background="@drawable/button_rounded_corners"
        app:layout_constraintTop_toBottomOf="@+id/findId_linearLayout2"></android.widget.Button>
    <android.widget.Button
        android:id="@+id/cancelBtn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginTop="15dp"
        android:text="로그인 화면으로 돌아가기"
        android:textColor="#000000"
        android:background="@drawable/button_rounded_corners"
        app:layout_constraintTop_toBottomOf="@+id/findIdBtn"></android.widget.Button>

</androidx.constraintlayout.widget.ConstraintLayout>
<?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"
    android:layout_marginStart="20dp"
    android:layout_marginEnd="20dp"
    tools:context=".FindIdActivity2">

    <TextView
        android:id="@+id/findIdTextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:textSize="32dp"
        android:text="아이디 찾기"
        android:textStyle="bold"
        android:textColor="#000000"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"></TextView>

    <TextView
        android:id="@+id/findIdtv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:gravity="center"
        android:textColor="#000000"
        android:layout_marginTop="50dp"
        app:layout_constraintTop_toBottomOf="@+id/findIdTextView2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"></TextView>

    <android.widget.Button
        android:id="@+id/backBtn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginTop="50dp"
        android:text="로그인 화면으로 돌아가기"
        android:textColor="#000000"
        android:background="@drawable/button_rounded_corners"
        app:layout_constraintTop_toBottomOf="@+id/findIdtv1"></android.widget.Button>

</androidx.constraintlayout.widget.ConstraintLayout>

아이디 찾기 액티비티
FindIdActivity.java

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class FindIdActivity extends AppCompatActivity {
    EditText nameEditText, numberEditText;
    Button findIdBtn, cancelBtn;

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

        nameEditText = findViewById(R.id.findId_nameEditText);
        numberEditText = findViewById(R.id.findId_numberEditText);
        findIdBtn = findViewById(R.id.findIdBtn);
        cancelBtn = findViewById(R.id.cancelBtn);

        findIdBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String name = nameEditText.getText().toString();
                String number = numberEditText.getText().toString();

                // 이름과 전화번호 정보를 Intent에 담아서 FindIdActivity2로 전달
                Intent intent = new Intent(FindIdActivity.this, FindIdActivity2.class);
                intent.putExtra("name", name);
                intent.putExtra("number", number);
                startActivity(intent);
            }
        });

        cancelBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 취소 버튼 클릭 시 MainActivity로 돌아감
                Intent intent = new Intent(FindIdActivity.this, MainActivity.class);
                startActivity(intent);
            }
        });
    }
}
  • 이름과 전화번호를 입력한 후 "아이디 찾기" 버튼을 클릭하여 아이디를 찾을 수 있게 구현됨.
  • 사용자는 EditText를 통해 이름과 전화번호를 입력함.
  • 사용자가 "아이디 찾기" 버튼을 클릭하면 입력된 이름과 전화번호 정보를 Intent에 담아서 FindIdActivity2로 전달함.
  • 사용자가 "취소" 버튼을 클릭하면 MainActivity(로그인 액티비티)로 돌아감.

FindIdActivity2.java

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
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.Query;
import com.google.firebase.database.ValueEventListener;

public class FindIdActivity2 extends AppCompatActivity {
    TextView idTextView;
    Button backBtn;
    DatabaseReference databaseReference;

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

        idTextView = findViewById(R.id.findIdtv1);
        backBtn = findViewById(R.id.backBtn);

        Intent intent = getIntent();
        String name = intent.getStringExtra("name");
        String number = intent.getStringExtra("number");

        findUserId(name, number); // 사용자 이메일 찾는 메서드 호출

        backBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(FindIdActivity2.this, MainActivity.class);
                startActivity(intent);
            }
        });
    }

    // 사용자의 이름과 전화번호를 이용하여 이메일(아이디)을 찾는 메서드
    private void findUserId(String name, String number) {
        DatabaseReference userReference = FirebaseDatabase.getInstance().getReference().child("UserAccount");
        userReference.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                boolean found = false;
                for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                    String userName = (String) userSnapshot.child("name").getValue();
                    String userNumber = (String) userSnapshot.child("number").getValue();
                    if (userName != null && userName.equals(name) && userNumber != null && userNumber.equals(number)) {
                        String userId = (String) userSnapshot.child("id").getValue(); // 사용자의 아이디
                        idTextView.setText("'" + userId + "' 입니다.");
                        found = true;

                        break;
                    }
                }


                if (!found) {
                    idTextView.setText("해당하는 사용자를 찾을 수 없습니다.");
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                idTextView.setText("오류가 발생했습니다. 다시 시도해주세요.");
            }
        });
    }

}
  • 사용자의 이름과 전화번호를 받아와서 해당하는 사용자의 아이디를 찾고 화면에 표시하는 기능을 수행
  • 이전 액티비티에서 전달된 인텐트를 받아와서 이름과 전화번호를 가져옴.

// 사용자의 이름과 전화번호를 이용하여 이메일(아이디)을 찾는 메서드
    private void findUserId(String name, String number) {
        DatabaseReference userReference = FirebaseDatabase.getInstance().getReference().child("UserAccount");
        userReference.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                boolean found = false;
                for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                    String userName = (String) userSnapshot.child("name").getValue();
                    String userNumber = (String) userSnapshot.child("number").getValue();
                    if (userName != null && userName.equals(name) && userNumber != null && userNumber.equals(number)) {
                        String userId = (String) userSnapshot.child("id").getValue(); // 사용자의 아이디
                        idTextView.setText("'" + userId + "' 입니다.");
                        found = true;

                        break;
                    }
                }


                if (!found) {
                    idTextView.setText("해당하는 사용자를 찾을 수 없습니다.");
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                idTextView.setText("오류가 발생했습니다. 다시 시도해주세요.");
            }
        });
    }
  • Firebase Realtime Database에서 "UserAccount" 경로에 있는 사용자 계정 정보를 가져와서 사용자가 입력한 이름과 전화번호와 일치하는 사용자의 아이디를 찾아야 함.
  • 이때 로그인 된 상태가 아니기때문에 FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); 를 사용하지 않음.
  • DataSnapshot은 Firebase Realtime Database의 데이터 스냅샷을 나타내고, 이를 통해 데이터베이스에서 가져온 데이터를 사용할 수 있음.
  • for 루프를 사용하여 "UserAccount" 경로의 각 사용자에 대한 스냅샷을 반복함.
  • 각 사용자의 이름과 전화번호를 가져와서 입력된 이름과 전화번호와 비교
  • 이름과 전화번호가 일치하는 사용자를 찾으면 해당 사용자의 아이디를 가져와서 TextView를 사용해 화면에 표시함.
  • found 변수를 사용하여 사용자를 찾았는지 여부를 추적하고, 사용자를 찾지 못한 경우 "해당하는 사용자를 찾을 수 없습니다." 메시지를 표시
  • 데이터베이스에서 사용자 정보를 가져오는 과정에서 오류가 발생할 경우 적절한 메시지를 표시
  • 뒤로 가기 버튼을 클릭하면 MainActivity(로그인 액티비티)로 이동

수행 화면


비밀번호 찾기 UI

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_marginStart="20dp"
    android:layout_marginEnd="20dp"
    tools:context=".FindPasswordActivity">

    <TextView
        android:id="@+id/findPwTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:textSize="32dp"
        android:text="비밀번호 찾기"
        android:textStyle="bold"
        android:textColor="#000000"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"></TextView>
    <LinearLayout
        android:id="@+id/findPw_linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/findPwTextView">
        <TextView
            android:id="@+id/findPw_nameTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="이름"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/findPw_nameEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="예) 홍길동"></EditText>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/findPw_linearLayout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/findPw_linearLayout1">
        <TextView
            android:id="@+id/findPw_IdTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="이메일"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/findPw_IdEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="예) apple@gmail.com"></EditText>
    </LinearLayout>
    <android.widget.Button
        android:id="@+id/findPwBtn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginTop="15dp"
        android:text="새 비밀번호 설정 메일 보내기"
        android:textColor="#000000"
        android:background="@drawable/button_rounded_corners"
        app:layout_constraintTop_toBottomOf="@+id/findPw_linearLayout2"></android.widget.Button>
    <android.widget.Button
        android:id="@+id/cancelBtn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginTop="15dp"
        android:text="로그인 화면으로 돌아가기"
        android:textColor="#000000"
        android:background="@drawable/button_rounded_corners"
        app:layout_constraintTop_toBottomOf="@+id/findPwBtn"></android.widget.Button>


</androidx.constraintlayout.widget.ConstraintLayout>

비밀번호 찾기 액티비티
FindPwActivity.java

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthInvalidUserException;
import com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException;
import com.google.firebase.auth.FirebaseAuthUserCollisionException;

public class FindPasswordActivity extends AppCompatActivity {
    EditText nameEditText, idEditText;
    Button findPwBtn, cancelBtn;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_findpw);

        nameEditText = findViewById(R.id.findPw_nameEditText);
        idEditText = findViewById(R.id.findPw_IdEditText);
        findPwBtn = findViewById(R.id.findPwBtn);
        cancelBtn = findViewById(R.id.cancelBtn);

        findPwBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final String name = nameEditText.getText().toString().trim();
                final String email = idEditText.getText().toString().trim();

                // 이름과 이메일이 입력되었는지 확인
                if (name.isEmpty() || email.isEmpty()) {
                    Toast.makeText(FindPasswordActivity.this, "이름과 이메일을 입력하세요.", Toast.LENGTH_SHORT).show();
                    return;
                }

                // Firebase에서 비밀번호 재설정 이메일 보내기
                FirebaseAuth.getInstance().sendPasswordResetEmail(email)
                        .addOnCompleteListener(task -> {
                            if (task.isSuccessful()) {
                                Toast.makeText(FindPasswordActivity.this, "비밀번호 재설정 이메일을 전송했습니다.", Toast.LENGTH_SHORT).show();
                                // 비밀번호 재설정 이메일을 보냈으므로 메인 액티비티로 이동
                                Intent intent = new Intent(FindPasswordActivity.this, MainActivity.class);
                                startActivity(intent);
                            } else {
                                // Firebase의 예외 처리
                                try {
                                    throw task.getException();
                                } catch (FirebaseAuthInvalidUserException e) {
                                    Toast.makeText(FindPasswordActivity.this, "존재하지 않는 이메일입니다.", Toast.LENGTH_SHORT).show();
                                } catch (FirebaseAuthRecentLoginRequiredException e) {
                                    Toast.makeText(FindPasswordActivity.this, "최근에 로그인한 기기가 아닙니다.", Toast.LENGTH_SHORT).show();
                                } catch (FirebaseAuthUserCollisionException e) {
                                    Toast.makeText(FindPasswordActivity.this, "사용자 충돌이 발생했습니다.", Toast.LENGTH_SHORT).show();
                                } catch (Exception e) {
                                    Toast.makeText(FindPasswordActivity.this, "비밀번호 재설정 이메일 전송에 실패했습니다.", Toast.LENGTH_SHORT).show();
                                }
                            }
                        });
            }
        });

        cancelBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 취소 버튼 클릭 시 메인 액티비티로 이동
                Intent intent = new Intent(FindPasswordActivity.this, MainActivity.class);
                startActivity(intent);
            }
        });
    }
}
  • 비밀번호를 잊어버렸을 때 비밀번호 재설정 이메일을 보내는 기능을 구현
  • 사용자가 이름과 이메일을 입력했는지 확인하고, 입력되지 않았을 경우 사용자에게 메시지를 표시
  • Firebase Auth의 sendPasswordResetEmail() 메서드를 사용하여 사용자의 이메일 주소로 비밀번호 재설정 이메일을 보냄. 이메일 전송이 성공하면 성공 메시지를 표시하고, 실패한 경우 Firebase 예외를 처리하여 적절한 메시지를 표시
  • 사용자가 "취소" 버튼을 클릭하면 MainActivity(로그인 액티비티)로 이동

수행 화면

0개의 댓글