로그인한 사용자의 정보 중에 사용자마다 무조건 다른 값은 아이디와 사용자 번호임
데이터를 저장할때 중복해서 저장될 데이터가 있는지 고려해야 한다.
자동로그인을 체크하고 로그인하면 사용자의 idx를 저장한다.
이후에 다시 로그인 페이지로 올때 사용자의 idx가 저장되어있는게 확인되면 자동로그인 처리를 해준다.
자동로그인을 체크하지 않고 로그인하면 사용자의 idx를 저장하지 않는다.
이후에 다시 로그인 페이지로 오면 다시 로그인 과정을 거쳐야 한다.
단말기 로컬 저장방법 3개(File, SQLite, Preferences) 중 Preferences를 이용하여 사용자 정보를 저장한다.
UserDao.kt
// 아이디를 통해 사용자 정보를 가져오는 메서드
suspend fun getUserDataById(userId:String) : UserModel?{
// 사용자 정보 객체를 담을 변수
var userModel:UserModel? = null
val job1 = CoroutineScope(Dispatchers.IO).launch {
// UserData 컬렉션 접근 객체를 가져온다.
val collectionReference = Firebase.firestore.collection("UserData")
// userId 필드가 매개변수로 들어오는 userId와 같은 문서들을 가져온다.
val querySnapshot = collectionReference.whereEqualTo("userId", userId).get().await()
// 만약 가져온 것이 있다면
if(querySnapshot.isEmpty == false){
// 가져온 문서 객체들이 들어있는 리스트에서 첫 번째 객체를 추출한다.
// 아이디가 동일한 사용자는 없기 때문에 무조건 하나만 나오기 때문
userModel = querySnapshot.documents[0].toObject(UserModel::class.java)
// 이때 UserModel클래스의 매개변수가 없는 생성자를 호출해주기 때문에 생성자를 만들어놔야 한다.
// Log.d("test1234","${userModel}")
}
}
job1.join()
return userModel
}

fireStore 를 사용할 때 데이터를 담을 클래스 타입을 지정하게 되면 매개 변수가 없는 생성자를 사용해 객체 생성해주기 때문에, 해당 클래스에 매개 변수가 없는 생성자를 만들어줘야 한다.
// UserModel.kt
// 회원번호, 아이디, 비밀번호, 닉네임, 나이, 성별 , 취미6가지, 회원상태
data class UserModel(
var userIdx:Int,
var userId:String,
var userPw:String,
var userNickName:String,
var userAge:Int,
var userGender:Int,
var userHobby1:Boolean, var userHobby2:Boolean, var userHobby3:Boolean,
var userHobby4:Boolean, var userHobby5:Boolean, var userHobby6:Boolean,
var userState:Int
){
// 매개 변수가 없는 생성자
// fireStore 를 사용할 때 데이터를 담을 클래스 타입을 지정하게 되면
// 매개 변수가 없는 생성자를 사용해 객체 생성해주기 때문에 만들어줘야 한다.
constructor() : this(0, "", "", "", 0, 0, false, false, false, false, false, false, 0)
}
// LoginFragment.kt
// 로그인 버튼
fun settingButtonLoginSubmit(){
fragmentLoginBinding.apply {
buttonLoginSubmit.apply {
// 버튼을 눌렀을 때
setOnClickListener {
// 유효성 검사
val chk = checkInputForm()
// 모든 유효성 검사에 통과를 했다면
if(chk == true){
loginPro()
}
}
}
}
}
// 로그인 처리
fun loginPro(){
// 사용자가 입력한 정보를 가져온다.
val userId = loginViewModel.textFieldLoginUserId.value!!
val userPw = loginViewModel.textFieldLoginUserPw.value!!
val job1 = CoroutineScope(Dispatchers.Main).launch {
val loginUserModel = UserDao.getUserDataById(userId)
// 만약 null이라면
if(loginUserModel == null){
Tools.showErrorDialog(mainActivity, fragmentLoginBinding.textFieldLoginUserId, "로그인 오류", "존재하지 않는 아이디입니다")
}
// 만약 정보를 가져온 것이 있다면
else {
// 입력한 비밀번호와 서버에서 받아온 사용자의 비밀번호가 다르다면..
if(userPw != loginUserModel.userPw){
Tools.showErrorDialog(mainActivity, fragmentLoginBinding.textFieldLoginUserId, "로그인 오류", "비밀번호가 잘못되었습니다")
}
// 비밀번호가 일치한다면
else{
// Snackbar.make(fragmentLoginBinding.root, "로그인에 성공하였습니다", Snackbar.LENGTH_SHORT).show()
// 액티비티가 바뀌므로 스낵바가 바로 사라진다
// ContentActivity를 실행한다.
val contentIntent = Intent(mainActivity, ContentActivity::class.java)
// 로그인한 사용자의 정보를 전달해준다.
contentIntent.putExtra("loginUserIdx", loginUserModel.userIdx)
contentIntent.putExtra("loginUserNickName", loginUserModel.userNickName)
startActivity(contentIntent)
// MainActivity를 종료한다.
mainActivity.finish()
}
}
}
}


ContentActivity에서 로그인한 사용자의 정보를 사용할 수 있게 변수를 생성하고
전달받은 Intent로부터 값을 가져와 담아준다.
// ContentActivity.kt
// 로그인한 사용자의 정보를 담을 변수
var loginUserIdx = 0
var loginUserNickName = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityContentBinding = ActivityContentBinding.inflate(layoutInflater)
setContentView(activityContentBinding.root)
// 로그인한 사용자 정보를 변수에 담아둔다.
loginUserIdx = intent.getIntExtra("loginUserIdx", 0)
loginUserNickName = intent.getStringExtra("loginUserNickName")!!
settingNavigationView()
val bundle = Bundle()
bundle.putString("title","전체게시판")
replaceFragment(ContentFragmentName.MAIN_FRAGMENT, false, false, bundle)
}
기존 메서드에 자동 로그인이 체크되어 있다면 Preferences에 idx와 닉네임을 저장해주는 코드도 추가해준다.
// LoginFragment.kt
// 로그인 처리
fun loginPro(){
// 사용자가 입력한 정보를 가져온다.
val userId = loginViewModel.textFieldLoginUserId.value!!
val userPw = loginViewModel.textFieldLoginUserPw.value!!
val job1 = CoroutineScope(Dispatchers.Main).launch {
val loginUserModel = UserDao.getUserDataById(userId)
// 만약 null이라면
if(loginUserModel == null){
Tools.showErrorDialog(mainActivity, fragmentLoginBinding.textFieldLoginUserId, "로그인 오류", "존재하지 않는 아이디입니다")
}
// 만약 정보를 가져온 것이 있다면
else {
// 입력한 비밀번호와 서버에서 받아온 사용자의 비밀번호가 다르다면..
if(userPw != loginUserModel.userPw){
Tools.showErrorDialog(mainActivity, fragmentLoginBinding.textFieldLoginUserId, "로그인 오류", "비밀번호가 잘못되었습니다")
}
// 비밀번호가 일치한다면
else{
// 자동 로그인이 체크되어 있다면
if(loginViewModel.checkBoxLoginAuto.value == true){
// Preferences에 사용자 정보를 저장해준다.
val sharedPreferences = mainActivity.getSharedPreferences("AutoLogin", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putInt("loginUserIdx", loginUserModel.userIdx)
editor.putString("loginUserNickName", loginUserModel.userNickName)
editor.apply()
}
// Snackbar.make(fragmentLoginBinding.root, "로그인에 성공하였습니다", Snackbar.LENGTH_SHORT).show()
// ContentActivity를 실행한다.
val contentIntent = Intent(mainActivity, ContentActivity::class.java)
// 로그인한 사용자의 정보를 전달해준다.
contentIntent.putExtra("loginUserIdx", loginUserModel.userIdx)
contentIntent.putExtra("loginUserNickName", loginUserModel.userNickName)
startActivity(contentIntent)
// MainActivity를 종료한다.
mainActivity.finish()
}
}
}
}
자동로그인 여부를 확인하고 되어있다면 바로 ContentActivity를 실행시키고
아니라면 로그인 화면을 띄운다.
// MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 스플래시 스크린이 나타나게 한다.
// 반드시 setContentView 전에 해야 한다.
// 코틀린에서는 installSplashScreen 메서드가 구현이 되어있어 호출만 하면 된다.
installSplashScreen()
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
// 권한 확인
requestPermissions(permissionList, 0)
// 자동로그인 시 저장된 사용자 정보를 가져온다.
val sharedPreferences = getSharedPreferences("AutoLogin", MODE_PRIVATE)
val loginUserIdx = sharedPreferences.getInt("loginUserIdx", -1)
val loginUserNickName = sharedPreferences.getString("loginUserNickName", null)
// 자동 로그인 시 저장된 사용자 인덱스값이 없다면(자동로그인을 체크하지 않았다면)
if(loginUserIdx == -1){
// 첫 화면을 띄워준다.
replaceFragment(MainFragmentName.LOGIN_FRAGMENT, false, false, null)
}
// 그렇지 않으면
else {
// ContentActivity를 실행한다.
val contentIntent = Intent(this, ContentActivity::class.java)
// 로그인한 사용자의 정보를 전달해준다.
contentIntent.putExtra("loginUserIdx", loginUserIdx)
contentIntent.putExtra("loginUserNickName", loginUserNickName)
startActivity(contentIntent)
// MainActivity를 종료한다.
finish()
}
}
자동로그인 체크 후 로그인을 한 후에 어플을 종료하고 다시 키면 로그인 과정 없이 바로 게시판으로 들어가는 것을 확인할 수 있다.