Android Open Source - kakao-android-sdk-standalone Session






From Project

Back to project page kakao-android-sdk-standalone.

License

The source code is released under:

Apache License

If you think the Android project kakao-android-sdk-standalone listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Copyright 2014 Minyoung Jeong <kkungkkung@gmail.com>
 * Copyright 2014 Kakao Corp./*from  w  ww  . java2s  .c  o  m*/
 *
 * Redistribution and modification in source or binary forms are not permitted without specific prior written permission.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.kakao;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;

import com.kakao.authorization.AuthorizationResult;
import com.kakao.authorization.accesstoken.AccessToken;
import com.kakao.authorization.accesstoken.AccessTokenRequest;
import com.kakao.authorization.authcode.AuthorizationCode;
import com.kakao.authorization.authcode.AuthorizationCodeRequest;
import com.kakao.exception.KakaoException;
import com.kakao.exception.KakaoException.ERROR_TYPE;
import com.kakao.helper.Logger;
import com.kakao.helper.SharedPreferencesCache;
import com.kakao.helper.Utility;

import java.util.ArrayList;
import java.util.List;

/**
 * ????? ???? ?? ???? ???? access token??? ????.
 * @author MJ
 */
public class Session {
    private static Session currentSession;
    private static final String APP_KEY_PROPERTY = "com.kakao.sdk.AppKey";
    private static final String REDIRECT_URL_PREFIX = "kakao";
    private static final String REDIRECT_URL_POSTFIX = "://oauth";


    private final Context context;
    private final String appKey;
    private final String redirectUri;
    private final SharedPreferencesCache appCache;
    private final List<SessionCallback> sessionCallbacks;
    private final Handler sessionCallbackHandler;

    private final Object INSTANCE_LOCK = new Object();
    // ?? ????? ?????? ??? INSTANCE_LOCK??? ??? ???.
    private SessionState state;
    // close? ??
    private RequestType requestType;
    private AuthorizationCode authorizationCode;
    private AccessToken accessToken;

    /**
     * ????? ???? ??? ????? ?????, ???? ??????? ???????? ????? ??????.
     * ???? ????? ??? ? ????.
     * opened ??? : ???? acitivity?
     * closed ??? : ???? action??? ?? open ????
     * opening ??? : ???? ?? ????
     * @param context ????? ???? context. ??? ?? app key? redirect uri? ????.
     * @param sessionCallback ???? ????? ??? ? ????? ??? ?? ??
     */
    public static synchronized boolean initializeSession(final Context context, final SessionCallback sessionCallback) {
        if (currentSession == null) {
            currentSession = new Session(context);
        }
        return currentSession.implicitOpen(sessionCallback);
    }

    /**
     * ???? ????? ???? ??? ????.
     * ???? ????? background? ????? ??????? ????.
     * @param sessionCallback ????? ????????? ? ?????? ??
     * @return ???? ????? ??? ?? true, ???? ????? ?? ???? false? return ??.
     */
    public boolean implicitOpen(final SessionCallback sessionCallback) {
        if (currentSession.isOpening() && currentSession.accessToken.hasRefreshToken()) {
            open(sessionCallback);
            return true;
        } else {
            return false;
        }
    }

    /**
     * ?? ????? ????.
     * @return ?? ?? ???
     */
    public static synchronized Session getCurrentSession() {
        if(currentSession == null)
            throw new IllegalStateException("Session is not initialized. Use Session#initializeSession(Context ,SessionCallback) in login process.");
        return currentSession;
    }

    /**
     * ?? ????? ????.
     * {@link SessionState#OPENED} ??????? ?? ??.
     * {@link SessionState#CLOSED} ??????? authorization code ??. ???/??? {@link SessionState#CLOSED}
     * {@link SessionState#OPENING} ??????? code ??? refresh token ??????  access token ??? ????. ???/??? {@link SessionState#CLOSED}, refresh ?????? {@link SessionState#OPENING} ??.
     * param?? ???? ???? ? ??? ????.
     * @param sessionCallback ?? ??? ???? ??
     */
    public void open(final SessionCallback sessionCallback) {
        // ???? open??? ???? ??.
        if (getState().isOpened()) {
            return;
        }

        addCallback(sessionCallback);

        //????? ???? request? ??.
        if(getRequestType() != null){
            Logger.getInstance().d(getRequestType() + " is still doing.");
            return;
        }
        try {
            checkLoginActivity();
            synchronized (INSTANCE_LOCK){
                switch (state) {
                    case CLOSED:
                        if (appKey != null && redirectUri != null) {
                            this.requestType = RequestType.GETTING_AUTHORIZATION_CODE;
                            final AuthorizationCodeRequest authorizationCodeRequest = AuthorizationCodeRequest.createNewRequest(appKey, redirectUri);
                            requestLogin(getLoginActivityIntent(authorizationCodeRequest));
                        } else {
                            internalClose(new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "can not request authorization code because appKey or redirectUri is invalid."), false);
                        }
                        break;
                    case OPENING:
                        if(accessToken.hasRefreshToken()){
                            this.requestType = RequestType.REFRESHING_ACCESS_TOKEN;
                            final  AccessTokenRequest accessTokenRequest = AccessTokenRequest.createRequestWithRefreshToken(context, appKey, redirectUri, accessToken.getRefreshTokenString());
                            requestLogin(getLoginActivityIntent(accessTokenRequest));
                        } else if(authorizationCode.hasAuthorizationCode()){
                            this.requestType = RequestType.GETTING_ACCESS_TOKEN;
                            final AccessTokenRequest accessTokenRequest = AccessTokenRequest.createRequestWithAuthorizationCode(context, appKey, redirectUri, authorizationCode.getAuthorizationCode());
                            requestLogin(getLoginActivityIntent(accessTokenRequest));
                        } else {
                            internalClose(new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "can not request access token because both authorization code and refresh token are invalid."), false);
                        }
                        break;
                    default:
                        throw new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "current session state is not possible to open. state = " + state);
                }
            }
        } catch (KakaoException e) {
            internalClose(e, false);
        }
    }

    /**
     * ???? ?? close(????/??). request? ??? ????? ??? ??? ?? ????.
     * token??? ???? ???? authorization code??(????? ??) ?? ??? ????? open ????.
     * @param sessionCallback close ??? ???? ?? callback
     */
    public void close(final SessionCallback sessionCallback) {
        if(sessionCallback != null)
            addCallback(sessionCallback);

        internalClose(null, true);
    }

    /**
     * ?? ????? ??? ?? access token??? ????? ??? ????? ???? ????.
     * ???????? opened ???? ?? opening???? ??????.
     * @return ????? ???
     */
    public final SessionState checkState() {
        synchronized (INSTANCE_LOCK) {
            if(state.isOpened() && !accessToken.hasValidAccessToken()){
                synchronized (INSTANCE_LOCK) {
                    state = SessionState.OPENING;
                    requestType = null;
                    authorizationCode = AuthorizationCode.createEmptyCode();
                }
            }
            return state;
        }
    }

    /**
     * ?? ????? ???
     * @return ????? ???
     */
    public SessionState getState() {
        synchronized (INSTANCE_LOCK) {
            return state;
        }
    }

    /**
     * ?? ????? ?? ??????? ??? ????.
     * @return ????? ?? ??????? true, ????? ?? false? ????.
     */
    public final boolean isOpened() {
        final SessionState state = checkState();
        return state == SessionState.OPENED;
    }

    private boolean isOpening() {
        final SessionState state = checkState();
        return state == SessionState.OPENING;
    }

    /**
     * ?? ????? ?? ??????? ??? ????.
     * @return ????? ?? ??????? true, ????? ?? false? ????.
     */
    public final boolean isClosed() {
        final SessionState state = checkState();
        return state == SessionState.CLOSED;
    }

    /**
     * ?? ?? ???? ?? ??
     * @return ?? ?? ???? ?? ??
     */
    public final RequestType getRequestType() {
        synchronized (INSTANCE_LOCK) {
            return requestType;
        }
    }

    /**
     * ?? ????? ??? ?? access token??? ????.
     * @return access token
     */
    public final String getAccessToken() {
        synchronized (INSTANCE_LOCK) {
            return (accessToken == null) ? null : accessToken.getAccessTokenString();
        }
    }

    /**
     * ? ???? ????.
     * @return ? ???
     */
    public static SharedPreferencesCache getAppCache() {
        final Session session = Session.getCurrentSession();
        return session.appCache;
    }

    /**
     * authorization code ??? ?? ????. (authcode ??, state ??, accesstoken??)
     */
    public void onAuthCodeCompleted(final AuthorizationResult result) {
        AuthorizationCode authCode = null;
        KakaoException exception = null;
        if(getRequestType() == null){
            exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "session is closed during requesting authorization code. result will be ignored. state = " + getState());
        } else if (result == null) {
            exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "the result of authorization code request is null.");
        } else {
            final String resultRedirectURL = result.getRedirectURL();
            if(result.isSuccess()){
                // ?? ???? redirect uri ????
                if (resultRedirectURL != null && resultRedirectURL.startsWith(redirectUri)) {
                    authCode = AuthorizationCode.createFromRedirectedUri(result.getRedirectUri());
                    // authorization code? ???????? ????
                    if (!authCode.hasAuthorizationCode()) {
                        authCode = null;
                        exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "the result of authorization code request does not have authorization code.");
                    }
                // ?? ???? redirect uri ?????
                } else {
                    exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "the result of authorization code request mismatched the registered redirect uri. msg = " + result.getResultMessage());
                }
            } else if (result.isCanceled()) {
                exception = new KakaoException(ERROR_TYPE.CANCELED_OPERATiON, result.getResultMessage());
            } else {
                exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, result.getResultMessage());
            }
        }

        synchronized (INSTANCE_LOCK) {
            final SessionState previousState = state;
            if (authCode != null) {
                this.authorizationCode = authCode;
                state = SessionState.OPENING;
                // log? ??? callback??? ?????? ???.
                onStateChange(previousState, state, requestType, null, false);
                //  request? ?????? ?????? request? reset
                requestType = null;
            } else {
                internalClose(exception, false);
                return;
            }
        }
        // request AccessToken
        open(null);
    }

    /**
     * access token ??? ?? ????. (access token ??, state ??)
     */
    public void onAccessTokenCompleted(final AuthorizationResult result) {
        AccessToken resultAccessToken = null;
        KakaoException exception = null;
        if(getRequestType() == null){
            exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "session is closed during requesting access token. result will be ignored. state = " + getState());
        } else if (result == null) {
            exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "the result of access token request is null.");
        } else {
            if (result.isSuccess()) {
                resultAccessToken = result.getAccessToken();
                if (!resultAccessToken.hasValidAccessToken()) {
                    resultAccessToken = null;
                    exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "the result of access token request is invalid access token.");
                }
            } else if (result.isCanceled()) {
                exception = new KakaoException(ERROR_TYPE.CANCELED_OPERATiON, result.getResultMessage());
            } else {
                exception = new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, result.getResultMessage());
            }
        }

        synchronized (INSTANCE_LOCK) {
            final SessionState previousState = state;
            if (resultAccessToken != null) {
                // refresh ????? refresh token??? ???? ???? ? ???? accessToken = resultAccessToken??? ?? ?????.
                accessToken.updateAccessToken(resultAccessToken);
                //authorization code? ?? ??? ???? ???.
                authorizationCode = AuthorizationCode.createEmptyCode();
                saveTokenToCache(accessToken);
                state = SessionState.OPENED;
                onStateChange(previousState, state, requestType, null, false);
                requestType = null;
            } else {
                // refresh token?? ??????? ??? ? ??? ?????? ?? refresh token??? ??? ? ???? close??? ???.
                if(!(getRequestType().isRefreshingTokenRequest() && exception.isCancledOperation())){
                    internalClose(exception, false);
                }
            }
        }
    }

    private Session(final Context context){
        if(context == null)
            throw new KakaoException(ERROR_TYPE.ILLEGAL_ARGUMENT, "cannot create Session without Context.");

        this.context = context;
        this.appKey = Utility.getMetadata(context, APP_KEY_PROPERTY);
        if(appKey == null)
            throw new KakaoException(ERROR_TYPE.MISS_CONFIGURATION, String.format("need to declare %s in your AndroidManifest.xml", APP_KEY_PROPERTY));
        this.redirectUri = REDIRECT_URL_PREFIX + this.appKey + REDIRECT_URL_POSTFIX;
        this.appCache = new SharedPreferencesCache(context, appKey);
        this.sessionCallbacks = new ArrayList<SessionCallback>();
        this.sessionCallbackHandler = new Handler(Looper.getMainLooper()); //?? callback??? main thread??? ?????????? ??.

        final Bundle loadedFromCache = appCache.load();
        synchronized (INSTANCE_LOCK) {
            authorizationCode = AuthorizationCode.createEmptyCode();
            accessToken = AccessToken.createFromCache(loadedFromCache);
            if (accessToken.hasValidAccessToken()) {
                this.state = SessionState.OPENED;
            } else if (accessToken.hasRefreshToken()) {
                this.state = SessionState.OPENING;
            } else {
                this.state = SessionState.CLOSED;
                internalClose(null, false);
            }
        }
    }

    /**
     * @param callback ??? ?? ??
     */
    private void addCallback(final SessionCallback callback) {
        synchronized (sessionCallbacks) {
            if (callback != null && !sessionCallbacks.contains(callback)) {
                sessionCallbacks.add(callback);
            }
        }
    }

    private void removeCallbacks(final List<SessionCallback> sessionCallbacksToBeRemoved) {
        synchronized (sessionCallbacks) {
            sessionCallbacks.removeAll(sessionCallbacksToBeRemoved);
        }
    }

    private void checkLoginActivity() throws KakaoException {
        Intent intent = new Intent();
        intent.setClass(context, LoginActivity.class);
        if (!resolveIntent(intent)) {
            throw new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, String.format("need to declare %s as an activity in your AndroidManifest.xml",
                LoginActivity.class.getName()));
        }
    }

    private boolean resolveIntent(final Intent intent) {
        final ResolveInfo resolveInfo = Utility.resolveIntent(context, intent);
        return resolveInfo != null;
    }

    private Intent getLoginActivityIntent(final AuthorizationCodeRequest authCodeRequest) {
        final Intent intent = new Intent(context, LoginActivity.class);
        intent.putExtra(LoginActivity.CODE_REQUEST_KEY, authCodeRequest);
        return intent;
    }

    private Intent getLoginActivityIntent(final AccessTokenRequest accessTokenRequest) {
        final Intent intent = new Intent(context, LoginActivity.class);
        intent.putExtra(LoginActivity.TOKEN_REQUEST_KEY, accessTokenRequest);
        return intent;
    }

    private void requestLogin(final Intent intent) {
        boolean found = startLoginActivity(intent);
        if (!found) {
            internalClose(new KakaoException(ERROR_TYPE.AUTHORIZATION_FAILED, "failed to find LoginActivity"), false);
        }
    }

    private boolean startLoginActivity(final Intent intent) {
        try {
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            return false;
        }
        return true;
    }

    /**
     * ????? close?? ?????? ??? ?? open??? ????.
     * @param kakaoException  exception??? ????? close?? ?? ?? exception??? ???.
     * @param forced ?? close ??. ?? close???? ???? close? ???????? callback??? ????.
     */
    private void internalClose(final KakaoException kakaoException, final boolean forced) {
        synchronized (INSTANCE_LOCK) {
            final SessionState previous = state;
            state = SessionState.CLOSED;
            requestType = null;
            authorizationCode = AuthorizationCode.createEmptyCode();
            accessToken = AccessToken.createEmptyToken();
            onStateChange(previous, state, requestType, kakaoException, forced);
        }
        if (this.appCache != null) {
            this.appCache.clearAll();
        }
        // ?? ??????? cookie? ???? ??? CookieManager? ???? cookie? ? app?? ?? cookie?? ??? ????? ?????.
        // CookieManager? ??? CookieSyncManager? ???? ?? ??? ??.
        CookieSyncManager.createInstance(context.getApplicationContext());
        CookieManager.getInstance().removeAllCookie();
    }

    private void saveTokenToCache(final AccessToken newToken) {
        if (newToken != null && appCache != null) {
            newToken.saveAccessTokenToCache(appCache);
        }
    }

    private void onStateChange(final SessionState previousState, final SessionState newState,
                               final RequestType requestType, final KakaoException exception,
                               boolean forced) {
        if (!forced && (previousState == newState) && exception == null) {
            return;
        }

        Logger.getInstance().d(String.format("Session State changed : %s -> %s \n ex = %s, request_type = %s",previousState, newState ,(exception != null ? ", ex=" + exception.getMessage() : ""), requestType));

        // ??????? opening??? state? ??? ??? ???.
        if( newState.isOpening())
            return;

        final List<SessionCallback> dumpSessionCallbacks = new ArrayList<SessionCallback>(sessionCallbacks);
        Runnable runCallbacks = new Runnable() {
            public void run() {
                for(SessionCallback callback : dumpSessionCallbacks){
                    if (newState.isOpened())
                        callback.onSessionOpened();
                    else if (newState.isClosed())
                        callback.onSessionClosed(exception);

                }
                removeCallbacks(dumpSessionCallbacks);
            }
        };
        //?? callback??? main thread??? ?????????? ??.
        sessionCallbackHandler.post(runCallbacks);
    }

    /**
     * @author MJ
     */
    private static enum SessionState {
        /**
         * memory? cache?? session ??? ?? ?? ???.
         * ???? session?? ??? ? ??? session??? close(?? ?? ????, ??)? ???.
         * open({@link com.kakao.Session.RequestType#GETTING_AUTHORIZATION_CODE}) : ?? - {@link #OPENING}, ?? - ??? CLOSED
         * close(???? close) : ??? CLOSED
         */
        CLOSED,
        /**
         * {@link #CLOSED}?????? token??? ?? ?? ?? authorization code? ?? ?? valid? authorization code? ??? ?? ???.
         * ??? ??????? ???????? refresh token??? ??? ?? ???.
         * open({@link com.kakao.Session.RequestType#GETTING_ACCESS_TOKEN} ??? {@link com.kakao.Session.RequestType#REFRESHING_ACCESS_TOKEN}) :  ?? - {@link #OPENED}, ?? - {@link #CLOSED}
         * close(???? close) : {@link #CLOSED}
         */
        OPENING,
        /**
         * access token??? ?????? ?? ?? valid access token??? ??? ?? ???.
         * ???? ?? : {@link #OPENING}
         * close(???? close) : {@link #CLOSED}
         */
        OPENED;

        private boolean isClosed(){
            return this == SessionState.CLOSED;
        }

        private boolean isOpening(){
            return this == SessionState.OPENING;
        }

        private boolean isOpened(){
            return this == SessionState.OPENED;
        }
    }

    private enum RequestType {
        GETTING_AUTHORIZATION_CODE,
        GETTING_ACCESS_TOKEN,
        REFRESHING_ACCESS_TOKEN;

        private boolean isAuthorizationCodeRequest() {
            return this == RequestType.GETTING_AUTHORIZATION_CODE;
        }

        private boolean isAccessTokenRequest() {
            return this == RequestType.GETTING_ACCESS_TOKEN;
        }

        private boolean isRefreshingTokenRequest() {
            return this == RequestType.REFRESHING_ACCESS_TOKEN;
        }
    }
}




Java Source Code List

com.kakao.APIErrorResult.java
com.kakao.AppActionBuilder.java
com.kakao.ErrorCode.java
com.kakao.KakaoLinkParseException.java
com.kakao.KakaoLink.java
com.kakao.KakaoStoryHttpResponseHandler.java
com.kakao.KakaoStoryPostParamBuilder.java
com.kakao.KakaoStoryProfile.java
com.kakao.KakaoStoryService.java
com.kakao.KakaoStoryUpload.java
com.kakao.KakaoTalkHttpResponseHandler.java
com.kakao.KakaoTalkLinkMessageBuilder.java
com.kakao.KakaoTalkProfile.java
com.kakao.KakaoTalkService.java
com.kakao.LoginActivity.java
com.kakao.LogoutResponseCallback.java
com.kakao.MeResponseCallback.java
com.kakao.SessionCallback.java
com.kakao.Session.java
com.kakao.SignupResponseCallback.java
com.kakao.UnlinkResponseCallback.java
com.kakao.UpdateProfileResponseCallback.java
com.kakao.UserManagement.java
com.kakao.UserProfileResponseCallback.java
com.kakao.UserProfile.java
com.kakao.UserResponseCallback.java
com.kakao.User.java
com.kakao.authorization.AuthorizationResult.java
com.kakao.authorization.Authorizer.java
com.kakao.authorization.accesstoken.AccessTokenRequest.java
com.kakao.authorization.accesstoken.AccessToken.java
com.kakao.authorization.accesstoken.GetterAccessToken.java
com.kakao.authorization.accesstoken.package-info.java
com.kakao.authorization.authcode.AuthorizationCodeHandler.java
com.kakao.authorization.authcode.AuthorizationCodeRequest.java
com.kakao.authorization.authcode.AuthorizationCode.java
com.kakao.authorization.authcode.GetterAuthorizationCode.java
com.kakao.authorization.authcode.KakaoWebViewDialog.java
com.kakao.authorization.authcode.LoggedInTalkAuthHandler.java
com.kakao.authorization.authcode.LoggedOutTalkAuthHandler.java
com.kakao.authorization.authcode.OnWebViewCompleteListener.java
com.kakao.authorization.authcode.WebViewAuthHandler.java
com.kakao.authorization.authcode.package-info.java
com.kakao.exception.KakaoException.java
com.kakao.exception.KakaoWebviewException.java
com.kakao.exception.package-info.java
com.kakao.helper.Base64.java
com.kakao.helper.JsonHelper.java
com.kakao.helper.Logger.java
com.kakao.helper.ServerProtocol.java
com.kakao.helper.SharedPreferencesCache.java
com.kakao.helper.SystemInfo.java
com.kakao.helper.TalkProtocol.java
com.kakao.helper.Utility.java
com.kakao.helper.package-info.java
com.kakao.http.AsyncHttpClient.java
com.kakao.http.BodyPart.java
com.kakao.http.FilePart.java
com.kakao.http.HttpRequestBuilder.java
com.kakao.http.HttpRequestTask.java
com.kakao.http.HttpResponseHandler.java
com.kakao.http.HttpTaskManager.java
com.kakao.http.KakaoAsyncHandler.java
com.kakao.http.Multipart.java
com.kakao.http.Request.java
com.kakao.http.Response.java
com.kakao.http.package-info.java
com.kakao.internal.ActionInfo.java
com.kakao.internal.Action.java
com.kakao.internal.KakaoTalkLinkProtocol.java
com.kakao.internal.LinkObject.java
com.kakao.internal.package-info.java
com.kakao.rest.APIHttpRequestTask.java
com.kakao.rest.package-info.java
com.kakao.sample.kakaolink.KakaoLinkMainActivity.java
com.kakao.sample.kakaolink.KakaoLinkSplashActivity.java
com.kakao.sample.kakaolink.package-info.java
com.kakao.sample.kakaostory.KakaoStoryLoginActivity.java
com.kakao.sample.kakaostory.KakaoStoryMainActivity.java
com.kakao.sample.kakaostory.KakaoStorySignupActivity.java
com.kakao.sample.kakaostory.package-info.java
com.kakao.sample.kakaotalk.KakaoTalkLoginActivity.java
com.kakao.sample.kakaotalk.KakaoTalkMainActivity.java
com.kakao.sample.kakaotalk.KakaoTalkSignupActivity.java
com.kakao.sample.kakaotalk.package-info.java
com.kakao.sample.usermgmt.ExtraUserPropertyLayout.java
com.kakao.sample.usermgmt.UserMgmtLoginActivity.java
com.kakao.sample.usermgmt.UsermgmtMainActivity.java
com.kakao.sample.usermgmt.UsermgmtSignupActivity.java
com.kakao.sample.usermgmt.package-info.java
com.kakao.template.loginbase.SampleLoginActivity.java
com.kakao.template.loginbase.SampleSignupActivity.java
com.kakao.template.loginbase.package-info.java
com.kakao.template.loginfree.LoginFreeTemplateActivity.java
com.kakao.template.loginfree.package-info.java
com.kakao.widget.LoginButton.java
com.kakao.widget.ProfileLayout.java
com.kakao.widget.package-info.java
com.kakao.package-info.java