[일일이] android/kotlin 구글 로그인 연동하기

두리두두·2024년 6월 9일
0

TIL

목록 보기
12/15

  • 자자 .. 구글 로그인 연동을 해보자
  • 구글 플레이에 설정도 해야하고 앱에도 넣어야하고 복잡하다 복자배!
  • 신경써야할 것들을 정리해보았다.

1. Google Firebase Console

https://console.firebase.google.com/

  • 프로젝트 설정 > 일반 > SHA-1 설정 (내 프로젝트의 SHA-1 가져와서 저장)
  • Authentication > Google 로그인 추가 설정 (-> 이거 추가 저장을 안하고 계속 빌드하다가 로그인 실패 떠서 여기서 설정이 안되어있음을 깨닫고 ,, 해결했다)
    => 요런 설정 마친 후 젤 최신 버전의 google-services.json을 app 폴더에 갱신해줘야함!!

2. Google Cloud Console

https://console.cloud.google.com/apis/

  • OAuth 2.0 클라이언트 ID 추가 : 요건 OAuth 동의 화면 작성 후 가능하다. 여기서 얻은 클라이언트 ID를 패키지 values - string.xml에 저장해두고 갖다써야한다!!

3. gradle

  • app 단위 gradle
  • 여기 플러그인에 google-services를 추가 안했다가 앱이 계속 강종됐다 ^_^
// 플러그인 마지막줄 추가 안했다가 빌드 오류 계속남!!
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("com.google.gms.google-services")
}


// Import the BoM for the Firebase platform
    implementation(platform("com.google.firebase:firebase-bom:32.3.1"))

    // Add the dependency for the Firebase Authentication library
    // When using the BoM, you don't specify versions in Firebase library dependencies
    implementation("com.google.firebase:firebase-auth-ktx")

    // Also add the dependency for the Google Play services library and specify its version
    implementation("com.google.android.gms:play-services-auth:20.7.0")
  • 프로젝트 단위 gradle
plugins {
  ...
    id("com.google.gms.google-services") version "4.4.2" apply false
}

4. 구현

activity_login.xml

  • 몰랐는데 구글 로그인 넣으려면 구글이 권장하는 디자인 가이드를 따라야한다고 한다 ㄱ-
  • 버튼 height 48dp 이상, 구글 로고 넣어야하고, 버튼 색이 구글 색이어야하는 등등...
  • 나는 앱 시작 화면에만 들어가므로 대략 이렇게 디자인만 잡아보았다.
<?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:background="#FFFFFF"
    tools:context=".LoginActivity">

    <ImageView
        android:id="@+id/logo_login"
        android:layout_width="147dp"
        android:layout_height="68dp"
        android:layout_marginTop="176dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/logo" />

    <TextView
        android:id="@+id/infoLogin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:text="로그인하고 나만의 일기를 작성해보세요."
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.57"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/logo_login" />

    <Button
        android:id="@+id/btnGoogle"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginHorizontal="16dp"
        android:layout_marginTop="60dp"
        android:background="#4285F4"
        android:drawableStart="@drawable/ic_google_logo"
        android:drawablePadding="8dp"
        android:gravity="center_vertical|start"
        android:paddingHorizontal="16dp"
        android:paddingVertical="12dp"
        android:text="Google로 로그인"
        android:textColor="#ffffff"
        android:textSize="14sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.937"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/infoLogin" />

</androidx.constraintlayout.widget.ConstraintLayout>

LoginActivity.kt

  • 대망의 액티비티.
  • 최초 접속 시 기본 화면이 이 액티비티이고, 로그인 상태이거나 로그인 성공한 후에는 MainActivity로 가게 할 것이다.
  1. 기본 화면 세팅 (AndroidManifest.xml)
<!-- LoginActivity를 앱의 진입점으로 설정 -->
        <activity
            android:name=".LoginActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".MainActivity"
            android:exported="true">
        </activity>
  1. LoginActivity.kt
  • 일단 내가 이해하기론,, 파이어베이스 연동하여 로그인 하는 과정이
    1) 사용자의 ID와 기본 프로필 정보를 요청하기 위해 GoogleSignInOptions 생성 (이 때 OAuth 클라이언트 ID필요, requestIdToken, requestEmail 등 설정)
    2) 위에서 지정한 옵션으로 googleSignInClient 객체 생성
    3) 생성한 googleSignInClient의 인텐트를 구글 로그인을 위한 화면 여는 곳에 넘긴다. GoogleSignIn.getSignedInAccountFromIntent로 구글 로그인 시작
    4) 로그인 결과를 받아와서 성공이면 파이어베이스 인증을 태운다. 이 때 credential이 필요한데, 위에서 얻은 tokenId로 가져오고 firebaseAuth.signInWithCredential(credential)를 통해 파이어베이스 인증을 마친다.
    5) 성공하면 메인액티비티로, 실패하면 얼럿을 띄우도록 해보자
package com.duridudu.oneone2

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import com.duridudu.oneone2.databinding.ActivityLoginBinding
import com.duridudu.oneone2.databinding.ActivityMainBinding
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.GoogleAuthProvider

class LoginActivity : AppCompatActivity() {
    private lateinit var binding: ActivityLoginBinding
    private lateinit var googleSignInClient: GoogleSignInClient
    private lateinit var firebaseAuth: FirebaseAuth

    private val googleSignInLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            result ->
            val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
            Log.d("LOGIN--", task.toString())
            try {
                // Google 로그인이 성공하면, Firebase로 인증합니다.
                val account = task.getResult(ApiException::class.java)!!
                Log.d("LOGIN--22", account.idToken!!)
                firebaseAuthWithGoogle(account.idToken!!)
            } catch (e: ApiException) {
                // Google 로그인 실패
                Toast.makeText(this, "Google 로그인에 실패했습니다.", Toast.LENGTH_SHORT).show()
            }

    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // Firebase Authentication 인스턴스 초기화
        firebaseAuth = FirebaseAuth.getInstance()

        // 이미 로그인되어 있는지 확인
        if (firebaseAuth.currentUser != null) {
            // 이미 로그인된 경우 메인 화면으로 이동
            startActivity(Intent(this, MainActivity::class.java))
            finish()
            return
        }

        // GoogleSignInOptions를 구성합니다.
        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestServerAuthCode(getString(R.string.default_web_client_id))
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .build()

        // GoogleSignInClient를 초기화합니다.
        googleSignInClient = GoogleSignIn.getClient(this, gso)

        // 구글 로그인 버튼 클릭 이벤트 처리
        binding.btnGoogle.setOnClickListener {
            signIn()
        }
    }

    private fun signIn() {
        val signInIntent = googleSignInClient.signInIntent
        googleSignInLauncher.launch(signInIntent)
    }

    private fun firebaseAuthWithGoogle(idToken: String) {
        Log.d("LOGIN--3",idToken)
        val credential = GoogleAuthProvider.getCredential(idToken, null)
        firebaseAuth.signInWithCredential(credential)
            .addOnCompleteListener(this) { task ->
                if (task.isSuccessful) {
                    // 로그인 성공
                    val user = firebaseAuth.currentUser
                    Toast.makeText(this, "환영합니다, ${user?.displayName}!", Toast.LENGTH_SHORT).show()
                    // 여기서 로그인 후 화면 전환 등의 작업을 수행할 수 있습니다.
                    startActivity(Intent(this, MainActivity::class.java))
                    finish()
                } else {
                    // 로그인 실패
                    Toast.makeText(this, "Firebase 인증에 실패했습니다.", Toast.LENGTH_SHORT).show()
                }
            }
    }
}
  • 결과는 gif 따려니 나의 안드로이드스튜디오가 너무 느려서 생략하겠다.. 이제 할 것은 이 로그인한 유저 ID를 어떻게 저장해서 어떻게 관리하느냐이다! 이제 글 작성할 준비가 조금은 되었다 후후

번외

  • 번외로 챗지피티가 플로우를 잘 설명해준게 있어서 추가한다.. ^_ㅠ

구글 로그인 관련
1. GoogleSignInOptions 객체를 사용하여 Google 로그인을 위한 옵션을 설정합니다. 이 옵션에는 ID 토큰 요청, 이메일 요청 등이 포함될 수 있습니다.
2. GoogleSignInClient 객체를 생성하여 Google 로그인을 수행합니다. 이때는 GoogleSignInOptions 객체를 전달하여 클라이언트를 초기화합니다.
3. signInIntent 메서드를 호출하여 Google 로그인을 위한 Intent를 생성합니다. 이 Intent는 Google 로그인 창을 표시하고 사용자에게 로그인을 요청합니다.
4. startActivityForResult()를 사용하여 이 Intent를 시작하고, 사용자의 로그인 상태에 따라 적절한 처리를 수행합니다.

firebase 인증 관련
1. GoogleAuthProvider.getCredential(idToken, null): Google 로그인 후에 받은 ID 토큰을 사용하여 Firebase에 인증 자격 증명을 만듭니다. 이를 통해 Firebase에 사용자를 인증할 수 있습니다. idToken은 사용자가 Google 로그인을 통해 발급받은 인증 토큰입니다.
2. firebaseAuth.signInWithCredential(credential): Firebase의 Authentication 기능을 사용하여 인증 자격 증명을 사용하여 사용자를 로그인시킵니다. 이 메서드를 호출하면 Firebase는 해당 인증 자격 증명을 사용하여 사용자를 인증하고, 인증이 성공하면 Firebase에 사용자를 로그인시킵니다.
3. addOnCompleteListener { task -> }: 로그인 작업이 완료되면 실행할 작업을 지정합니다. 이 코드 블록 내에서는 로그인이 성공했는지 실패했는지를 확인하고, 성공한 경우에는 로그인된 사용자에 대한 추가 작업을 수행할 수 있습니다. 실패한 경우에는 오류를 처리하거나 사용자에게 알리는 등의 작업을 수행할 수 있습니다

파이어베이스 인증도 하는 이유
Firebase를 사용하는 경우에는 Firebase Authentication을 통해 사용자를 구글 로그인하고, 로그인한 사용자의 정보를 Firebase에 저장하고 관리할 수 있습니다. Firebase를 사용하면 구글 로그인을 포함한 다양한 인증 방법을 통합하여 사용자를 관리할 수 있으며, 보안 및 편의성 측면에서 많은 이점을 제공합니다.

profile
야금야금 앱 개발자

0개의 댓글