Android

[안드로이드 - 코틀린] 카카오 로그인 구현(2)

내가갈게하와이 2022. 1. 27. 01:05

이어서 계속 구현해보자.

 

manifest 하단에 아래의 코드를 붙여놓자. 

아래의 코드중 네이티브 앱 키를 넣는 부분에서 kakko네이티브 앱 키 이런 형식으로 넣어주자.

<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" />
        <data android:host="oauth"
            android:scheme="kakao{NATIVE_APP_KEY}" />
    </intent-filter>
</activity>

이제는 로그인 버튼을 생성해 보자.

SDK V1에서는 com.kakao.usermgmt.LoginButton으로 버튼을 바로 생성할 수 있었는데, SDK V2에서는 그 기능이 사라지고 직접 버튼을 만들거나 리소스를 다운받아서 해야한다. 리소스는 아래 링크에서 다운받을 수 있다.

https://developers.kakao.com/tool/resource/login

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

다운받은 뒤에 drawable을 클릭한 후 붙여넣기를 하여 그림 파일을 넣어주자.

그리고 activity_main.xml로 이동하여 idkakao_login_button인 ImageButton을 생성한다.

<ImageButton
    android:id="@+id/kakao_login_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/kakao_login"
    android:background="@android:color/transparent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    android:layout_marginBottom="40dp"
    />

로그인 버튼 코드를 구현한다. 

 

SDK v1에서는 버튼 생성하면 알아서 그 뒤 기능까지 작동이 되었는데, 이제는 우리가 생성해줘야한다.

아래 두 가지 코드를 MainActivity.kt에 넣어주자.

import com.kakao.sdk.common.model.AuthErrorCause.*
val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
    if (error != null) {
        when {
            error.toString() == AccessDenied.toString() -> {
                Toast.makeText(this, "접근이 거부 됨(동의 취소)", Toast.LENGTH_SHORT).show()
            }
            error.toString() == InvalidClient.toString() -> {
                Toast.makeText(this, "유효하지 않은 앱", Toast.LENGTH_SHORT).show()
            }
            error.toString() == InvalidGrant.toString() -> {
                Toast.makeText(this, "인증 수단이 유효하지 않아 인증할 수 없는 상태", Toast.LENGTH_SHORT).show()
            }
            error.toString() == InvalidRequest.toString() -> {
                Toast.makeText(this, "요청 파라미터 오류", Toast.LENGTH_SHORT).show()
            }
            error.toString() == InvalidScope.toString() -> {
                Toast.makeText(this, "유효하지 않은 scope ID", Toast.LENGTH_SHORT).show()
            }
            error.toString() == Misconfigured.toString() -> {
                Toast.makeText(this, "설정이 올바르지 않음(android key hash)", Toast.LENGTH_SHORT).show()
            }
            error.toString() == ServerError.toString() -> {
                Toast.makeText(this, "서버 내부 에러", Toast.LENGTH_SHORT).show()
            }
            error.toString() == Unauthorized.toString() -> {
                Toast.makeText(this, "앱이 요청 권한이 없음", Toast.LENGTH_SHORT).show()
            }
            else -> { // Unknown
                Toast.makeText(this, "기타 에러", Toast.LENGTH_SHORT).show()
            }
        }
    }
    else if (token != null) {
        Toast.makeText(this, "로그인에 성공하였습니다.", Toast.LENGTH_SHORT).show()
    }
}

kakao_login_button.setOnClickListener {
    if(LoginClient.instance.isKakaoTalkLoginAvailable(this)){
        LoginClient.instance.loginWithKakaoTalk(this, callback = callback)
    }else{
        LoginClient.instance.loginWithKakaoAccount(this, callback = callback)
    }
}

이 코드가 있다면 로그인은 시킬 수 있지만, 로그인 했을 때 토스트 메시지를 띄우는 것 외에는 어떠한 동작도 없다.

intent로 로그인이 성공했을 경우 다른 화면으로 넘어가록 구현해보자.

 

SecondActivity라는 이름으로 액티비티를 생성한다.

이렇게 만들고 MainActivity.kt 에 넣은 코드중 아래의 코드를 찾아서 아래와 같이 수정한다. 

else if (token != null) {
    Toast.makeText(this, "로그인에 성공하였습니다.", Toast.LENGTH_SHORT).show()
    val intent = Intent(this, SecondActivity::class.java)
    startActivity(intent)
}

실행시키면 빈 화면으로 넘어가게 된다.

activity_second.xml 에 로그아웃 버튼과 회원 탈퇴 버튼을 만들어보자.

<Button
    android:id="@+id/kakao_logout_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="로그아웃"
    android:textSize="20sp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toTopOf="@+id/kakao_unlink_button"
    />

<Button
    android:id="@+id/kakao_unlink_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="회원 탈퇴"
    android:textSize="20sp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    />

그리고 마지막으로 SecondActivity에 로그아웃, 회원 탈퇴 코드를 구현한다.

kakao_logout_button.setOnClickListener {
    UserApiClient.instance.logout { error ->
        if (error != null) {
            Toast.makeText(this, "로그아웃 실패 $error", Toast.LENGTH_SHORT).show()
        }else {
            Toast.makeText(this, "로그아웃 성공", Toast.LENGTH_SHORT).show()
        }
        val intent = Intent(this, MainActivity::class.java)
        startActivity(intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP))
    }
}

kakao_unlink_button.setOnClickListener {
    UserApiClient.instance.unlink { error ->
        if (error != null) {
            Toast.makeText(this, "회원 탈퇴 실패 $error", Toast.LENGTH_SHORT).show()
        }else {
            Toast.makeText(this, "회원 탈퇴 성공", Toast.LENGTH_SHORT).show()
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP))
        }
    }
}

 


로그아웃이나 회원탈퇴를 하였을 때, intentflag를 주어 이전 화면으로 돌아오도록 하였다.

로그인을 했을 때도 뒤로 가기를 했을 때 로그인 화면으로 돌아오면 안되므로 intent를 수정해주자.

    else if (token != null) {
        Toast.makeText(this, "로그인에 성공하였습니다.", Toast.LENGTH_SHORT).show()
        val intent = Intent(this, SecondActivity::class.java)
        startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)) 수정부분
    }

로그인 유지를 위해

먼저, 한 번 로그인을 하면 sdk에서는 토큰을 가지고 있다. 로그아웃이나 회원 탈퇴를 하면 이 토큰을 삭제하도록 되어있기 때문에, 로그인이 되었는지 확인을 하기 위해서는 이 토큰이 있는지를 확인해보면 되는 것이다. 유효한 토큰이 존재하는지 확인한 뒤에 토큰이 존재한다면 로그인 상태이므로 SecondActivity로 넘겨주고, 토큰이 존재하지 않는다면 MainActivity에 머무르게 하면 된다.

토큰 확인은 UserApiClient.instance.accessTokenInfo로 가능하다.

UserApiClient.instance.accessTokenInfo { tokenInfo, error ->
    if (error != null) {
        Toast.makeText(this, "토큰 정보 보기 실패", Toast.LENGTH_SHORT).show()
    }
    else if (tokenInfo != null) {
        Toast.makeText(this, "토큰 정보 보기 성공", Toast.LENGTH_SHORT).show()
        val intent = Intent(this, SecondActivity::class.java)
        startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
    }
}

사용자의 프로필 정보를 불러오는 구현을 해보자.

카카오 developers에 들어가 아래의 화면처럼 설정한다. 

activity_second.xml 수정(추가) 해준다.

<TextView
    android:id="@+id/id"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="회원번호: "
    android:textSize="20sp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    />
        
<TextView
    android:id="@+id/nickname"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="닉네임: "
    android:textSize="20sp"
    app:layout_constraintTop_toBottomOf="@+id/id"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    />

<TextView
    android:id="@+id/profileimage_url"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="프로필 링크: "
    android:textSize="20sp"
    app:layout_constraintTop_toBottomOf="@+id/nickname"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    />

<TextView
    android:id="@+id/thumbnailimage_url"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="썸네일 링크: "
    android:textSize="20sp"
    app:layout_constraintTop_toBottomOf="@+id/profileimage_url"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    />

SecondActivity.kt 수정(추가) 해준다.

UserApiClient.instance.me { user, error ->
    id.text = "회원번호: ${user?.id}"
    nickname.text = "닉네임: ${user?.kakaoAccount?.profile?.nickname}"
    profileimage_url.text = "프로필 링크: ${user?.kakaoAccount?.profile?.profileImageUrl}"
    thumbnailimage_url.text = "썸네일 링크: ${user?.kakaoAccount?.profile?.thumbnailImageUrl}"
}

이렇게 마무리 하면 카카오 로그인 구현을 성공한 것이다.