使用Facebook Android SDK和Proguard进行登录

13

我使用Facebook Android SDK 3.0创建了一个Android应用程序。

我创造了一个可工作的应用程序(在Eclipse中运行时)。它将创建一个Facebook会话(与com.facebook.UiLifecycleHelper一起)和一个登录按钮(与com.facebook.LoginButton一起),以便用户可以登录Facebook。显示Facebook身份验证对话框,填写凭据后,登录按钮将显示用户已登录Facebook。

到目前为止,一切都很顺利,但当我进行发布构建(启用Proguard)时,我会遇到以下异常:

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

我已经尝试添加了一些Proguard规则,但是没有解决这个问题:

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

有人知道如何解决这个问题吗?


看看这个问题:https://dev59.com/XmYr5IYBdhLWcg3wnrZ0 - Victor Ronin
1个回答

26

你堆栈跟踪中的NotSerializableException很可能是关键。

你已经按照规则集正确地进行了操作。请查看这份Proguard文档,特别是“处理可序列化类”一节。

你可以从中尝试最简单的示例:

-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();
}

但他们在此基础上进行了扩展并增加了更多的复杂性。

我曾经在Android的AIDL和Parcelable接口中看到类似的情况,这是序列化的不同实例(通过远程API传递对象)。 Proguard更改了类名,这意味着它无法再找到预期的类来构造。


有趣的答案。奇怪的是,问题中的类(com.facebook.internal.SessionTracker$CallbackWrapper)没有实现java.io.Serializable接口。因此,异常似乎是有效的。但是当我从Eclipse构建时它是如何工作的呢? - Peter Fortuin
3
我认为Proguard仅在创建发布版本时运行,而不会在部署调试版本时运行(因为这会使调试变得更加困难)。 - Rob Pridham
3
你对CallbackWrapper的看法似乎是正确的,但调用跟踪的开始是Session的尝试序列化,而Session确实是Serializable的。我认为现实情况更加复杂,Proguard正在执行相当复杂的操作。尝试使用建议的规则并查看结果。 - Rob Pridham
2
这真的很有效。在调试构建期间不运行Proguard确实使调试更加困难。谢谢。 - user1611248

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接