[UMC] Android 9주차 워크북 (Network) - 소셜 로그인
📝 Standard Mission
소셜 로그인 한 가지 이상 구현해보기
- ex. 카카오, 네이버, 구글…
- 단순 화면 전환 뿐만 아니라 이름, 이메일 값 가져와서 TextView에 띄우기
- SDK 사용 가능
✅ 프로젝트 초기 설정
우선 프로젝트를 하나 생성하고 build.gradle(project) 파일 대신 settings.gradle 파일에 Android SDK 레파지토리(Repository)를 설정한다. (이유는 아래 블로그를 참고)
[안드로이드] Android studio Arctic Fox 버전 이후 gradle allprojects 추가방법
안드로이드 스튜디오 버전을 업데이트하고 신규 프로젝트파일을 생성했습니다. 라이브러리 추가가 필요해서 jcenter와 jitpack.io 레포지토리 등록을 평소처럼 프로젝트 단위의 build.gradle에서 추가
ideajini.tistory.com
다음 코드를 적고 우측 상단에 있는 Sync Now를 누른다.
// 카카오 sdk 레포지토리 설정
maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/' }
다음으로 build.gradle (app) 파일에 카카오 로그인 모듈을 추가하고 Sync Now를 해준다.
implementation "com.kakao.sdk:v2-user:2.0.1"
카카오 api를 통해 카카오 서버와 통신하기 위해 앱에 인터넷 사용 권한을 설정한다.
mainfests -> AndroidMainfest.xml에서 다음 코드를 적는다.
<!-- 인터넷 사용 권한 설정-->
<uses-permission android:name="android.permission.INTERNET" />
✅ 키 해시 구하기
MainActivity에서 다음 코드를 작성해 키 해시를 구한다. Log를 출력해보면 Hash 값이 나오는 것을 확인할 수 있다.
val keyHash = Utility.getKeyHash(this)
Log.d("Hash", keyHash)
이제 키 해시를 복사하여 android 플랫폼 등록에 사용한다.
카카오계정
accounts.kakao.com
플랫폼에 들어가 패키지명과 키 해시 값을 적어준다.
✅ GlobalApplication 생성
Kakao SDK를 사용하기 위해서 Native App Key로 초기화를 해야 한다.
GlobalApplication이란 이름으로 된 코틀린 class를 하나 생성한다.
생성된 class에 다음 코드를 작성하고 appKey에 네이티브 앱 키를 작성한다.
package com.example.sociallogin
import android.app.Application
import com.kakao.sdk.common.KakaoSdk
class GlobalApplication: Application() {
override fun onCreate() {
super.onCreate()
KakaoSdk.init(this, "네이티브 앱 키")
}
}
네이티브 앱 키는 '앱 키' 에서 확인할 수 있다.
✅ AndroidManifest.xml 설정
GlobalApplication을 생성했으면 Mainfset에서 GlobalApplication 클래스가 사용될 수 있도록 한다. 아래의 코드를 application 태그 안에 작성하여 애플리케이션 프로세스가 시작될 때, 애플리케이션의 다른 컴포넌트보다 먼저 실행되게 한다.
android:name=".GlobalApplication"
다음으로 로그인 창이 되는 액티비티를 추가한다. 네이티브 앱 키 부분에는 위에 사용했던 네이티브 앱 키를 복붙 하면 된다. 형식은 kakao + 네이티브 앱 키 를 작성해야 한다. kakao를 작성하지 않고 네이티브 앱 키만 작성할 경우 카카오 로그인 창으로 이동이 안될 수 있다.
<activity
android:exported="true"
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네이티브 앱 키" />
</intent-filter>
</activity>
✅ 카카오 로그인 버튼
아래의 링크에서 버튼 이미지를 다운로드할 수 있다. 다운을 받고 res/drawable 폴더에 넣어준다.
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
activity_main.xml에 카카오 로그인 버튼을 생성한다.
<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"
/>
MainActivity
이때 로그인 후 이동해야 하는 액티비티를 하나 만들어야 한다.
자신이 원하는 이름으로 액티비티를 하나 만들고 그 액티비티와 연결시킨다.
package com.example.sociallogin
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import com.example.sociallogin.databinding.ActivityMainBinding
import com.kakao.sdk.auth.LoginClient
import com.kakao.sdk.auth.model.OAuthToken
import com.kakao.sdk.common.model.AuthErrorCause
import com.kakao.sdk.user.UserApiClient
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// 로그인 정보 확인
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 keyHash = Utility.getKeyHash(this)
// Log.d("Hash", keyHash)
val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
if (error != null) {
when {
error.toString() == AuthErrorCause.AccessDenied.toString() -> {
Toast.makeText(this, "접근이 거부 됨(동의 취소)", Toast.LENGTH_SHORT).show()
}
error.toString() == AuthErrorCause.InvalidClient.toString() -> {
Toast.makeText(this, "유효하지 않은 앱", Toast.LENGTH_SHORT).show()
}
error.toString() == AuthErrorCause.InvalidGrant.toString() -> {
Toast.makeText(this, "인증 수단이 유효하지 않아 인증할 수 없는 상태", Toast.LENGTH_SHORT).show()
}
error.toString() == AuthErrorCause.InvalidRequest.toString() -> {
Toast.makeText(this, "요청 파라미터 오류", Toast.LENGTH_SHORT).show()
}
error.toString() == AuthErrorCause.InvalidScope.toString() -> {
Toast.makeText(this, "유효하지 않은 scope ID", Toast.LENGTH_SHORT).show()
}
error.toString() == AuthErrorCause.Misconfigured.toString() -> {
Toast.makeText(this, "설정이 올바르지 않음(android key hash)", Toast.LENGTH_SHORT).show()
}
error.toString() == AuthErrorCause.ServerError.toString() -> {
Toast.makeText(this, "서버 내부 에러", Toast.LENGTH_SHORT).show()
}
error.toString() == AuthErrorCause.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()
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
finish()
}
}
val kakao_login_button = binding.kakaoLoginButton // 로그인 버튼
kakao_login_button.setOnClickListener {
if(LoginClient.instance.isKakaoTalkLoginAvailable(this)){
LoginClient.instance.loginWithKakaoTalk(this, callback = callback)
}else{
LoginClient.instance.loginWithKakaoAccount(this, callback = callback)
}
}
}
}
✅ 로그아웃 버튼, 회원 탈퇴 버튼 생성
로그인을 하면 로그아웃도 필요하고 회원 탈퇴 기능도 필요하다.
그래서 로그인 후 이동되는 액티비티에 로그아웃 버튼과 회원 탈퇴 버튼을 만들었다.
activity_second.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:layout_marginHorizontal="20dp"
android:layout_marginBottom="10dp"
android:backgroundTint="#fee500"
android:paddingVertical="12dp"
android:text="로그아웃"
android:textColor="#181600"
android:textSize="20sp"
android:textStyle="bold"
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:layout_marginHorizontal="20dp"
android:layout_marginBottom="30dp"
android:backgroundTint="#fee500"
android:paddingVertical="12dp"
android:text="회원탈퇴"
android:textColor="#181600"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
SecondActivity.kt
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import com.example.sociallogin.MainActivity
import com.example.sociallogin.databinding.ActivitySecondBinding
import com.kakao.sdk.user.UserApiClient
class SecondActivity : AppCompatActivity() {
private lateinit var binding: ActivitySecondBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySecondBinding.inflate(layoutInflater)
setContentView(binding.root)
val kakao_logout_button = binding.kakaoLogoutButton // 로그아웃 버튼
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 = binding.kakaoUnlinkButton // 회원 탈퇴 버튼
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()
}
}
}
}
}
✅ 카카오 설정 활성화
코드를 작성하고 실행하기 전에 카카오 로그인 설정을 활성화시켜줘야 정상적으로 실행시킬 수 있다.
카카오계정
accounts.kakao.com
✅ 사용자 정보 조회
위 링크를 통해 아래 창을 들어가서 자신이 필요한 정보를 동의를 구해 불러온다.
닉네임과 이메일을 예시로 하여 불러올 것이다.
동의 항목 설정은 위 창과 같이 설정하면 된다.
이제 정보를 받아올 액티비티와 레이아웃을 수정해야 하는데 로그인 후 실행되는 액티비티를 수정한다.
activity_second.xml
<TextView
android:id="@+id/nickname"
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_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="60dp"
android:layout_marginTop="15dp"
android:text="이메일: "
android:textColor="#181600"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/nickname" />
SecondActivity.kt
다음 액티비티 코드를 onCreate에 작성한다.
val nickname = binding.nickname // 닉네임
UserApiClient.instance.me { user, error ->
nickname.text = "닉네임: ${user?.kakaoAccount?.profile?.nickname}"
}
val email = binding.email // 이메일
UserApiClient.instance.me { user, error ->
email.text = "이메일: ${user?.kakaoAccount?.email}"
}
✅ 결과물
참고)
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com