Class not found when unmarshalling

KakaoTalk 이 설치되어있고 로긴이 되어는데도 불구하고 가입 유도하는 로긴 웹뷰를 띄웁니다. 로그에 아래와 같이 남습니다.

08-23 13:52:28.018 1408-2584/? E/Parcel: Class not found when unmarshalling: com.kakao.auth.authorization.authcode.GetterAuthCode$1
                                         java.lang.ClassNotFoundException: com.kakao.auth.authorization.authcode.GetterAuthCode$1
                                             at java.lang.Class.classForName(Native Method)
                                             at java.lang.Class.forName(Class.java:324)
                                             at android.os.Parcel.readParcelableCreator(Parcel.java:2404)
                                             at android.os.Parcel.readParcelable(Parcel.java:2358)
                                             at android.os.Parcel.readValue(Parcel.java:2264)
                                             at android.os.Parcel.readArrayMapInternal(Parcel.java:2614)
                                             at android.os.BaseBundle.unparcel(BaseBundle.java:221)
                                             at android.os.BaseBundle.getString(BaseBundle.java:920)
                                             at android.content.Intent.getStringExtra(Intent.java:6195)
                                             at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:2695)
                                             at com.android.server.am.ActivityStackSupervisor.startActivityMayWait(ActivityStackSupervisor.java:2157)
                                             at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:6320)
                                             at com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:6098)
                                             at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:170)
                                             at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3988)
                                             at android.os.Binder.execTransact(Binder.java:453)
                                          Caused by: java.lang.ClassNotFoundException: com.kakao.auth.authorization.authcode.GetterAuthCode$1
                                             at java.lang.Class.classForName(Native Method)
                                             at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
                                             at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
                                             at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
                                             at java.lang.Class.classForName(Native Method) 
                                             at java.lang.Class.forName(Class.java:324) 
                                             at android.os.Parcel.readParcelableCreator(Parcel.java:2404) 
                                             at android.os.Parcel.readParcelable(Parcel.java:2358) 
                                             at android.os.Parcel.readValue(Parcel.java:2264) 
                                             at android.os.Parcel.readArrayMapInternal(Parcel.java:2614) 
                                             at android.os.BaseBundle.unparcel(BaseBundle.java:221) 
                                             at android.os.BaseBundle.getString(BaseBundle.java:920) 
                                             at android.content.Intent.getStringExtra(Intent.java:6195) 
                                             at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:2695) 
                                             at com.android.server.am.ActivityStackSupervisor.startActivityMayWait(ActivityStackSupervisor.java:2157) 
                                             at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:6320) 
                                             at com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:6098) 
                                             at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:170) 
                                             at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3988) 
                                             at android.os.Binder.execTransact(Binder.java:453) 
                                          Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available

SDK는 1.1.20 / 1.1.21 둘다 테스트해 보았고, 관련 코드와 설정들은 다음과 같습니다.

  • app/AndroidManifest.xml

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

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="22" />

    <application>

        <meta-data android:name="com.kakao.sdk.AppKey"
            android:value="13425bebec14a97e8d6f98485596c0f7" />

        <activity
            android:name="com.kakao.auth.authorization.authcode.KakaoWebViewActivity"
            android:launchMode="singleTop"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

    </application>
  • gradle.properties

...
KAKAO_SDK_GROUP=com.kakao.sdk
KAKAO_SDK_VERSION=1.1.21
  • bundle.gradle

allprojects {
    repositories {
        mavenLocal()
        jcenter()
        ...
        maven { url 'http://devrepo.kakao.com:8088/nexus/content/groups/public/' }
    }
}
  • app/bundle.gradle

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"
...
}
...
dependencies {
...
    // 카카오톡 sdk를 사용하기 위해 필요.
    compile group: project.KAKAO_SDK_GROUP, name: 'usermgmt', version: project.KAKAO_SDK_VERSION
...
}
  • app/proguard-rules.pro

-keep class com.kakao.** { *; }
-keepattributes Signature
-keepclassmembers class * {
  public static <fields>;
  public *;
}
  • Login

    private class KakaoSessionOpenCallback implements ISessionCallback {
        private Promise _promise;
        public KakaoSessionOpenCallback(Promise promise) {
            _promise = promise;
        }

        @Override
        public void onSessionOpened() {
            Session session = Session.getCurrentSession();
            session.removeCallback(this);
            _promise.resolve(session.getAccessToken());
        }

        @Override
        public void onSessionOpenFailed(KakaoException exception) {
            Session.getCurrentSession().removeCallback(this);

            if (exception == null) {
                Log.d("kakao", "kakao-login-closed");
                _promise.reject("kakao-login-cancel", "kakao-login-cancel");
            } else {
                Log.e("kakao", exception.getLocalizedMessage());
                _promise.reject("kakao-login-error", exception);
            }
        }
    }

    public void login(Promise promise) {
        Session session = Session.getCurrentSession();
        if(session.hasValidAccessToken()) {
            promise.resolve(session.getAccessToken());
        } else {
            session.addCallback(new KakaoSessionOpenCallback(promise));
            session.open(AuthType.KAKAO_LOGIN_ALL, MainApplication.getCurrentActivity());
        }
    }
  • MainActivity

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // KAKAO
        if (Session.getCurrentSession().handleActivityResult(requestCode, resultCode, data)) {
            return;
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void onResume() {
        super.onResume();
        MainApplication.setCurrentActivity(this);
    }

    @Override
    protected void onPause() {
        Beacon.disconnect();
        clearReferences();
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        Beacon.disconnect();
        clearReferences();
        super.onDestroy();
    }

    private void clearReferences() {
        Activity currActivity = MainApplication.getCurrentActivity();
        if (currActivity != null && currActivity.equals(this)) {
            MainApplication.setCurrentActivity(null);
        }
    }
  • KakaoSDKAdapter

    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_LOGIN_ALL};
            }

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

            @Override
            public boolean isSecureMode() {
                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 MainApplication.getCurrentActivity();
            }

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

    private static volatile MainApplication instance = null;

    private static FragmentActivity currentActivity;

    @Override
    public void onCreate() {
      super.onCreate();
      // KAKAO
      instance = this;
      KakaoSDK.init(new KakaoSDKAdapter());
      // FACEBOOK
      FacebookSdk.sdkInitialize(getApplicationContext());
      // If you want to use AppEventsLogger to log events.
      AppEventsLogger.activateApp(this);
    }

    public static FragmentActivity getCurrentActivity() {
      return currentActivity;
    }

    // KAKAO

    /**
     * singleton 애플리케이션 객체를 얻는다.
     * @return singleton 애플리케이션 객체
     */
    public static MainApplication getGlobalApplicationContext() {
      if(instance == null)
        throw new IllegalStateException("this application does not inherit MainApplication");
      return instance;
    }

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

    /**
     * 애플리케이션 종료시 singleton 어플리케이션 객체 초기화한다.
     */
    @Override
    public void onTerminate() {
      super.onTerminate();
      instance = null;
    }

그외에 iOS에서는 UserManagement.requestMe 도 작동을 안해서 accessToken 얻어서 API 호출하고 있습니다. Callback호출이 안되네요

헐…전혀 상관없는 에러였군요. 웹뷰가 뜰때 항상나오네요.

간편 로그인이 안되던 문제는 KAKAO_LOGIN_ALL을 썼기 때문이네요…당연히 네이티브 앱이 존재하면 네이티브 앱을 우선할것이라 예상했는데, 오산이군요. KAKAO_TALK으로 교체한후 잘됩니다.

@iameugenejo_kakao 이상하네요. KAKAO_LOGIN_ALL의 경우 가능한 모든 로그인을 하도록 하는거에요. 톡이 있으면(당연히 해당 톡에 카카오계정이 연결되어 있어야 함) 톡, 스토리가 있으면 스토리. 즉 로그인 가능한것이 중간 팝업 list가 떠서 선택을 할 수 있게 해 주는거에요.
우선이라기보다 선택 팝업이 떠서 고르게 해주는거죠.
KAKAO_TALK의 경우 선택 팝업을 제공하는것이 아니라 톡으로만 최대 로그인 하겠다는 기능이구요. 물론 톡이 없으면 id/pass창이 뜨구요.

제가 샘플코드를 잘못 이해해서 생긴 문제네요. React Native로 구현중이라 샘플코드를 그대로 가져다 쓰는데 한계가 있어서 하나씩 뜯어보고 구현하고 있습니다.

1개의 좋아요