본문 바로가기

안드로이드/자바

[안드로이드/Android] 카카오톡 로그인 연동

반응형

최초 작성 17.08.25

최종 수정 19.05.27 ( removeCallback 추가 ) 

 

이번 포스팅에서는 카카오톡 로그인을 연동입니다. 새로운 앱들을 사용하다보면, 회원가입 자체가 유저들에게 진입장벽으로 작용해 많은 앱들이 신규 회원가입보단 SNS 연동을 통해 회원정보를 가져오는 방법을 선택하고 있습니다. 카카오톡 이외에도 많은 SNS가 있지만, 추후에 작성하도록 하겠습니다.

 

앱 생성

카카오톡 로그인을 사용하기 위해선 카카오 디벨로퍼 싸이트에서 앱을 생성해야합니다. KakaoDevelpoer링크를 통해 로그인을 하면 아래 사진과 같이 앱만들기를 선택할 수 있습니다. 

앱 생성후 처음 나오는 화면에서 네이티브 앱키를 알 수 있습니다. 해당 키는 SDK 사용에 필요한 정보이며, 나중에 설정 화면에서도 확인하실 수 있습니다.

플랫폼추가

플랫폼은 Android, Ios,  웹을 선택할 수 있지만 해당 포스팅은 안드로이드 환경에서 진행되고 있기 때문에 안드로이드를 선택후 패키지명을 입력하면 마켓 Url을 자동으로 채워집니다.

키해시 등록

카카오 API콜을 수행하려면 앱별 키해시를 등록해야 합니다. 해당 키해시를 통해 악의적인 앱인지 아닌지를 판별하는데 쓰인다고 합니다. 키해시는 앱마다 갖고 있는 고유키라고 생각하시면 됩니다. 프로젝트의 키해시를 얻는 방법은 2가지가 있습니다.

 

-commandline으로 키해시 구하기

아래와 같은 코드를 터미널(맥환경)에 입력합니다.

keytool -exportcert -alias androiddebugkey -keystore <debug_keystore_path> -storepass android -keypass android | openssl sha1 -binary | openssl base64

여기서 debug_keystroe_path는 실제 최소 한번의 디버그 이후 생성된 apk 경로를 적어주셔야합니다. ( /users/wony/.../app/outputs/apk/ )

 

-소스코드로 키해시 구하기

private void getHashKey(){
    try {
        PackageInfo info = getPackageManager().getPackageInfo("패키지이름", PackageManager.GET_SIGNATURES);
        for (Signature signature : info.signatures) {
            MessageDigest md = MessageDigest.getInstance("SHA");
            md.update(signature.toByteArray());
            Log.d(TAG,"key_hash="+Base64.encodeToString(md.digest(), Base64.DEFAULT));
        }
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

※위 2가지 방법중 후자인 소스코드를 선호합니다. 무슨 영문에서인지 전자의 방법은 후자와 결과값이 다르고, 제대로 작동을 하지 않습니다.

이렇게 생성한 해키시는 생성한 앱의 플랫폼 정보에 작성합니다.

사용자 관리 추가

사용자 관리 기능을 사용하기 위해서 설정/사용자 관리에서 아래와 같이 추가 설정을 합니다. 개인정보 보호항목에서 얻고자 하는 목록을 사용안함에서 원하는 항목으로 변경합니다. 그리고 수집목적을 필수로 작성하여, 사용자가 카카오계정 로그인할 경우 해당 수집목적을 나타내 사용자의 동의를 얻습니다.

이제 생성한 프로젝트를 수정해, SDK를 사용하기 위한 환경으로 설정하도록 하겠습니다.

SDK 추가

gradle ( project )

allprojects {

	repositories {
		jcenter()
		//kakao
		mavenCentral()
		maven { url 'http://devrepo.kakao.com:8088/nexus/content/groups/public/' }
	}
}

gradle.properties

KAKAO_SDK_GROUP=com.kakao.sdk
KAKAO_SDK_VERSION=1.1.7

gradle ( app )

dependencies {
.....
	// 카카오 로그인 sdk를 사용하기 위해 필요.
	compile group: project.KAKAO_SDK_GROUP, name: 'usermgmt', version: project.KAKAO_SDK_VERSION
}

kakao_string.xml

res/values/ 에 리소스 파일을 만들고 네이티브 앱키를 채워줍니다.

<resources>
    <string name="kakao_app_key">native app key</string>
</resources>

AndroidManifest.xml

서버와의 통신을 위해 network 권한을 설정합니다. 해당 코드를 통해 앱에서 인터넷 사용이 가능합니다. 그리고 위 단계에서 추가한 네이티브 앱 키를 메타데이터로 설정합니다.

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

<application
    ...
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <meta-data
        android:name="com.kakao.sdk.AppKey"
        android:value="@string/kakao_app_key" />
</application>

소스코드

GlobalApplication.java

public class GlobalApplication extends Application {

    private static volatile GlobalApplication obj = null;
    private static volatile Activity currentActivity = null;

    @Override
    public void onCreate() {
        super.onCreate();
        obj = this;
        KakaoSDK.init(new KakaoSDKAdapter());
    }

    public static GlobalApplication getGlobalApplicationContext() {
        return obj;
    }

    public static Activity getCurrentActivity() {
        return currentActivity;
    }

    // Activity가 올라올때마다 Activity의 onCreate에서 호출해줘야한다.
    public static void setCurrentActivity(Activity currentActivity) {
        GlobalApplication.currentActivity = currentActivity;
    }
}

KakaoSDKAdapter.java

public class KakaoSDKAdapter extends KakaoAdapter {
    /**
     * Session Config에 대해서는 default값들이 존재한다.
     * 필요한 상황에서만 override해서 사용하면 됨.
     * @return Session의 설정값.
     */
    @Override
    public ISessionConfig getSessionConfig() {
        return new ISessionConfig() {
            @Override
            public AuthType[] getAuthTypes() {
                return new AuthType[] {AuthType.KAKAO_ACCOUNT};
            }

            @Override
            public boolean isUsingWebviewTimer() {
                return false;
            }


            @Override
            public ApprovalType getApprovalType() {
                return ApprovalType.INDIVIDUAL;
            }

            @Override
            public boolean isSaveFormData() {
                return true;
            }
        };
    }

    @Override
    public IApplicationConfig getApplicationConfig() {
        return new IApplicationConfig() {
            @Override
            public Activity getTopActivity() {
                return GlobalApplication.getCurrentActivity();
            }

            @Override
            public Context getApplicationContext() {
                return GlobalApplication.getGlobalApplicationContext();
            }
        };
    }
}

Androidmanifest.xml

<application
android:name=".GlobalApplication"
..>

SessionCallBack.java

private class SessionCallback implements ISessionCallback {

        @Override
        public void onSessionOpened() {

            UserManagement.requestMe(new MeResponseCallback() {

                @Override
                public void onFailure(ErrorResult errorResult) {
                    String message = "failed to get user info. msg=" + errorResult;

                    ErrorCode result = ErrorCode.valueOf(errorResult.getErrorCode());
                    if (result == ErrorCode.CLIENT_ERROR_CODE) {
                        //에러로 인한 로그인 실패
//                        finish();
                    } else {
                        //redirectMainActivity();
                    }
                }

                @Override
                public void onSessionClosed(ErrorResult errorResult) {
                }

                @Override
                public void onNotSignedUp() {

                }

                @Override
                public void onSuccess(UserProfile userProfile) {
                    //로그인에 성공하면 로그인한 사용자의 일련번호, 닉네임, 이미지url등을 리턴합니다.
                    //사용자 ID는 보안상의 문제로 제공하지 않고 일련번호는 제공합니다.

//                    Log.e("UserProfile", userProfile.toString());
//                    Log.e("UserProfile", userProfile.getId() + "");


                    long number = userProfile.getId();


                }
            });

        }

        @Override
        public void onSessionOpenFailed(KakaoException exception) {
            // 세션 연결이 실패했을때
            // 어쩔때 실패되는지는 테스트를 안해보았음 ㅜㅜ

        }
    }

로그인 기능 구현 엑티비티

(19.05.27 추가) Callback은 엑티비티가 끝나는 시점에 removeCallback을 해주지 않으면, 로그인 onSuccess등이 다중 실행될수 있습니다.

    SessionCallback callback;

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

        callback = new SessionCallback();
        Session.getCurrentSession().addCallback(callback);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Session.getCurrentSession().removeCallback(kakaoCallbackManager);
    }

엑티비티 레이아웃

<com.kakao.usermgmt.LoginButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="10dp"/>

이후에 해당 앱을 실행해 테스트해보면 로그인이 성공해서 해당 계정에 정보를 얻어서 콜백 클래스에서 처리 해주시면 됩니다.

유저정보 가져오기

많은 앱들이 최초 로그인 이후 자동로그인 기능을 제공하는데, 카카오 또한 해당 메소드를 사용해서 자동로그인 기능을 사용할 수 있을것 같습니다. 로그인 화면 및 메인화면등의 해당 메소드로 유저정보에 대한 캐시가 남아 있으면 처리합니다.

public void requestMe() {
        //유저의 정보를 받아오는 함수

        UserManagement.requestMe(new MeResponseCallback() {
            @Override
            public void onFailure(ErrorResult errorResult) {
                Log.e(TAG, "error message=" + errorResult);
//                super.onFailure(errorResult);
            }

            @Override
            public void onSessionClosed(ErrorResult errorResult) {

                Log.d(TAG, "onSessionClosed1 =" + errorResult);
            }

            @Override
            public void onNotSignedUp() {
                //카카오톡 회원이 아닐시
                Log.d(TAG, "onNotSignedUp ");

            }

            @Override
            public void onSuccess(UserProfile result) {
                Log.e("UserProfile", result.toString());
                Log.e("UserProfile", result.getId() + "");
            }
        });
    }

 

이상으로 카카오톡 로그인 연동 포스팅을 마침니다. 

문의사항 및 이의사항에 대해서는 댓글이나 방명록으로 남겨주시면 확인후 처리하겠습니다.

감사합니다.

 

 

ps. UserProfile 데이터에서 얻을수 있는 정보 

 

 

 

 

 

참조

KakaoDevelopers

반응형