안드로이드 개발/중고거래앱 만들기

[Android Kotlin] 코틀린 카카오 로그인 구현하기

얌자 2021. 2. 3. 02:18

2021/01/27 - [안드로이드 개발/중고거래앱 만들기] - [Android] 로그인 화면 만들기

2021/01/29 - [안드로이드 개발/중고거래앱 만들기] - [Kotlin] Firebase연결 및 Firebase로 회원가입 /File google-servieces.json is missing 오류 해결 방법 /socket failed:EPERM(Operation not permitted) 오류해결법/

2021/01/29 - [안드로이드 개발/중고거래앱 만들기] - [Kotlin] Firebase 로그인 구현

2021/01/29 - [안드로이드 개발/중고거래앱 만들기] - [Kotlin] Firebase 구글 로그인 구현

 

[Kotlin] Firebase 구글 로그인 구현

구글 로그인을 구현 해보겠습니다. 일단 Firebase 홈페이지에 들어가셔서 Authentication -> Sign-in-method 에 들어가 Google 로그인을 사용할 수 있도록 설정 하겠습니다. 사용 설정 클릭하시고 이메일 입력

yumja.tistory.com

 

 

이번에는 카카오 로그인을 구현해보겠습니다.

카카오 공식 홈페이지에 나와 있긴 하지만 적용해서 하기에는 어려운 면이 있더라구요.

 

 

1. 애플리케이션 추가

 

 

카카오 개발자 웹사이트에서 로그인한 후, [내 애플리케이션] > [애플리케이션 추가하기]를 눌러 앱을 생성할 수 있습니다.

 

앱 아이콘은 필수 사항이 아니며, 앱 이름과 회사 이름만 입력해주어도 됩니다. 회사 이름은 그냥 본인 이름 써도 무관하더라구요.

 

 

 

2. 플랫폼 등록

 

 

카카오 로그인, 카카오링크를 비롯한 일부 카카오 API는 등록된 플랫폼에서만 사용 가능하기 때문에 등록을 먼저 해주도록 하겠습니다.

 

[내 애플리케이션] > [앱 설정] > [플랫폼] 메뉴에서 플랫폼을 등록합니다.

 

 

패키지명은 Module 수준의 build.gradle 파일이나, AndroidManifest.xml 파일에서 확인할 수 있습니다.

 

 

등록할 키 해시의 값도 알아야하는데, com.kakao.sdk.common.util 에서 키 해시 값을 알 수 있는 Util을 제공해줍니다. 

MainActivity의 onCreate 안에  다음 코드를 실행하여 키 해시 값을 가져오도록 할게요.

Log에 뜬 키 해시 값을 그대로 복사하여 붙여넣으면 됩니다.

 

 

var keyHash = Utility.getKeyHash(this)
Log.v(TAG, keyHash)

 

 

3. 카카오 로그인 활성화 및 Redirect URI 설정

 

 

 

[내 애플리케이션] > [제품 설정] > [카카오 로그인] 에 들어가서 카카오 로그인을 활성화 해줍니다.

 

Redirect URI 같은 경우는 서버가 있다면 설정을 해주시고 아니라면 임의의 URI 를 등록 해주시면 됩니다.

 

임의의 URI를 등록한 모습

 

4. 동의 항목 설정

 

 

[내 애플리케이션] > [제품 설정] > [카카오 로그인] > [동의항목] 에서 필요한 사용자 정보에 대한 설정을 할 수 있습니다. 필요하다고 생각 되시는 항목을 추가해주시면 됩니다.

 

 

5. Gradle 설정하기

 

이제 코드를 추가해 보겠습니다. 

프로젝트 레벨 build.gradle에 다음과 같이 Android SDK 레파지토리(Repository)를 설정합니다.

 

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/' }
    }
}

 

6. 필요한 모듈 설정하기

 

 

모듈 레벨의 build.gradle 파일에 필요한 모듈을 설정합니다.

실질적으로 지금 필요한것은 로그인 파트 뿐이니 implementation "com.kakao.sdk:v2-user:2.0.5" 만 추가해도 무관하다.

 

dependencies {
  implementation "com.kakao.sdk:v2-user:2.3.0" // 카카오 로그인
  implementation "com.kakao.sdk:v2-talk:2.3.0" // 친구, 메시지(카카오톡)
  implementation "com.kakao.sdk:v2-story:2.3.0" // 카카오스토리
  implementation "com.kakao.sdk:v2-link:2.3.0" // 메시지(카카오링크)
  implementation "com.kakao.sdk:v2-navi:2.3.0" // 카카오내비
}

 

 

7. 인터넷 사용 권한 설정

 

 

AndroidManifest.xml에 다음과 같이 인터넷 사용 권한을 설정합니다.

 

 

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.sample">

    <!-- 인터넷 사용 권한 설정-->
    <uses-permission android:name="android.permission.INTERNET" />

    <application
    android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
    ...

 

 

8. 카카오 SDK 초기화

 

[내 애플리케이션] > [앱 설정] > [요약 정보] 에서 네이티브 앱 키 를 확인하고 이를 이용해 카카오 SDK를 초기화 해줍니다. 

res -> values -> strings.xml 파일에 하단의 코드를 추가해줍니다. 네이티브 앱 키 입력 칸에 키를 붙혀 넣습니다.

 

 

<resources>
    <string name="kakao_app_key">네이티브 앱 키 입력</string>
</resources>

 

 

GlobalApplication.kt 클라스를 생성해줍니다.

 

 

package com.example.carrotmarket

import android.app.Application
import com.kakao.sdk.common.KakaoSdk

class GlobalApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        KakaoSdk.init(this,getString(R.string.kakao_app_key))
    }
}

 

 

AndroidManifest.xml 에 android:name을 추가 설정해줍니다.

 

 

<application
    <!-- android:name 설정 -->
    android:name=".GlobalApplication"
    ...
>

 

 

9. Redirect URI 설정하기

 

 

AndroidManifest.xml 에 하단의 코드를 추가해줍니다.

'android:scheme' 속성의 'kakao{NATIVE_APP_KEY}' 안에는 네이티브 앱 키를 넣어줍니다. 예를 들어 네이티브 앱 키가 '123456789'라면 'kakao123456789'를 입력해주시면 돼요.

 

 

<activity android:name=“com.kakao.sdk.auth.AuthCodeHandlerActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <!-- Redirect URI: "kakao{NATIVE_APP_KEY}://oauth“ -->
        <data android:host="oauth"
                android:scheme="kakao{NATIVE_APP_KEY}" />
    </intent-filter>
</activity>

 

10. 로그인 코드 구현

 

 

카카오 디벨로퍼 사이트에 나와 있는 로그인 구현 예제 입니다.

 

카카오톡이 설치 되어 있다면 loginWithKakaoTalk()을,

카카오톡이 미설치 되었다면 loginWithKakaoAccount()를 사용합니다.

 

 

LoginActivity.kt 의 onCreate 안에 작성한 코드입니다.

 

 

 val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
            if (error != null) {
                //Login Fail
            }
            else if (token != null) {
                //Login Success
                val nextIntent = Intent(this, MainActivity::class.java)
                startActivity(nextIntent)
            }
        }
        
          btn_login_kakao.setOnClickListener {
            LoginClient.instance.run {
                if (isKakaoTalkLoginAvailable(this@LoginActivity)) {
                    loginWithKakaoTalk(this@LoginActivity, callback = callback)
                } else {
                    loginWithKakaoAccount(this@LoginActivity, callback = callback)
                }
            }
        }

 

 

11. 결과

 

 

 

에뮬레이터에 카카오톡 앱이 다운 받아져 있지 않기 때문에 인터넷 창이 뜨네요.

 

 

저는 동의 항목에서 프로필 정보(닉네임/프로필 사진) 제공을 동의 하도록 설정해서 위 화면처럼 팝업이 뜹니다.

 

다시 로그인을 시도하면 전에 로그인 했던 카카오톡 아이디를 저절로 불러옵니다.

 

 

 

LoginActivity.kt 전체 코드

 

 

 

package com.example.carrotmarket

import android.content.Intent
import android.nfc.Tag
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.auth.api.Auth
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.GoogleAuthProvider
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.kakao.sdk.auth.LoginClient
import com.kakao.sdk.auth.model.OAuthToken
import kotlinx.android.synthetic.main.activity_login.*

class LoginActivity : AppCompatActivity() {

    private lateinit var auth: FirebaseAuth
    var googleSignInClient : GoogleSignInClient? = null
    var GOOGLE_LOGIN_CODE = 9001

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        auth = Firebase.auth

        val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
            if (error != null) {
                //Login Fail
            }
            else if (token != null) {
                //Login Success
                val nextIntent = Intent(this, MainActivity::class.java)
                startActivity(nextIntent)
            }
        }
        btn_sign_up_go.setOnClickListener {
            val nextIntent = Intent(this, SingUpActivity::class.java)
            startActivity(nextIntent)
        }

        btn_login.setOnClickListener {
            signin()
        }

        btn_login_google.setOnClickListener {
            googleLogin()
        }

        btn_login_kakao.setOnClickListener {
            LoginClient.instance.run {
                if (isKakaoTalkLoginAvailable(this@LoginActivity)) {
                    loginWithKakaoTalk(this@LoginActivity, callback = callback)
                } else {
                    loginWithKakaoAccount(this@LoginActivity, callback = callback)
                }
            }
        }


        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken("567256059244-f9uocncnrjkv5jkf1ml1vj7d714e8840.apps.googleusercontent.com")
            .requestEmail()
            .build()

        googleSignInClient = GoogleSignIn.getClient(this,gso)

    }


    fun googleLogin(){
        var signInIntent = googleSignInClient?.signInIntent
        startActivityForResult(signInIntent,GOOGLE_LOGIN_CODE)
    }
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(requestCode == GOOGLE_LOGIN_CODE){
            var result = Auth.GoogleSignInApi.getSignInResultFromIntent(data)
            if (result != null) {
                if (result.isSuccess){
                    var account = result.signInAccount
                    firebaseAuthWithGoogle(account)
                }
            }
        }
    }

    fun firebaseAuthWithGoogle(account : GoogleSignInAccount?){
        var credential = GoogleAuthProvider.getCredential(account?.idToken,null)
        auth?.signInWithCredential(credential)
            ?.addOnCompleteListener {
                    task ->
                if(task.isSuccessful){
                    //Login
                    moveMainPage(task.result?.user)
                }
                else{
                    Toast.makeText(this,task.exception?.message, Toast.LENGTH_LONG).show()
                    //Show the error message
                }
            }
    }
    fun signin(){
        auth?.signInWithEmailAndPassword(editText_email.text.toString(),editText_password.text.toString())
            ?.addOnCompleteListener {
                    task ->
                if(task.isSuccessful){
                    moveMainPage(task.result?.user)
                }else{
                    //Show the error message
                    Toast.makeText(this,task.exception?.message, Toast.LENGTH_LONG).show()
                }

            }
    }

    fun moveMainPage(user: FirebaseUser?){
        if(user !=null){
            startActivity(Intent(this,MainActivity::class.java))
        }
    }
}