본문 바로가기
안드로이드 자바

[JAVA][Android] Kakao 로그인 API 사용하기

by teamnova 2023. 3. 6.
728x90

카카오 로그인 api 사용에 앞서 Android SDK를 사용하기 위한 최소 요구 사양 입니다.

https://developers.kakao.com/console/app

 

카카오계정

 

accounts.kakao.com

 

1. 내 어플리케이션 등록하기

위의 링크로 들어가 내 어플리케이션 먼저 등록해줍니다.

 

사이트 상단에 내어플리케이션을 선택한 후 추가하기를 통해 내 어플리케이션을 추가하겠습니다.

앱이름과 사업자명을 작성해주세요. 앱아이콘 설정은 선택입니다. 

 

어플을 등록하면 아래와 같은 앱키를 확인할 수 있습니다.

여기서 네이트브 앱키만 기억해주세요.

 

2. 카카오 로그인 활성화 & 동의항목 설정해주기

내 어플리케이션 -> 제품 설정 -> 카카오로그인 에 들어가 상태를 On으로 변경해줍니다.

 

동의 항목 설정도 해줍니다.

해당 포스팅에서는 닉네임, 프로필 사진, 연령대, 카카오 계정 항목을 설정해주겠습니다.

 

3. 플랫폼 등록하기

내 어플리케이션 -> 앱설정 -> 플랫폼 으로 들어가 플랫폼을 설정합니다.

Android 플랫폼으로 설정해줘야 합니다.

본인의 프로젝트명을 입력하고 키해시를 입력해줍니다.

 

+ 키 해시 알아내는 법

키 해시(Key Hash)란 인증서(Certificate)의 인증서 지문 값(Certificate fingerprints)을 해시(hash)한 값으로, 악성 앱인지 판별하는 데 사용됩니다. 카카오 API를 호출하면 카카오 API 서버가 요청 헤더에 추가된 키 해시값과 카카오 플랫폼에 등록한 값이 일치하는지 확인합니다. 키 해시는 디버그 키 해시(Debug key hash)와 릴리즈 키 해시(Release key hash) 두 가지가 있습니다.

  • 디버그 키 해시: 프로젝트를 처음 생성하거나 디버그할 때, 안드로이드 스튜디오에서 개발 환경에 맞게 자동으로 생성되는 디버그 인증서 에서 해시(hash)한 값입니다.
  • 릴리즈 키 해시: 앱 스토어에 앱을 배포하기 위해 생성한 릴리즈 인증서로부터 해시한 값입니다.

공식 홈페이지에서는 키 해시를 알아내기 위한 3가지의 방법이 있으나 2번쨰 방법인 kakao SDK를 이용하는 방법을 사용하겠습니다.

1. 터미널을 이용해 티버그, 릴리즈 키 해시 생성하기

2. kakao SDK를 이용해 디버그, 릴리즈 키 해시 확인하기

3. google play console에서 릴리즈 키 해시 구하기.

 

PackageInfo packageInfo = null;
try {
    packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}
if (packageInfo == null)
    Log.e("KeyHash", "KeyHash:null");

for (Signature signature : packageInfo.signatures) {
    try {
        MessageDigest md = MessageDigest.getInstance("SHA");
        md.update(signature.toByteArray());
        Log.d("KeyHash", Base64.encodeToString(md.digest(), Base64.DEFAULT));
    } catch (NoSuchAlgorithmException e) {
        Log.e("KeyHash", "Unable to get MessageDigest. signature=" + signature, e);
    }
}

 위와 같이 코드를 작성하고 프로젝트를 실행하게 되면 로그를 통해 해시 값을 획득할 수 있습니다.

이때 획득한 키 해시를 플랫폼 작성칸에 입력해줍니다.

 

4. 매니페스트, 클래스에서 초기화해주기

KakaoApplication이라는 클래스를 생성해 초기화를 진행합니다.

 

public class KakaoApplication extends Application {
    private static KakaoApplication instance;

    @Override
    public void onCreate() {
        super.onCreate();
        KakaoSdk.init(this,"{NATIVE_APP_KEY}");
    }
}

{NATIVE_APP_KEY}에는 내 어플리케이션 등록할때 발급받은 네이티브 앱 키를 넣어주면 됩니다.

 

다음으로 매니페스트에는 kakao 로그인 화면으로 이동하기 위한 kakao.sdk에 존재하는 AuthCodeHandler를 추가해줍니다. android:scheme에 들어가는 string 값은 kakao+ native 앱 키입니다.

 

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

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

또한 application 태그 안에도 kakao SDK 초기화를 수행한 클래스의 이름을 설정해야 합니다.


<application
    android:name=".KakaoApplication"

kakaoApplication 클래스에서 초기화를 했으므로 위와같이 코드를 추가해주면 됩니다.

 

5. 레이아웃 만들기

먼저 (문서> 유용한 참고 정보 > 디자인 가이드) 로 가서 카카오 버튼 이미지를 다운받아 줍니다.

https://developers.kakao.com/docs/latest/ko/reference/design-guide

 

Kakao Developers

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

developers.kakao.com

<LinearLayout 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=".KakaoLogin"
    android:orientation="vertical">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/profile"
            android:layout_width="200dp"
            android:layout_height="200dp"
            />

        <TextView
            android:id="@+id/nickname"
            android:textSize="20sp"
            android:textColor="@color/black"

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>


    <ImageView
        android:id="@+id/login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/kakao_login_medium_narrow"
        android:layout_marginBottom="30dp"
        />


    <Button
        android:id="@+id/logout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="로그아웃"
        android:visibility="gone"
        />



</LinearLayout>

6. 액티비티 작성하기

 


import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.google.android.gms.common.internal.TelemetryLoggingClient;
import com.kakao.sdk.auth.model.OAuthToken;
import com.kakao.sdk.user.UserApiClient;
import com.kakao.sdk.user.model.User;

import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import kotlin.jvm.functions.Function2;

public class KakaoLogin extends AppCompatActivity {

    private static final String TAG = "KakaoLogin";
    private View loginButton, logoutButton;
    private TextView nickName;
    private ImageView profileImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_kakao_login);

        loginButton = findViewById(R.id.login);
        logoutButton = findViewById(R.id.logout);
        nickName = findViewById(R.id.nickname);
        profileImage = findViewById(R.id.profile);

        // 카카오톡이 설치되어 있는지 확인하는 메서드 , 카카오에서 제공함. 콜백 객체를 이용합.
        Function2<OAuthToken,Throwable,Unit> callback =new Function2<OAuthToken, Throwable, Unit>() {
            @Override
            // 콜백 메서드 ,
            public Unit invoke(OAuthToken oAuthToken, Throwable throwable) {
                Log.e(TAG,"CallBack Method");
                //oAuthToken != null 이라면 로그인 성공
                if(oAuthToken!=null){
                    // 토큰이 전달된다면 로그인이 성공한 것이고 토큰이 전달되지 않으면 로그인 실패한다.
                    updateKakaoLoginUi();

                }else {
                    //로그인 실패
                    Log.e(TAG, "invoke: login fail" );
                }

                return null;
            }
        };

        // 로그인 버튼 클릭 리스너
        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                
                // 해당 기기에 카카오톡이 설치되어 있는 확인
               if(UserApiClient.getInstance().isKakaoTalkLoginAvailable(KakaoLogin.this)){
                   UserApiClient.getInstance().loginWithKakaoTalk(KakaoLogin.this, callback);
               }else{
                   // 카카오톡이 설치되어 있지 않다면
                   UserApiClient.getInstance().loginWithKakaoAccount(KakaoLogin.this, callback);
               }
            }
        });

        // 로그아읏 버튼 
        logoutButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                UserApiClient.getInstance().logout(new Function1<Throwable, Unit>() {
                    @Override
                    public Unit invoke(Throwable throwable) {
                        updateKakaoLoginUi();
                        return null;
                    }
                });
            }
        });

        updateKakaoLoginUi();
    }

    private void updateKakaoLoginUi() {

        // 로그인 여부에 따른 UI 설정 
        UserApiClient.getInstance().me(new Function2<User, Throwable, Unit>() {
            @Override
            public Unit invoke(User user, Throwable throwable) {

                if (user != null) {

                    // 유저의 아이디
                    Log.d(TAG, "invoke: id =" + user.getId());
                    // 유저의 이메일
                    Log.d(TAG, "invoke: email =" + user.getKakaoAccount().getEmail());
                    // 유저의 닉네임
                    Log.d(TAG, "invoke: nickname =" + user.getKakaoAccount().getProfile().getNickname());
                    // 유저의 성별
                    Log.d(TAG, "invoke: gender =" + user.getKakaoAccount().getGender());
                    // 유저의 연령대
                    Log.d(TAG, "invoke: age=" + user.getKakaoAccount().getAgeRange());


                    // 유저 닉네임 세팅해주기
                    nickName.setText(user.getKakaoAccount().getProfile().getNickname());
                    // 유저 프로필 사진 세팅해주기
                    Glide.with(profileImage).load(user.getKakaoAccount().getProfile().getThumbnailImageUrl()).circleCrop().into(profileImage);
                    Log.d(TAG, "invoke: profile = "+user.getKakaoAccount().getProfile().getThumbnailImageUrl());

                    // 로그인이 되어있으면
                    loginButton.setVisibility(View.GONE);
                    logoutButton.setVisibility(View.VISIBLE);
                } else {
                    // 로그인 되어있지 않으면
                    nickName.setText(null);
                    profileImage.setImageBitmap(null);

                    loginButton.setVisibility(View.VISIBLE);
                    logoutButton.setVisibility(View.GONE);
                }
                return null;
            }
        });
    }
}

 

예제 영상입니다.