🟨 목 차 🟨
1. Firebase Authentication, Realtime Database를 이용하여 ID 찾기
2. Firebase Authentication, Realtime Database를 이용하여 PWD 찾기
흔히들 있는 앱에서 회원가입, 로그인 뿐 만 아니라 아이디 찾기, 비밀번호 찾기는 꼭 가지고 있는 기능이다.
나는 아이디 찾기, 비밀번호 찾기 기능을 어떻게 구현할 지 생각을 해보았다.
회원가입하였을때 Firebase Authentication을 이용하여 이곳에 정보를 저장하고 로그인 기능을 구현했을때 이곳의 정보를 이용하여 로그인을 하였으니 아이디 찾기와 비밀번호 찾기도 Firebase Authentication을 이용하지 않을까 싶었다.
결론만 말하자면,
- ID를 찾을때에는 회원가입하였을때 Firebase Realtime Database에 고유의 전화번호에 대해서 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답] 을 저장하였는데 이것들 중 이름과 고유한 전화번호를 비교하여 일치하면 ID를 찾게 되는 방식이다.
[ Firebase Authentication 사용 x , Firebase Realtime Database 사용 o ] - PassWord를 찾을때에는 Firebase Realtime Database에 고유의 전화번호에 대해서 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답] 을 저장하였는데 이것들 중 이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답을 비교하여 일치하면 PassWord를 찾게 되는 방식이다.
[ Firebase Authentication 사용 o , Firebase Realtime Database 사용 o ]
아래에 자세히 명세하도록 하겠다.
◼️ 1. Firebase Authentication, Realtime Database를 이용하여 ID 찾기 ◼️
로그인 액티비티에서 아이디 찾기를 클릭하면 내가 직접 만든 CustomDialog_find_id를 띄어준다. 띄어진 Dialog의 기능들은
회원가입하였을때 Firebase Realtime Database에 전화 번호에 대해서 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답] 을 저장하였는데 이것들 중 이름과 고유한 전화번호를 비교하여 일치하면 ID를 찾게 되는 방식이다.
Firebase Realtime Database에 고유의 전화번호에 대해서 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답] 들을 저장을 했고, 입력한 핸드폰 번호가 Firebase Realtime Database에 존재하면 값을 가져오도록 하여 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답]의 정보들을 가져올 수 있는 것이고, 핸드폰 번호가 Firebase Realtime Database에 존재하지 않는다면 애초에 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답]의 정보들을 가져올 수 없다. 즉,
- Firebase Realtime Database에서 shopproject-UserAccount-(내가 입력한 전화번호)에 데이터가 null 값이아니고(내가 입력한 전화번호가 존재한다면) 또한 내가 입력한 이름과 Firebase Realtime Database의 가져온 이름과 일치한다면 Firebase Realtime Database에서 이메일 아이디 데이터를 가져와 Toast 메세지로 이메일 아이디를 띄우는 방식이다.
- Firebase Realtime Database에서 shopproject-UserAccount-(내가 입력한 전화번호)에 데이터가 null 이라면 Toast메세지로 이름과 전화번호가 일치하는 정보를 찾지 못했다고 띄우는 방식이다.
< CustomDialog_find_id.java >
package com.example.shopproject;
import android.app.Dialog;
import android.content.Context;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
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.ValueEventListener;
public class CustomDialog_find_id extends Dialog implements AdapterView.OnItemSelectedListener{
private EditText find_id_name;
private EditText find_id_phone;
private Button find_id_button;
private DatabaseReference mDatabaseRef; // 파이어베이스 실시간 데이터베이스 변수 생성
public CustomDialog_find_id(Context context)
{
super(context);
setContentView(R.layout.custom_dialog_find_id); // CustomDialog_find_id에 적용될 xml 연결
find_id_name = findViewById(R.id.find_id_name); // CustomDialog_find_id에 적용될 xml 연결
find_id_phone = findViewById(R.id.find_id_phone); // CustomDialog_find_id에 적용될 xml 연결
find_id_button = findViewById(R.id.find_id_button); // CustomDialog_find_id에 적용될 xml 연결
mDatabaseRef = FirebaseDatabase.getInstance().getReference("shopproject"); // 파이어베이스 DB 인스턴스 획득 및 shopproject 상위 가지 형성
find_id_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String name = find_id_name.getText().toString().trim(); //사용자가 입력한 글자 추출
String phone = find_id_phone.getText().toString().trim(); //사용자가 입력한 글자 추출
mDatabaseRef.child("UserAccount").child(phone).addValueEventListener(new ValueEventListener() {
//파이어베이스의 실시간 데이터베이스에서 shopproject-UserAccount-(내가 입력한 전화번호)의 위치애 들어간다.
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) { //작업이 완료가 되었을때
UserAccount user = snapshot.getValue(UserAccount.class);//UserAccount의 객체를 생성하는데 이것이 파이어베이스의 실시간 데이터베이스에서 데이터를 가져온다.
if (user != null && name.equals(user.getName())) {
//만약 파이어베이스의 실시간 데이터베이스에서 shopproject-UserAccount-(내가 입력한 전화번호)에 데이터가 null 값이아니고(내가 입력한 전화번호가 존재한다면) 또한 내가 입력한 이름과 파이어베이스의 가져온 이름과 일치한다면
Toast.makeText(context, "당신의 아이디는 [ " + user.getEmailId() + " ] 입니다.",Toast.LENGTH_LONG).show(); // 실시간 데이터베이스로부터 shopproject-UserAccount-(내가 입력한 전화번호)속에 있는 이메일ID 데이터를 Toast메세지로 띄운다.
dismiss();//Dialog 창 닫기
}
else { // 그게 아니라면
Toast.makeText(context, "이름과 전화번호가 일치하는 정보를 찾지 못했습니다.", Toast.LENGTH_SHORT).show();
//일치하는 정보가 없다고 Toast 메세지 띄우기
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) { //중간에 작업에 오류가 났을때
}
});
}
});
}
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
< CustomDialog_find_id.xml >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<LinearLayout
android:layout_width="280dp"
android:layout_height="245dp"
android:layout_gravity="center"
android:background="#eeeeee"
android:gravity="start"
android:orientation="vertical"
>
<!-- 타이틀바 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="53dp"
android:gravity="center"
android:text="계정찾기"
android:textColor="@color/black"
android:textSize="20sp" />
</LinearLayout>
<!-- //end 타이틀바 -->
<!-- Notice -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/find_id_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:ems="10"
android:inputType="textPersonName"
android:hint=" 이름을 입력해주세요."
android:textColor="@color/black" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/find_id_phone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:ems="10"
android:inputType="textPersonName"
android:hint=" 전화번호를 입력해주세요."
android:textColor="@color/black" />
</LinearLayout>
</LinearLayout>
<!-- Notice -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#66bdbdbd" />
<!-- 닫기 버튼 -->
<Button
android:id="@+id/find_id_button"
android:layout_width="125dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:background="@color/yellow"
android:gravity="center"
android:text="찾기"
android:textColor="@color/white" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
</LinearLayout>
<!--// 닫기 버튼 -->
</LinearLayout>
</LinearLayout>
◼️ 2. Firebase Authentication, Realtime Database를 이용하여 PWD 찾기 ◼️
로그인 액티비티에서 비밀번호 찾기를 클릭하면 내가 직접 만든 CustomDialog_find_pwd를 띄어준다. 띄어진 Dialog의 기능들은
회원가입하였을때 Firebase Realtime Database에 전화 번호에 대해서 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답] 을 저장하였는데 이것들 중 이메일아이디, 이름, 전화번호, 질문, 질문의 답 비교하여 일치하면 PW를 입력한 이메일로 비밀번호 변경 메세지를 보내어 바꾸는 형식이다.
[ 나는 이메일로 바꾸는 형식이 아닌 바로 비밀번호를 바꾸는 형식으로 하려고 했지만, Firebase Authentication에 등록된 비밀번호도 바꿔야 한다는 것 이였다. Firebase Authentication에 등록된 비밀번호를 바꾸기 위해서는 Firebase Authentication 인스턴스를 획득하고 이 인스턴스를 이용하여 FirebaseUser 인스턴스를 획득을 하고 FirebaseUser을 통해 비밀번호를 바꾸는 메소드를 이용하여 바꿔야한다. 하지만 FirebaseUser를 이용을 하게되면 로그인이 되어 있는 상태에서 진행해야하기때문에 불가능 했다. 왜냐하면 비밀번호 찾는 기능은 로그인이 안되어서 로그인을 하기 위한 방법인데 말이지.. 로그인한 상태에서 한다는 말은 말이 안되기 때문이다. 그래서 Firebase Authentication을 통해 이용할 수 있는 email을 통하여 비밀번호를 바꾸는 방법을 선택했다.]
- Firebase Authentication 인스턴스[ sendPasswordResetEmail()메소드 ] : 로그인이 되어있지 않은 상태에서 이메일을 통해 비밀번호를 변경할 수 있다.
- FirebaseUser 인스턴스[ updatePassword()메소드 ] : 로그인이 되어 있는 상태에서 비밀번호를 변경 할 수 있다.
Firebase Realtime Database에 고유의 전화번호에 대해서 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답] 들을 저장을 했고, 입력한 핸드폰 번호가 Firebase Realtime Database에 존재하면 값을 가져오도록 하여 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답]의 정보들을 가져올 수 있는 것이고, 핸드폰 번호가 Firebase Realtime Database에 존재하지 않는다면 애초에 [이메일아이디, 생년월일, 이름, 전화번호, 질문, 질문의 답]의 정보들을 가져올 수 없다. 즉,
- Firebase Realtime Database에서 shopproject-UserAccount-(내가 입력한 전화번호)에 데이터가 null 값이아니고(내가 입력한 전화번호가 존재한다면) 또한 내가 입력한 이름과 Firebase Realtime Database의 이름이 일치하고, 또한 내가 입력한 핸드폰 번호와 Firebase Realtime Database의 번호가 일치하고, 또한 내가 입력한 이메일과 Firebase Realtime Database의 이메일이 일치하고,내가 선택한 spinner(질문)과 Firebase Realtime Database의 질문이 일치하고, 또한 내가 입력한 질문의 답 과 Firebase Realtime Database의 질문의 답변이 일치한다면 Firebase Realtime Database에서 이메일 데이터를 얻어와 Firebase Authentication 인스턴스를 얻어 사용하는 sendPasswordResetEmail()메소드를 사용하여 이메일 변경 메세지를 보내고 Toast 메세지로 이메일로 비밀번호 변경 메세지를 보냈다고 띄우는 방식이다.
- 예외처리로 아무런 입력값이 없을때는 Toast메세지로 "정보를 입력해주세요" 메세지를 띄우고, Firebase Realtime Database에서 shopproject-UserAccount-(내가 입력한 전화번호)에 데이터가 null 이라면 Toast메세지로 일치하는 회원정보가 없다고 띄우고, 내가 입력한 이름과 Firebase Realtime Database의 이름이 일치하지 않고, 또한 내가 입력한 핸드폰 번호와 Firebase Realtime Database의 번호가 일치하지 않고, 또한 내가 입력한 이메일과 Firebase Realtime Database의 이메일이 일치하지 않는다면 Toast메세지로 일치하는 회원정보가 없다고 띄우고, 내가 선택한 spinner(질문)과 Firebase Realtime Database의 질문이 일치하지 않고, 또한 내가 입력한 질문의 답 과 Firebase Realtime Database의 질문의 답변이 일치하지 않는다면 Toast메세지로 질문의 답이 일치하지 않는다고 띄우는 방식이다.
< CustomDialog_find_pwd.java >
package com.example.shopproject;
import android.app.Dialog;
import android.content.Context;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.google.firebase.auth.FirebaseAuth;
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.ValueEventListener;
public class CustomDialog_find_pwd extends Dialog implements AdapterView.OnItemSelectedListener{
private EditText find_pwd_email;
private EditText find_pwd_name;
private EditText find_pwd_phone;
private EditText find_pwd_question;
private Button find_pwd_button;
private Spinner find_pwd_spinner;
private FirebaseAuth mFirebaseAuth; // 파이어베이스 인증 변수 생성
private DatabaseReference mDatabaseRef; // 파이어베이스 실시간 데이터베이스 변수 생성
private CustomDialog_change_pwd customDialogChangePwd; // CustomDialog_change_pwd 객체 변수 생성
public CustomDialog_find_pwd(Context context)
{
super(context);
setContentView(R.layout.custom_dialog_find_pwd); //custom_dialog_find_pwd 적용될 xml 연결
find_pwd_email = findViewById(R.id.find_pwd_email); //custom_dialog_find_pwd 적용될 xml 연결
find_pwd_name = findViewById(R.id.find_pwd_name); //custom_dialog_find_pwd 적용될 xml 연결
find_pwd_phone = findViewById(R.id.find_pwd_phone); //custom_dialog_find_pwd 적용될 xml 연결
find_pwd_question = findViewById(R.id.find_pwd_question); //custom_dialog_find_pwd 적용될 xml 연결
find_pwd_button = findViewById(R.id.find_pwd_button); //custom_dialog_find_pwd 적용될 xml 연결
find_pwd_spinner = findViewById(R.id.find_pwd_spinner); //custom_dialog_find_pwd 적용될 xml 연결
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context,R.array.question, android.R.layout.simple_spinner_item);
//simple_spinner_item의 xml에 question의 array 아이템들의 데이터를 생성하는 spinner의 Adapter 생성
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // dropdown 되었을 때 보여지는 View에서 사용될 layout을 별도로 설정하는 경우 사용
find_pwd_spinner.setAdapter(adapter); //find_pwd_spinner에 adapter를 연결
find_pwd_spinner.setOnItemSelectedListener(this); //해당 포지션에 세팅된 아이템 내용을 얻는다.
mFirebaseAuth = FirebaseAuth.getInstance(); // 파이어베이스 인증 인스턴스 획득
mDatabaseRef = FirebaseDatabase.getInstance().getReference("shopproject"); // 파이어베이스 DB 인스턴스 획득 및 shopproject 상위 가지 형성
find_pwd_button.setOnClickListener(new View.OnClickListener() { //find_pwd_button를 클릭했을때
@Override
public void onClick(View view) {
String email = find_pwd_email.getText().toString().trim(); //사용자가 입력한 글자 추출
String name = find_pwd_name.getText().toString().trim(); //사용자가 입력한 글자 추출
String phone = find_pwd_phone.getText().toString().trim(); //사용자가 입력한 글자 추출
String question = find_pwd_question.getText().toString().trim(); //사용자가 입력한 글자 추출
String spinner = find_pwd_spinner.getSelectedItem().toString().trim(); //사용자가 입력한 글자 추출
mDatabaseRef.child("UserAccount").child(phone).addValueEventListener(new ValueEventListener() {
//파이어베이스의 실시간 데이터베이스에서 shopproject-UserAccount-(내가 입력한 전화번호)의 위치에 들어간다.
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) { //작업이 완료가 되었을때
UserAccount user = snapshot.getValue(UserAccount.class); //UserAccount의 객체를 생성하는데 이것이 파이어베이스의 실시간 데이터베이스에서 데이터를 가져온다.
if( !email.equals("") && !name.equals("") && !phone.equals("") && !spinner.equals("") && !question.equals("")){
//입력한 email, name, phone, question, 선택한 spinner의 값이 null 값이 아니라면
if(user !=null) { //만약 파이어베이스의 실시간 데이터베이스에서 shopproject-UserAccount-(내가 입력한 전화번호)에 데이터가 null 값이 아니라면
if (name.equals(user.getName()) && phone.equals(user.getPhone())
&& email.equals(user.getEmailId())) {//내가 입력한 이름과 실시간 데이터베이스의 이름이 일치하고, 또한 내가 입력한 핸드폰 번호와 실시간 데이터베이스의 번호가 일치하고, 또한 내가 입력한 이메일과 실시간 데이터베이스의 이메일이 일치한다면
if (spinner.equals(user.getSpinner()) && question.equals(user.getQuestion())) {//내가 선택한 spinner(질문)과 실시간 데이터베이스의 질문이 일치하고, 또한 내가 입력한 질문의 답과 실시간 데이터베이스의 질문의 답변이 일치한다면
mFirebaseAuth.sendPasswordResetEmail(user.getEmailId()).addOnCompleteListener(task -> { //파이어베이스 인증 객체를 이용하여 등록한 이메일로 비밀번호 변경 메세지를 보낸다.
if (task.isSuccessful()){ //성공한다면
Toast.makeText(context, "설정하신 이메일로 비밀번호 변경 메세지를 발송하였습니다.("+user.getEmailId()+")", Toast.LENGTH_LONG).show(); //Toast메세지로 설정하신 이메일로 비밀번호 변경 메세지를 발송하였다는 메세지를 띄운다.
dismiss(); //창을 닫는다.
}
});
// Toast.makeText(context, "비밀번호 변경가능합니다", Toast.LENGTH_SHORT).show();//Toast 메세지로 비밀번호 변경이 가능하다고 띄어준다.
// dismiss(); //창을 닫는다
// customDialogChangePwd = new CustomDialog_change_pwd(context, phone);//CustomDialog_change_pwd(Pwd를 바꾸는 Dialog)의 객체를 생성한다.
// customDialogChangePwd.show();// CustomDialog_change_pwd 객체를 실행한다.
} else {
Toast.makeText(context, "질문의 답이 일치 하지 않습니다.", Toast.LENGTH_SHORT).show(); //Toast 메세지로 질문의 답이 일치 하지 않는다고 띄어준다.
}
} else {
Toast.makeText(context, "일치하는 회원정보가 없습니다.", Toast.LENGTH_SHORT).show(); //Toast 메세지로 일치하는 회원정보가 없다고 띄어준다.
}
}
else {
Toast.makeText(context, "일치하는 회원정보가 없습니다.", Toast.LENGTH_SHORT).show(); //Toast 메세지로 일치하는 회원정보가 없다고 띄어준다.
}
}
else {
Toast.makeText(context, "정보를 입력해주세요.",Toast.LENGTH_SHORT).show(); //Toast 메세지로 정보를 입력해주세요 라고 띄어준다.
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) { //중간에 작업에 오류가 났을때
}
});
}
});
}
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
String text = adapterView.getItemAtPosition(i).toString();
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
< CustomDialog_find_pwd.xml >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<LinearLayout
android:layout_width="280dp"
android:layout_height="260dp"
android:layout_gravity="center"
android:background="#eeeeee"
android:gravity="start"
android:orientation="vertical"
>
<!-- 타이틀바 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="53dp"
android:gravity="center"
android:text="비밀번호 변경"
android:textColor="@color/black"
android:textSize="20sp" />
</LinearLayout>
<!-- //end 타이틀바 -->
<!-- Notice -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="155dp"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/find_pwd_email"
android:layout_width="match_parent"
android:layout_height="40dp"
android:ems="10"
android:inputType="textPersonName"
android:textSize="13dp"
android:hint=" 아이디를 입력해주세요."
android:textColor="@color/black" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/find_pwd_name"
android:layout_width="135dp"
android:layout_height="match_parent"
android:ems="10"
android:hint=" 이름을 입력해주세요."
android:textSize="13dp"
android:inputType="textPersonName"
android:textColor="@color/black" />
<EditText
android:id="@+id/find_pwd_phone"
android:layout_width="match_parent"
android:layout_height="40dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="전화번호를 입력해주세요."
android:textSize="13dp"
android:textColor="@color/black" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Spinner
android:id="@+id/find_pwd_spinner"
android:layout_width="match_parent"
android:layout_height="30dp"
android:spinnerMode="dropdown"
>
</Spinner>
<EditText
android:id="@+id/find_pwd_question"
android:layout_width="match_parent"
android:layout_height="40dp"
android:ems="10"
android:inputType="textPersonName"
android:textSize="13dp"
android:hint=" 질문의 답을 입력해주세요."
android:textColor="@color/black" />
</LinearLayout>
</LinearLayout>
<!-- Notice -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#66bdbdbd" />
<!-- 닫기 버튼 -->
<Button
android:id="@+id/find_pwd_button"
android:layout_width="125dp"
android:layout_height="35dp"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:layout_marginBottom="10dp"
android:background="@color/yellow"
android:gravity="center"
android:text="찾기"
android:textColor="@color/black" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
</LinearLayout>
<!--// 닫기 버튼 -->
</LinearLayout>
</LinearLayout>
'프로젝트 > Android Studio_중고거래앱_Project' 카테고리의 다른 글
Android Studio_중고거래 앱(SharedPreferences를 이용한 로그인 정보 저장 구현(자동 로그인) ) (0) | 2022.08.05 |
---|---|
Android Studio_중고거래 앱(파이어베이스를 이용한 로그아웃, 회원탈퇴) (0) | 2022.08.05 |
Android Studio_중고거래 앱(프래그먼트 >> 액티비티로의 데이터[위치 정보] 전달) (0) | 2022.08.04 |
Android Studio_중고거래 앱(구글 Map Api 사용을 하여 현재 위치 추출하기) (0) | 2022.08.04 |
Android Studio_중고거래 앱(등록된 상품 목록을 클릭하면 자세한 상품 내용 보여주는 화면 구성) (0) | 2022.08.04 |