Вход с помощью Facebook Android SDK и Proguard

Я создал приложение для Android с помощью Facebook Android SDK 3.0.

Я создал рабочее приложение (при запуске из 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>;  }

Кто-нибудь знает, как решить эту проблему?


person Peter Fortuin    schedule 29.01.2013    source источник
comment
Посмотрите на этот вопрос: stackoverflow.com/questions/13538070/   -  person Victor Ronin    schedule 01.02.2013


Ответы (1)


Ключ, вероятно, будет 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 изменяет имена классов, а это означает, что он больше не может найти ожидаемые классы для построения.

person Rob Pridham    schedule 01.02.2013
comment
Интересный ответчик. Странно то, что рассматриваемый класс (com.facebook.internal.SessionTracker$CallbackWrapper) не реализует java.io.Serializable. Итак, кажется, что исключение действительно. Но как это работает, когда я строю из Eclipse? - person Peter Fortuin; 01.02.2013
comment
Я думаю, что Proguard запускается только при создании релизной сборки, а не при развертывании отладочной сборки (поскольку это затруднит отладку). - person Rob Pridham; 01.02.2013
comment
Похоже, вы правы насчет CallbackWrapper, но начало трассировки вызовов — это попытка сериализации сеанса, который является сериализуемым. Я ожидаю, что реальность более сложна, и Proguard делает что-то довольно сложное. Попробуйте предложенное правило и посмотрите, как у вас получится. - person Rob Pridham; 01.02.2013
comment
Это действительно сработало. Proguard, не запущенный во время отладочной сборки, действительно усложняет отладку. Спасибо - person user1611248; 07.06.2013