๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Android][Kakao SDK]์•ˆ๋“œ๋กœ์ด๋“œ ์นด์นด์˜ค ๋กœ๊ทธ์ธ SDK Legacy v1 -> v2 ์—…๋ฐ์ดํŠธ

์‹ ๊ทœ๋กœ ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์—ฐ๋™ํ•˜๋Š” ๋ธ”๋กœ๊ทธ๋“ค์€ ๊ฝค๋‚˜ ๋ดค๋Š”๋ฐ, v1.x.x ์—์„œ v2.x.x๋กœ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ธ€๋“ค์€ ์ œ๊ฐ€ ๋ชป ์ฐพ์•„์„œ ์ •๋ฆฌํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 

์‹ ๊ทœ๋กœ ์นด์นด์˜ค ๊ณ„์ • ๋กœ๊ทธ์ธ ์„œ๋น„์Šค๋ฅผ ๋„ฃ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ƒ๋žต๋œ ๊ณผ์ •๋“ค(ํ‚ค ํ•ด์‹œ ๋“ฑ๋ก ๋“ฑ)์ด ์žˆ์Šต๋‹ˆ๋‹ค.๐Ÿ˜Ž

6๋…„ ์ „์— ๋งŒ๋“ค์–ด์ ธ ์ง€๊ธˆ๊นŒ์ง€ ์œ ์ง€๋ณด์ˆ˜๋˜๊ณ  ์žˆ๋Š” ์•ฑ์ด๋ผ ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋Š” ๋ฐ ์ž๋ฐ”๋ฅผ ์“ฐ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.๐Ÿ‘ฉ‍๐Ÿ”ง๐Ÿ‘จ‍๐Ÿ”ง

 


Gradle ์„ค์ •ํ•˜๊ธฐ

ํ”„๋กœ์ ํŠธ์˜ build.gradle

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

allprojects {
    repositories {
        ....
        maven { url 'http://devrepo.kakao.com:8088/nexus/content/groups/public/' }
        ....
    }
}

 

์ˆ˜์ • ์ฝ”๋“œ

allprojects {
    repositories {
        ....
        maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/' }
        ....
    }
}

 

 

๐Ÿ™„โ” settings.gradle ์— ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ๋ฅผ ์„ค์ •ํ•œ๋‹ค?

kakao ๋ฌธ์„œ

 

https://developer.android.com/studio/build#build-files
 

๋นŒ๋“œ ๊ตฌ์„ฑ  |  Android ๊ฐœ๋ฐœ์ž  |  Android Developers

Android ๋นŒ๋“œ ์‹œ์Šคํ…œ์€ ์•ฑ ๋ฆฌ์†Œ์Šค ๋ฐ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผํ•˜๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ ํ…Œ์ŠคํŠธ, ๊ตฌ์ถ•, ์„œ๋ช… ๋ฐ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋Š” APK๋กœ ํŒจํ‚ค์ง•ํ•ฉ๋‹ˆ๋‹ค.

developer.android.com

https://developer.android.com/studio/preview/features#settings-gradle

 

Android ์ŠคํŠœ๋””์˜ค ๋ฏธ๋ฆฌ๋ณด๊ธฐ์˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ  |  Android ๊ฐœ๋ฐœ์ž  |  Android Developers

Android ์ŠคํŠœ๋””์˜ค ๋ฏธ๋ฆฌ๋ณด๊ธฐ์˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ํ™•์ธํ•˜์„ธ์š”.

developer.android.com

 

์˜ค... ๋ฐ”๋€ ๊ฑฐ ์ด์ œ ์•Œ์•˜๋‹ค.

 

์ž‘์—…ํ•˜๋Š” ์•ฑ์€ ์˜›๋‚  ์˜›์  6๋…„ ์ „์— ์ƒ์„ฑ๋œ ์˜ค๋žœ ํžˆ์Šคํ† ๋ฆฌ๊ฐ€ ์žˆ๋Š” ์•ฑ์ด๋‹ˆ ์ด๋Ÿฐ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ ์šฉํ•  ์ผ์ด ์—†์—ˆ๋‹ค. top level์˜ build.gradle์„ ์ˆ˜์ •ํ–ˆ๊ณ , ํ…Œ์ŠคํŠธํ•˜๋‹ˆ ์ž˜ ๋Œ์•„๊ฐ„๋‹ค.

 

 

๋กœ๊ทธ์ธ ๋ชจ๋“ˆ ์„ค์ •ํ•˜๊ธฐ

app์˜ build.gradle

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ SDK ๋ฒ„์ „์„ ๋ณด๋ฉด ๋ถ€๋„๋Ÿฝ๋‹ค... ๋„ˆ๋ฌด ์—…๋ฐ์ดํŠธ ์•ˆํ•˜๊ณ  ์‚ด์•˜๋‹ค.

dependencies {
    ....
    implementation 'com.kakao.sdk:usermgmt:1.27.0'
    ....
}

 

์ˆ˜์ • ์ฝ”๋“œ

dependencies {
    ....
    implementation 'com.kakao.sdk:v2-user:2.8.4'
    ....
}

 

ํ”„๋กœ๊ฐ€๋“œ ์„ค์ •ํ•˜๊ธฐ

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

์—†์Œ. (์•„๋‹ˆ๋ฉด ๋‚ด๊ฐ€ ๋ชจ๋ฅด๋Š” ๊ฒƒ์ผ ์ˆ˜๋„ ์žˆ๋‹ค...)

 

์ถ”๊ฐ€ ์ฝ”๋“œ

#์นด์นด์˜ค ๋กœ๊ทธ์ธ
-keep class com.kakao.sdk.**.model.* { <fields>; }
-keep class * extends com.google.gson.TypeAdapter

 

๐Ÿ˜“์•ฑ์—์„œ ์นด์นด์˜ค ๋ฒกํ„ฐ๋งต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์‚ฌ์šฉ ์ค‘์ด๊ณ , ์ด์™€ ๊ด€๋ จํ•ด์„œ ํ”„๋กœ๊ฐ€๋“œ์— ์ฝ”๋“œ๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์—ˆ๋‹ค. ํ•ด๋‹น ํ”„๋กœ๊ฐ€๋“œ ์ฝ”๋“œ๋“ค์˜ ์ฃผ์„์ด "#kakao" ๋ผ๊ณ ๋งŒ ์ ํ˜€์žˆ์–ด์„œ, ์นด์นด์˜ค ๋งต์€ ์ƒ๊ฐ์ง€๋„ ๋ชปํ•˜๊ณ  ๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ๋กœ๊ทธ์ธ sdk ์™€ ๊ด€๋ จ๋œ ์ค„ ์•Œ๊ณ  ๋‹ค ์ง€์› ๋‹ค๊ฐ€ ๋‚˜์ค‘์— ํ…Œ์ŠคํŠธํ•˜๋ฉฐ ํ•œ์ฐธ์„ ํ—ค๋งธ๋‹ค. ์ด๋ฒˆ ์‚ฝ์งˆ์˜ ๊ตํ›ˆ์€ "ํ”„๋กœ๊ฐ€๋“œ ์„ค์ •์„ ์œ„ํ•œ ๋ฆด๋ฆฌ์ฆˆ ํ…Œ์ŠคํŠธ๋Š” ์ž˜ํ–ˆ๋‹ค. ์ฃผ์„์„ ๋” ์ƒ์„ธํžˆ ์จ๋„ ๋˜๊ฒ ๋‹ค." 

 

 

Application ์ˆ˜์ •

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

public class App extends Application {

    @Override
    public void onCreate() {
        ....
        KakaoSDk.init(new KakaoSDKAdapter());
        ....
    }
    
    ....
    
    private class KakaoSDKAdapter extends KakaoAdapter {
    
        @Override
        public ISessionConfig getSessionConfig() {
            return new ISessionConfig() {
                @Override
                public AuthType[] getAuthTypes() {
                    return AuthType[]{AuthType.KAKAO_LOGIN_ALL};
                }
                
                @Override
                public boolean isSecureMode() {
                    return false;
                }
                
                @Override
                public boolean isUsingWebviewTimer() {
                    return false;
                }
                
                @Override
                public ApprovalType getApprovalType() {
                    return ApprovalType.INDIVIDUAL;
                }
                
                @Override
                public boolean isSaveFormData() {
                    return true;
                }
            }
        }
        
        @Override
        public IApplicationConfig getApplicationConfig() {
            return () -> {
                return App.this;
            };
        }
    
    }
    
    ....

}

 

 

์ˆ˜์ • ์ฝ”๋“œ

public class App extends Application {

    @Override
    public void onCreate() {
        ....
        //KakaoSDK ์ดˆ๊ธฐํ™” ์ฝ”๋“œ ์‚ญ์ œ
        
        KakaoSdk.init(this, getString(R.string.kakao_app_key));
        ....
    }
    
    ....
    //์นด์นด์˜ค sdk ์–ด๋Žํ„ฐ ์‚ญ์ œ
    ....
    
}

 

string value ์ˆ˜์ •

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

<resources>
    ....
    <string name="kakao_app_key" translatable="false">{ํ‚ค}</string>
    ....
</resources>

 

์ˆ˜์ • ์ฝ”๋“œ

<resources>
   ....
   <string name="kakao_app_key" translatable="false">{ํ‚ค}</string> <!--๊ธฐ์กด-->
   <string name="redirect_kakao_app_key" translatable="false">kakao{ํ‚ค}</string> <!--์ถ”๊ฐ€-->
   ....
</resources>

 

AndroidManifest ์ˆ˜์ •

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="llll">

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

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

    </application>

    ....
   
</manifest>

 

 

์ˆ˜์ • ์ฝ”๋“œ

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    pacakge="llll">
    
    ...
   <application
        android:name=".App"
        ...>
        
    <!-- ์นด์นด์˜ค sdk meta-data ์‚ญ์ œ -->  
        
    </application>
    
    
    <!-- ์•กํ‹ฐ๋น„ํ‹ฐ ์ถ”๊ฐ€ -->
    <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="@string/redirect_kakao_app_key" />
        </intent-filter>
    </activity>

    ...
    
</manifest>

 

๋กœ๊ทธ์ธ ํ™”๋ฉด layout xml ์ˆ˜์ •

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        
        ....
        <!--์‚ฌ์šฉ์ž๊ฐ€ ํด๋ฆญํ•˜๋Š” ๋ฒ„ํŠผ-->
        <androidx.appcompat.widget.AppCompatImageButton
            android:id="@+id/btKakao"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="14dp"
            android:layout_marginRight="24dp"
            android:layout_marginBottom="40dp"
            android:background="@drawable/login_btn_kakao"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@id/btnOther"
            app:layout_constraintTop_toBottomOf="@id/description" />
        
        ....
        
        <!--์นด์นด์˜ค ๋กœ๊ทธ์ธ sdk ์ œ๊ณต ๋ฒ„ํŠผ-->
        <com.kakao.usermgmt.LoginButton
            android:id="@+id/btKakaoLogin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintLeft_toRightOf="@id/btnAnother" />

        ....
        
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

์ˆ˜์ • ์ฝ”๋“œ

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        
        ....
        <!--์‚ฌ์šฉ์ž๊ฐ€ ํด๋ฆญํ•˜๋Š” ๋ฒ„ํŠผ-->
        <androidx.appcompat.widget.AppCompatImageButton
            android:id="@+id/btKakao"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="14dp"
            android:layout_marginRight="24dp"
            android:layout_marginBottom="40dp"
            android:background="@drawable/login_btn_kakao"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@id/btnOther"
            app:layout_constraintTop_toBottomOf="@id/description" />
        
        ....
        
        <!--์นด์นด์˜ค ๋กœ๊ทธ์ธ sdk ์ œ๊ณต ๋ฒ„ํŠผ ์‚ญ์ œ-->
        
        ....
        
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ง„ํ–‰ํ•˜๋Š” ๋กœ๊ทธ์ธ ์ฝ”๋“œ ์ˆ˜์ •

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

์†”์งํžˆ ๋งํ•ด์„œ ๋ณด๊ธฐ ์ข‹๊ณ  ์ž˜ ์“ด ์ฝ”๋“œ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š๋Š”๋‹ค.

SessionCallback์œผ๋กœ ์„ธ์…˜ open์ด ์„ฑ๊ณตํ•˜๋ฉด UserManagement๋กœ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€ MeV2ResponseCallback์„ ํ˜ธ์ถœํ•ด์„œ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

public class LoginFragment extends BaseFragment {

    ....
    private SessionCallback callback;    //KAKAO SESSION
    ....
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        ....
        
        initView();
        
        setSessionLogin();
        ....
    }
    
    private void initView() {
        ....
        
        binding.btnKakao.setOnClickListener(v ->{
            ....
            
            Session.getCurrentSession().addCallback(callback);
            binding.btnKakaoLogin.callOnClick();
        });
        
        ....
    }
    
    private void setSessionLogin() {
        ....
        callback = new SessionCallback();
        Session.getCurrentSession().addCallback(callback);
        ....    
        
        String loginType = Preference.INSTANCE.getAccountType();
        if(AccountType.KAKAO.name().equalsIgnoreCase(loginType)) {
            if(Session.getCurrentSession().checkAndImpliciteOpen()) {
               // ๋กœ๋”ฉ๋ฐ” ๋…ธ์ถœ ์ฝ”๋“œ
               ....
            }
        } else if(...) {
            ....
        }
        ....
    }
    
    ....
    
    private class SessionCallback implements ISessionCallback {
    
        @Override
        public void onSessionOpen() {
            //๋กœ๋”ฉ๋ฐ” ๋…ธ์ถœ ์ฝ”๋“œ
            ....
            requestMe(Session.getCurrentSession().getTokenInfo().getAccessToken());
        }
        
        @Override
        public void onSessionOpenFailed(KakaoExeption exception) {
            String loginType = Preference.INSTANCE.getAccountType();
            
            if(AccountType.KAKAO.name().equalsIgnoreCase(loginType)) {
                Session.getCurrentSession().removeCallback(callback);
                Session.getCurrentSession().close();
                Preference.INSTANCE.clearAccountType()
                //๋กœ๋”ฉ๋ฐ” ์ œ๊ฑฐ
                //์‚ฌ์šฉ์ž ์•Œ๋ฆผ ํ† ์ŠคํŠธ
                ....
            }
        }

    }
    
    private void requestMe(String accessToken) {
        UserManagement.getInstance().me(new MeV2ResponseCallback() {
            @Override
            public void onFailure(ErrorResult errorResult) {
                super.onFailure(errorResult)
                Session.getCurrentSession().removeCallback(callback);
                Session.getCurrentSession().close();
                Preference.INSTANCE.clearAccountType()
                //๋กœ๋”ฉ๋ฐ” ์ œ๊ฑฐ
                //์‚ฌ์šฉ์ž ์•Œ๋ฆผ ํ† ์ŠคํŠธ
                ....
            }
            
            @Override
            public void onSessionClosed(ErrorResult errorResult) {
            
            if (Session.getCurrentSession() != null) {
                    Session.getCurrentSession().removeCallback(callback);
                    Session.getCurrentSession().close();
                }
            }
            
            @Override
            public void onSuccess(MeV2Response result) {
            
                //ํ•„์š”ํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ›๊ธฐ
                String accountId = String.valueOf(result.getId());
                ....
            
            	///์„œ๋ฒ„๋กœ sns ๋กœ๊ทธ์ธ ์š”์ฒญ
                singInBySns(...);
            }
        });
    }

}

 

 

์ˆ˜์ • ์ฝ”๋“œ

์„ธ์…˜ ์ฝœ๋ฐฑ ๋ถ€๋ถ„์ด ์‚ฌ๋ผ์กŒ๊ณ , ๋‹จ๋ง์— ์นดํ†ก ์„ค์น˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ด ๋กœ๊ทธ์ธ ๋ฐฉ๋ฒ•์ด ๊ฐˆ๋ฆฌ๋„๋ก ์ˆ˜์ •๋˜์—ˆ๋‹ค. 

์นดํ†ก ๋กœ๊ทธ์ธ ํ˜น์€ ์นด์นด์˜ค ๊ณ„์ • ๋กœ๊ทธ์ธ ์ง„ํ–‰์— ๋”ฐ๋ฅธ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” Function2๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ–ˆ๋‹ค. ์นด์นด์˜ค sdk api๋“ค์€ ์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์ง€๋งŒ ์•ฑ์˜ ์ฝ”๋“œ๋Š” ์ž๋ฐ”์ด๊ธฐ์— ์ด๊ฒƒ์ด ๋‚˜์˜ ์ตœ์„ ์ด์—ˆ๋‹ค.

public class LoginFragment extends BaseFragment {

    ....
    //Session Callback ์‚ญ์ œ
    ....
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        ....
        
        initView();
        
        setSessionLogin();
        ....
    }
    
    private void initView() {
        ....
        
        binding.btnKakao.setOnClickListener(v ->{
            ....
            //์„ธ์…˜ ์ฝœ๋ฐฑ ๊ด€๋ จ ์ฝ”๋“œ ์ œ๊ฑฐ
            //์นด์นด์˜ค sdk ์ œ๊ณต ๋ฒ„ํŠผ ํด๋ฆญ ์ œ๊ฑฐ

            Function2<OAuthToken, Throwable, Unit> callback = (Function2<OAuthToken, Throwable, Unit>) (token, error) -> {
                if (error != null) {
                    //๋กœ๊ทธ์ธ ์‹คํŒจ
                    final String loginType = Prefrence.getACCOUNT_TYPE();
                    if (AccountType.KAKAO.name().equalsIgnoreCase(loginType)) {
                        Pref.Account.INSTANCE.clearAccountType();
                        //๋กœ๋”ฉ๋ฐ” ์ œ๊ฑฐ
                        //์‚ฌ์šฉ์ž ์•Œ๋ฆผ ํ† ์ŠคํŠธ
                        ....

                    }
                } else if (token != null) {
                    //๋กœ๊ทธ์ธ ์„ฑ๊ณต
                    //๋กœ๋”ฉ๋ฐ” ๋…ธ์ถœ
                    ....
                    String accessToken = token.getAccessToken();
                   
                    requestMe(accessToken);
                }
                return null;
            };

            // ์นด์นด์˜คํ†ก์ด ์„ค์น˜๋˜์–ด ์žˆ์œผ๋ฉด ์นด์นด์˜คํ†ก์œผ๋กœ ๋กœ๊ทธ์ธ, ์•„๋‹ˆ๋ฉด ์นด์นด์˜ค๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ
            if (UserApiClient.getInstance().isKakaoTalkLoginAvailable(requireContext())) {
                UserApiClient.getInstance().loginWithKakaoTalk(requireContext(), callback);
            } else {
                UserApiClient.getInstance().loginWithKakaoAccount(requireContext(), callback);
            }
        });
        
        ....
    }
 
    ....
    
    private void requestMe(String accessToken) {
        //UserManagement ๊ด€๋ จ ์ฝ”๋“œ ์‚ญ์ œ
        UserApiClient.getInstance().me((Function2<User, Throwable, Unit>) (user, error) -> {
            if (error != null) {
                //์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ ์‹คํŒจ
                //๋กœ๋”ฉ๋ฐ” ์‚ญ์ œ
                //์‚ฌ์šฉ์ž ์•Œ๋ฆผ ํ† ์ŠคํŠธ ๋…ธ์ถœ
                ....
            } else if (user != null) {
                //์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ ์„ฑ๊ณต
                //ํ•„์š”ํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ›์•„์˜ค๊ธฐ
                accountId = String.valueOf(user.getId());
                com.kakao.sdk.user.model.Account account = user.getKakaoAccount();
                if (account != null) {
                    com.kakao.sdk.user.model.Profile profile = account.getProfile();
                    if (profile != null) {
                        profileURL = profile.getProfileImageUrl();
                        ...
                    }
                    ...
                }

                //์„œ๋ฒ„๋กœ sns ๋กœ๊ทธ์ธ ์š”์ฒญ
                signInBySNS(....);
            }
            return null;
        });
    }

}

 

 

 

์„ธ์…˜์ด ๋‚จ์•„ ์žˆ๋Š” ๊ฒฝ์šฐ ์•ฑ ์ง„์ž…์‹œ ์ž๋™ ๋กœ๊ทธ์ธ ์ฝ”๋“œ ์ˆ˜์ •

์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•˜๊ฑฐ๋‚˜ ์˜ˆ์ œ๊ฐ€ ์žˆ๋Š” ๋ธ”๋กœ๊ทธ๋“ค์„ ์ฐพ์ง€ ๋ชปํ–ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋งž๋‚˜ ๊ธด๊ฐ€๋ฏผ๊ฐ€ ํ•˜๋ฉด์„œ ์ž‘์—…ํ–ˆ๋‹ค. ํ…Œ์ŠคํŠธํ•ด๋ณด๋‹ˆ ์ •์ƒ๋™์ž‘ํ•œ๋‹ค.

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

์†”์งํžˆ ๋งํ•ด์„œ ๋ณด๊ธฐ ์ข‹๊ณ  ์ž˜ ์“ด ์ฝ”๋“œ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š๋Š”๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด์„œ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ๊ณผ, ๋‚จ์€ ์„ธ์…˜์ด ์œ ํšจํ•ด์„œ ๋ฐ”๋กœ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ ๋ชจ๋‘ session callback์œผ๋กœ ์ง„ํ–‰๋˜๊ณ  ์žˆ์—ˆ๋‹ค.

SessionCallback์œผ๋กœ ์„ธ์…˜ open์ด ์„ฑ๊ณตํ•˜๋ฉด UserManagement๋กœ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€ MeV2ResponseCallback์„ ํ˜ธ์ถœํ•ด์„œ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

public class LoginFragment extends BaseFragment {

    ....
    private SessionCallback callback;    //KAKAO SESSION
    ....
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        ....
        
        setSessionLogin();
        ....
    }
    
    private void setSessionLogin() {
        ....
        callback = new SessionCallback();
        Session.getCurrentSession().addCallback(callback);
        ....    
        
        String loginType = Preference.INSTANCE.getAccountType();
        if(AccountType.KAKAO.name().equalsIgnoreCase(loginType)) {
            if(Session.getCurrentSession().checkAndImpliciteOpen()) {
               // ๋กœ๋”ฉ๋ฐ” ๋…ธ์ถœ ์ฝ”๋“œ
               ....
            }
        } else if(...) {
            ....
        }
        ....
    }
    
    ....
    
    private class SessionCallback implements ISessionCallback {
    
        @Override
        public void onSessionOpen() {
            //๋กœ๋”ฉ๋ฐ” ๋…ธ์ถœ ์ฝ”๋“œ
            ....
            requestMe(Session.getCurrentSession().getTokenInfo().getAccessToken());
        }
        
        @Override
        public void onSessionOpenFailed(KakaoExeption exception) {
            String loginType = Preference.INSTANCE.getAccountType();
            
            if(AccountType.KAKAO.name().equalsIgnoreCase(loginType)) {
                Session.getCurrentSession().removeCallback(callback);
                Session.getCurrentSession().close();
                Preference.INSTANCE.clearAccountType()
                //๋กœ๋”ฉ๋ฐ” ์ œ๊ฑฐ
                //์‚ฌ์šฉ์ž ์•Œ๋ฆผ ํ† ์ŠคํŠธ
                ....
            }
        }

    }
    
    private void requestMe(String accessToken) {
        UserManagement.getInstance().me(new MeV2ResponseCallback() {
            @Override
            public void onFailure(ErrorResult errorResult) {
                super.onFailure(errorResult)
                Session.getCurrentSession().removeCallback(callback);
                Session.getCurrentSession().close();
                Preference.INSTANCE.clearAccountType()
                //๋กœ๋”ฉ๋ฐ” ์ œ๊ฑฐ
                //์‚ฌ์šฉ์ž ์•Œ๋ฆผ ํ† ์ŠคํŠธ
                ....
            }
            
            @Override
            public void onSessionClosed(ErrorResult errorResult) {
            
            if (Session.getCurrentSession() != null) {
                    Session.getCurrentSession().removeCallback(callback);
                    Session.getCurrentSession().close();
                }
            }
            
            @Override
            public void onSuccess(MeV2Response result) {
            
                //ํ•„์š”ํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ›๊ธฐ
                String accountId = String.valueOf(result.getId());
                ....
            
            	///์„œ๋ฒ„๋กœ sns ๋กœ๊ทธ์ธ ์š”์ฒญ
                singInBySns(...);
            }
        });
    }

}

 

 

์ˆ˜์ • ์ฝ”๋“œ

SessionCallback ํด๋ž˜์Šค๋Š” ์‚ญ์ œ๋˜์—ˆ๊ณ , requestMe()๋Š” ๋ฒ„ํŠผ ํด๋ฆญ์œผ๋กœ ๋กœ๊ทธ์ธํ•  ๋•Œ์™€ ์•ฑ ์ง„์ž… ํ›„ ์„ธ์…˜ ๋กœ๊ทธ์ธํ•  ๋•Œ ๋‘˜ ๋‹ค ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. 

requestMe(String accessToken)์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํ† ํฐ๊ฐ’์ด ํ•„์š”ํ•œ๋ฐ, accessTokenInfo ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ token์ด ์ด๋ฆ„๋งŒ ํ† ํฐ์ด๋ผ๊ณ  ์ž ๊น ์ƒ๊ฐํ–ˆ์„ ์ •๋„๋กœ ์—‘์„ธ์Šค ํ† ํฐ ๊ฐ’์„ ๋นผ๊ณ  ๋‹ค๋ฅธ ์ •๋ณด๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ TokenManager๋กœ ์ง์ ‘ ํ† ํฐ๊ฐ’์„ ๊ฐ€์ ธ๋‹ค๊ฐ€ requestMe()๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค. 

public class LoginFragment extends BaseFragment {

    ....
    //Session Callback ์‚ญ์ œ
    ....
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        ....
        
        setSessionLogin();
        ....
    }
    
    ....
    
    private void setSessionLogin() {
        ....
        //์„ธ์…˜ ์ฝœ๋ฐฑ ๊ด€๋ จ ์ฝ”๋“œ ์‚ญ์ œ
        ....    
        
        String loginType = Preference.INSTANCE.getAccountType();
        if(AccountType.KAKAO.name().equalsIgnoreCase(loginType)) {
            //ํ† ํฐ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ
            if(AuthApiClient.getInstance().hasToken()) {
                UserApiClient.getInstance().accessTokenInfo((token, error) -> {
                    if(error == null) {
                        //ํ† ํฐ ์œ ํšจ์„ฑ ์ฒดํฌ ์„ฑ๊ณต
                        // ํ•„์š”์‹œ ํ† ํฐ ๊ฐฑ์‹  ๋จ
                        // ๋กœ๋”ฉ๋ฐ” ๋…ธ์ถœ ์ฝ”๋“œ
                        ....
                        
                        OAuthToken token = TokenManager.getInstance().getToken();
                        if(token != null) {
                            requestMe(token.getAccessToken());
                        }
                    }
                    return null;
                });
            }
        } else if(...) {
            ....
        }
        ....
    }
    
    ....
    //์„ธ์…˜ ์ฝœ๋ฐฑ ํด๋ž˜์Šค ์‚ญ์ œ
    ....
    
    private void requestMe(String accessToken) {
        //UserManagement ๊ด€๋ จ ์ฝ”๋“œ ์‚ญ์ œ
        UserApiClient.getInstance().me((Function2<User, Throwable, Unit>) (user, error) -> {
            if (error != null) {
                //์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ ์‹คํŒจ
                //๋กœ๋”ฉ๋ฐ” ์‚ญ์ œ
                //์‚ฌ์šฉ์ž ์•Œ๋ฆผ ํ† ์ŠคํŠธ ๋…ธ์ถœ
                ....
            } else if (user != null) {
                //์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ ์„ฑ๊ณต
                //ํ•„์š”ํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ›์•„์˜ค๊ธฐ
                accountId = String.valueOf(user.getId());
                com.kakao.sdk.user.model.Account account = user.getKakaoAccount();
                if (account != null) {
                    com.kakao.sdk.user.model.Profile profile = account.getProfile();
                    if (profile != null) {
                        profileURL = profile.getProfileImageUrl();
                        ...
                    }
                    ...
                }

                //์„œ๋ฒ„๋กœ sns ๋กœ๊ทธ์ธ ์š”์ฒญ
                signInBySNS(....);
            }
            return null;
        });
    }

}

 

 

๋กœ๊ทธ์•„์›ƒ ์ฝ”๋“œ ์ˆ˜์ •

 

๊ธฐ์กด ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ

์ „์ž„ ๊ฐœ๋ฐœ์ž๋Š” ์„ธ์…˜์„ close ํ•ด์„œ ๋กœ๊ทธ์•„์›ƒ์„ ์‹œ์ผฐ๋‹ค. 

publid void logout() {
    if (Session.getCurrentSession() != null) {
        Session.getCurrentSession().close()
    }
}

 

์ˆ˜์ • ์ฝ”๋“œ

์„ธ์…˜์„ ํ™•์ธํ•œ ์ „์ž„ ๊ฐœ๋ฐœ์ž์˜ ์ฝ”๋“œ์— ์˜๋„๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. (์ด์งํ•˜์‹  ๋ถ„์ด๋ผ ๊ทธ ์˜๋„๋ฅผ ๋ฌผ์–ด๋ณผ ์ˆ˜๋Š” ์—†๊ณ , ์˜๋„์™€ ๋น„์Šทํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ์ชฝ์ด ์–ด๋–ค ๊ฒƒ์ผ๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€) ํ˜„์žฌ ํ† ํฐ์ด ์œ ํšจํ•œ์ง€ ์ฒดํฌ ํ›„ ๋กœ๊ทธ์•„์›ƒ์„ ์ง„ํ–‰ํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ–ˆ๋‹ค. ํ…Œ์ŠคํŠธํ•˜๋‹ˆ ์ž˜ ๋Œ์•„๊ฐ„๋‹ค.

publid void logout() {
    if (AuthApiClient.getInstance().hasToken()) {
        UserApiClient.getInstance().logout(throwable -> null);
    }
}

 


์™„๋ฃŒ!!