UI
마이페이지 UI


사용자 프로필과 닉네임이 가장 상단에 뜨며, 하단에는 최근 본 약국과 스크랩한 칼럼을 볼 수 있다. 가장 하단 부분에는 사진과 같은 추가적인 기능들이 존재한다.
메인 액티비티 UI

하단의 내비게이션 바를 클릭하면 각각의 페이지가 화면에 띄워진다.
마이페이지 구현
MainActivity.kt
private var userEditor: SharedPreferences.Editor? = null
override fun onStart() {
super.onStart()
val userDataShared = getSharedPreferences("userData", MODE_PRIVATE) // SharedPeferences 객체 생성
userEditor = userDataShared.edit()
connectDatabase()
}
SharedPreferences 객체를 생성하고 connectDatabase() 메서드를 호출한다. (데이터의 변경이 있을 때 데이터를 불러오는 함수)
private fun connectDatabase() {
// 데이터베이스 연결
var userRef = database.child("users")
userRef!!.addListenerForSingleValueEvent(object : ValueEventListener { // 값의 변화가 있을 때 알려주는 리스너
override fun onDataChange(snapshot: DataSnapshot) {
for (user in snapshot.children) {
if (user.key.equals(currentUser?.uid)) {
val name = user.child("name").value.toString()
val email = user.child("email").value.toString()
val userType = user.child("userType").value.toString()
val profileUri =
if(user.child("profile").value != null)
user.child("profile").value.toString()
else // resource에 있는 'img_girls.png' 파일을 기본 프로필로 설정
Uri.parse("android.resource://" + R::class.java.getPackage().name + "/" + R.drawable.img_girls).toString()
userEditor?.putString("name", name)
userEditor?.putString("email", email)
userEditor?.putString("userType", userType)
userEditor?.putString("profileUri", profileUri)
userEditor?.apply()
return
}
}
}
override fun onCancelled(error: DatabaseError) {
Log.d("database", "Error : $error")
}
})
}
addListenerForSingleValueEvent() 메서드를 사용하여 초기 1회에만 데이터를 받아온다.
만약 firebase의 유저 목록(users)의 데이터에 변화가 있다면, 현재 유저의 uid와 일치하는 key의 value('name', 'email', 'userType', 'profile')들을 가져온다. 이후 userEditor를 통해 SharedPreferences 객체에 데이터를 저장한다.


MypageFragment.kt
var userData: SharedPreferences = (context as MainActivity).getSharedPreferences("userData", MODE_PRIVATE)
var name = userData.getString("name", null)
mypageGirl_profile_iv.setImageURI(imageUri) // 기본 프로필 출력을 위한 코드
mypageGirl_name_tv.text = name
getFireBaseProfileImage(currentUser!!.uid)
SharedPreferences 객체를 통해 userData에서 name 값을 읽어오고 화면 유저 이름을 출력한다.
getFireBaseProfileImage() 메서드를 통해서 현재 유저의 프로필 이미지를 가져오고 화면에 출력한다.
private fun getFireBaseProfileImage(uid: String) { // 파이어베이스 Storage에서 이미지를 다운받아 프로필에 불러오는 함수
val storage = FirebaseStorage.getInstance()
val storageRef = storage.reference
storageRef.child("profile_img/profile$uid.jpg").downloadUrl.addOnSuccessListener { uri ->
Glide.with((context as MainActivity))
.load(uri)
.into(mypageGirl_profile_iv)
imageUri = uri
}.addOnFailureListener { }
}
파이어베이스 Storage에서 uid에 해당하는 이미지를 다운로드하여 화면에 출력한다.

mypageGirl_logout_tv.setOnClickListener { // 로그아웃
auth.signOut()
moveLoginPage()
}
mypageGirl_withdraw_tv.setOnClickListener { // 회원 탈퇴
deleteUser()
moveLoginPage()
}
private fun deleteUser(){ // 회원을 DB에서 제거하는 함수
currentUser?.delete()
?.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d(TAG, "User account deleted.")
}
}
database.child("users").child(currentUser!!.uid).removeValue()
}
private fun moveLoginPage(){ // 로그인 페이지로 이동하는 함수
activity?.let{
val intent = Intent(context, LoginActivity::class.java)
startActivity(intent)
}
}
로그아웃을 할 때는 auth.signOut() 기능을 사용하여 로그아웃을 수행한다.
회원 탈퇴를 할 때는 currentUser.delete() 기능을 사용하여 Authentication에서 사용자 계정을 삭제하고, removeValue() 기능을 사용하여 Realtime DB에서 유저를 제거해 준다.
<전체 코드>
class MypageFragment : Fragment(){
private var database : DatabaseReference = FirebaseDatabase.getInstance().reference
private var auth: FirebaseAuth = FirebaseAuth.getInstance()
private var currentUser = auth.currentUser
private var imageUri: Uri? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
var binding = FragmentMypageBinding.inflate(inflater, container, false)
var userData: SharedPreferences = (context as MainActivity).getSharedPreferences("userData", MODE_PRIVATE)
var name = userData.getString("name", null)
mypageGirl_name_tv.text = name
getFireBaseProfileImage(currentUser!!.uid)
mypageGirl_profile_iv.setImageURI(imageUri) // 기본 프로필 출력을 위한 코드
mypageGirl_editProfile_btn.setOnClickListener { // 프로필 변경
val intent = Intent(context, ProfileActivity::class.java)
startActivity(intent)
}
mypage_intro_tv.setOnClickListener { // 서비스 소개
val intent = Intent(context, IntroduceActivity::class.java)
startActivity(intent)
}
mypageGirl_logout_tv.setOnClickListener { // 로그아웃
auth.signOut()
moveLoginPage()
}
mypageGirl_withdraw_tv.setOnClickListener { // 회원 탈퇴
deleteUser()
moveLoginPage()
}
return binding.root
}
private fun deleteUser(){ // 회원을 DB에서 제거하는 함수
currentUser?.delete()
?.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d(TAG, "User account deleted.")
}
}
database.child("users").child(currentUser!!.uid).removeValue()
}
private fun moveLoginPage(){ // 로그인 페이지로 이동하는 함수
activity?.let{
val intent = Intent(context, LoginActivity::class.java)
startActivity(intent)
}
}
private fun getFireBaseProfileImage(uid: String) { // 앱 내부 저장소에 디렉토리를 만드는 함수
// file에 디렉토리 경로를 지정
val file: File? =
(context as MainActivity).getExternalFilesDir(Environment.DIRECTORY_PICTURES + "/profile_img")
// file 경로에 디렉토리가 존재하지 않을 경우
if (!file?.isDirectory!!) {
file.mkdir() // 디렉토리 생성
}
downloadImg(uid)
}
private fun downloadImg(uid : String) { // 파이어베이스 Storage에서 이미지를 다운받아 프로필에 불러오는 함수
val storage = FirebaseStorage.getInstance()
val storageRef = storage.reference
storageRef.child("profile_img/profile$uid.jpg").downloadUrl.addOnSuccessListener { uri ->
Glide.with((context as MainActivity))
.load(uri)
.into(mypageGirl_profile_iv)
imageUri = uri
}.addOnFailureListener { }
}
}
+) 아쉽게도 시간이 부족하여 리사이클러뷰를 활용한 '최근 본 약국', '스크랩한 칼럼' 기능은 구현하지 못했다.
[Reference]
Glide로 이미지 로드 https://blog.yena.io/studynote/2020/06/10/Android-Glide.html