[안드로이드 - 코틀린] Kakao API Login

2022. 6. 21. 22:44Android

안드로이드 스튜디오 터미널을 이용해 HASH 키 값을 찾는 법 -> 터미널 검색을 통해 쉽게 찾을 수 있다  -> build.gradle에 카카오 라이브러리를 호출해야 사용가능

implementation "com.kakao.sdk:v2-user:2.11.0"

Kakao Developers에서 플랫폼 활성화에 사용된다

 

+  패키지명은 Activitiy, gradle ..에 있는 package 뒤에 있는걸 다 넣어주면 됨

//        Hash 키 값
        val keyHash = Utility.getKeyHash(this)
        Log.d("Hash", keyHash)

 

build.gradle ( Module ~ ) 

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.2'
    implementation 'com.google.android.material:material:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    
    implementation "com.kakao.sdk:v2-user:2.8.0" // 카카오 로그인

    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
implementation "com.kakao.sdk:v2-user:2.8.0" // 카카오 로그인

현재 사용되는 버전은 2022년 6월 21일 사용 향후 바뀌는 버전에 맞춰 업데이트를 해줘야함

 

settings.gradle 

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/' }
    }
}
maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/' }

 

AndroidManifest

 

인터넷 통신 활성화를 위한 인터넷 권한

<uses-permission android:name="android.permission.INTERNET" />

 

카카오 API를 이용해 불러올 Activity

<activity
    android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
    android:exported="true">
        <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="네이티브 키" />
        </intent-filter>
</activity>

 

<data android:host="oauth"
                android:scheme="네이티브 키" />

 

네이티브 키는 kakao developers  홈페이지에서 발급 받을 수 있다

 

https://developers.kakao.com/

 

Kakao Developers

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

developers.kakao.com

MainActivity

 

기존 로그인에 성공한 경우 '자동 로그인'이 실행되고 로그인을 하지 못한 경우에는 '로그인 기록 없음'이 토스트 메세지에 실행된다 

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 로그인 정보 확인
        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))
                finish()
            }
        }

 

토큰을 이용해 카카오 로그인

 

val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
    if (error != null) {
    	// 로그인 실패
    }
    else if (token != null){
    	// 로그인 성공
        val intent = Intent(this, SecondActivity::class.java)
        startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
        finish()
    }
} 

val kakao_login_button = findViewById<ImageButton>(R.id.kakao_login_button) // 로그인 버튼

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

 

GlobalApplication

 

new -> kotlin class/file 생성

 

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

        KakaoSdk.init(this, "네이티브 키")
    }

}

 

SecondActivity

 

로그인에 성공하면 나오는 창으로 사용자 정보를 화면에 나타낸다 

로그아웃과 회원탈퇴 버튼이 보이는데 코드를 보면 알 수 있는데 그냥 다시 로그인 창으로 돌아가는 기능이다 (진짜 회원 탈퇴 아님)

 

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.secondactivity)

        var id : TextView = findViewById(R.id.id)
        var nickname : TextView = findViewById(R.id.nickname)
        var profileimage_url : TextView = findViewById(R.id.profileimage_url)
        var thumbnailimage_url : TextView = findViewById(R.id.thumbnailimage_url)

        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}"
        }

        val kakao_logout_button = findViewById<Button>(R.id.kakao_logout_button) // 로그아웃 버튼

        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))
                finish()
            }
        }

        val kakao_unlink_button = findViewById<Button>(R.id.kakao_unlink_button) // 회원탈퇴 버튼

        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))
                    finish()
                }
            }
        }
    }

}

 

main_activity_xml

 

- drawable 호출은 Kakao Developers에서 이미지 다운 받은 것이다

<?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"
    tools:context=".MainActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

 

Secondactivity_xml

 

<?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"
    tools:context=".SecondActivity">

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

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

    <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"
        />


</androidx.constraintlayout.widget.ConstraintLayout>