13

I have created a Android application with the Facebook Android SDK 3.0.

I created a working application (when running from Eclipse). It will create a Facebook session (with com.facebook.UiLifecycleHelper) and a login button (with com.facebook.LoginButton) so that the user can login into Facebook. The Facebook authentication dialog is showing and after filling in the credentials the login button will show that the user is logged in into Facebook.

So, far everything works fine, but when I'm making a release build (with Proguard enabled) I get the following exception:

E/AndroidRuntime(14690): FATAL EXCEPTION: main
E/AndroidRuntime(14690): com.facebook.FacebookException: Unable to save session.
E/AndroidRuntime(14690):    at com.facebook.Session.saveSession(Session.java:673)
E/AndroidRuntime(14690):    at com.facebook.UiLifecycleHelper.onSaveInstanceState(UiLifecycleHelper.java:124)
E/AndroidRuntime(14690):    at com.peerkesoftware.blockcrusher.MorburActivity.onSaveInstanceState(MorburActivity.java:175)
E/AndroidRuntime(14690):    at android.app.Activity.performSaveInstanceState(Activity.java:1147)
E/AndroidRuntime(14690):    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1216)
E/AndroidRuntime(14690):    at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3253)
E/AndroidRuntime(14690):    at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3312)
E/AndroidRuntime(14690):    at android.app.ActivityThread.access$900(ActivityThread.java:150)
E/AndroidRuntime(14690):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1271)
E/AndroidRuntime(14690):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(14690):    at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(14690):    at android.app.ActivityThread.main(ActivityThread.java:5191)
E/AndroidRuntime(14690):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(14690):    at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(14690):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
E/AndroidRuntime(14690):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
E/AndroidRuntime(14690):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(14690): Caused by: java.io.NotSerializableException: com.facebook.internal.SessionTracker$CallbackWrapper
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
E/AndroidRuntime(14690):    at java.util.ArrayList.writeObject(ArrayList.java:644)
E/AndroidRuntime(14690):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(14690):    at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1053)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
E/AndroidRuntime(14690):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
E/AndroidRuntime(14690):    at com.facebook.Session.saveSession(Session.java:671)
E/AndroidRuntime(14690):    ... 16 more

I already tried adding some Proguard rules, but no luck resolving this issue:

-keep class com.facebook.*
-keep class com.facebook.android.*
-keep class android.webkit.WebViewClient
-keep class * extends android.webkit.WebViewClient
-keepclassmembers class * extends android.webkit.WebViewClient { 
    <methods>;  }

Does anybody have any idea how to resolve this problem?

Rob Pridham
  • 4,780
  • 1
  • 26
  • 38
Peter Fortuin
  • 5,041
  • 8
  • 41
  • 69
  • Look at this question: http://stackoverflow.com/questions/13538070/error-on-using-proguard-with-android-facebook-sdk-3-0 – Victor Ronin Feb 01 '13 at 00:10

1 Answers1

26

The key is likely to be the NotSerializableException in your stack trace.

You are already along the right lines with the rule set. Have a look at this Proguard documentation, in particular the section 'Processing serializable classes'.

The simplest example you can try from there is:

-keepclassmembers class * implements java.io.Serializable
{
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

but they expand on this and add more complexity.

I've seen something similar with Android's AIDL and the Parcelable interface, which is a different instance of serialisation (passing objects over a remote API). Proguard changes the class names, meaning that it can no longer find the expected classes to construct.

Rob Pridham
  • 4,780
  • 1
  • 26
  • 38
  • Interresting anwser. The strange thing is that the class in question (com.facebook.internal.SessionTracker$CallbackWrapper) doesn't implement java.io.Serializable. So, it seems that the exception is valid. But how is it working when I build from Eclipse? – Peter Fortuin Feb 01 '13 at 13:20
  • 3
    I think that Proguard only runs when creating a release build, and not when deploying a debug build (since this would make it harder to debug). – Rob Pridham Feb 01 '13 at 13:31
  • 3
    You appear to be right about CallbackWrapper, but the start of the call trace is the attempted serialisation of Session, which *is* Serializable. I expect the reality is more complex, and Proguard is doing something fairly intricate. Try the suggested rule and see how you get on. – Rob Pridham Feb 01 '13 at 13:33
  • 2
    This really worked. Proguard not running during debug build really makes the debugging harder. Thanks – user1611248 Jun 07 '13 at 08:32