이번 프로젝트는 전부 컴포즈로 구성하기로 해서 이전 프로젝트에서 쓴 파이어베이스 구글 로그인 코드를 컴포즈로 전환해 코드를 짜보았습니다.
로딩창 3초간 띄우고, 동시에 로그인 체크.
로그인 되어있으면 메인페이지, 로그인 안되어있으면 로그인페이지로
class StartActivity : ComponentActivity() {
// Firebase
private val auth: FirebaseAuth = FirebaseAuth.getInstance()
private val viewModel by viewModels<LoginViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 로그인 시도
viewModel.tryLogin(this)
lifecycleScope.launchWhenCreated {
viewModel.loginResult.collect { isLogin ->
if (isLogin) {
if (auth.currentUser != null) {
startActivity(Intent(this@StartActivity, MainActivity::class.java))
}
} else {
// 로그인 안되어있을 때 로그인 페이지 열림
startActivity(Intent(this@StartActivity, LoginActivity::class.java))
}
}
}
setContent {
Surface(color = Color.White) {
Text(text = "로그인 확인중", fontSize = 30.sp)
}
}
}
}
class LoginViewModel : ViewModel() {
// 로그인 결과 반환 변수
private val _loginResult = MutableSharedFlow<Boolean>()
var loginResult = _loginResult.asSharedFlow()
fun tryLogin(context: Context) {
viewModelScope.launch {
val account = async {
getLastSignedInAccount(context)
}
delay(2500)
// 계정 확인 -> true, 없음 -> false 반환
setLoginResult(account.await() != null)
}
}
// 이전에 로그인 한 계정이 있는지 확인
private fun getLastSignedInAccount(context: Context) = GoogleSignIn.getLastSignedInAccount(context)
private fun setLoginResult(isLogin: Boolean) {
viewModelScope.launch {
_loginResult.emit(isLogin)
}
}
}
class LoginActivity : ComponentActivity() {
// Firebase
private lateinit var googleSignInClient: GoogleSignInClient
private val auth: FirebaseAuth = FirebaseAuth.getInstance()
private val RC_SIGN_IN = 1313
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
LoginScreen { googleLogin() }
}
}
// 로그인 객체 생성
fun googleLogin() {
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
googleSignInClient = GoogleSignIn.getClient(this, gso)
googleSignIn()
}
// 구글 회원가입
private fun googleSignIn() {
val signInIntent = googleSignInClient.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RC_SIGN_IN) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
val account = task.getResult(ApiException::class.java)
firebaseAuthWithGoogle(account)
} catch (e: ApiException) {
Toast.makeText(this, "구글 회원가입에 실패하였습니다: ${e.message}", Toast.LENGTH_SHORT).show()
}
} else {
/*no-op*/
}
}
// account 객체에서 id 토큰 가져온 후 Firebase 인증
private fun firebaseAuthWithGoogle(account: GoogleSignInAccount?) {
val credential = GoogleAuthProvider.getCredential(account?.idToken, null)
auth.signInWithCredential(credential).addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
toMainActivity(auth.currentUser)
}
}
}
private fun toMainActivity(user: FirebaseUser?) {
if (user != null) {
startActivity(Intent(this, MainActivity::class.java))
}
}
}
@Composable
fun LoginScreen(content: () -> Unit) {
Surface(color = Color.White) {
Column(
modifier = Modifier.fillMaxSize().padding(start = 15.dp, end = 15.dp),
verticalArrangement = Arrangement.Center
) {
Greeting(text = "시작하시겠습니까?")
SignInGoogleButton { content() }
}
}
}
@Composable
fun Greeting(text: String) {
Text(text = text, style = MaterialTheme.typography.body2, color = Color.Gray, modifier = Modifier.padding(bottom = 12.dp))
}
@Composable
fun SignInGoogleButton(onClick: () -> Unit) {
Surface(
modifier = Modifier.clickable(onClick = onClick).fillMaxWidth(),
// border = BorderStroke(width = 1.dp, color = Color.LightGray),
color = MaterialTheme.colors.surface,
shape = MaterialTheme.shapes.small,
elevation = 10.dp
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
modifier = Modifier.padding(
start = 14.dp,
end = 12.dp,
top = 11.dp,
bottom = 11.dp
)
) {
Icon(painter = painterResource(id = R.drawable.icon_google), contentDescription = "Google sign button", tint = Color.Unspecified, modifier = Modifier.size(35.dp))
Spacer(modifier = Modifier.width(20.dp))
Text(text = "Sign in with Google", style = MaterialTheme.typography.overline, color = Color.Gray, fontSize = 17.sp, fontWeight = FontWeight.Bold)
}
}
}
xml 쓸때는 google 버튼이 따로 있어서 만들일이 없었는데 컴포즈에는 없고 심지어 컴포즈를 쓴게 이 페이지가 처음이라 꽤나 애먹은 ㅠㅡㅜ
그래도 나름 만들고 나니 뿌듯....
너무 유익해서 어지러워요 앞으로도 계속 써주세요!!! 뽀뽀쪽