在Android Facebook sdk 3.0上使用proguard时出错

bor*_*ges 17 android facebook proguard facebook-android-sdk

警告:我删除了很多"旧文本"以使问题更加清晰.如果需要,只需查看历史记录.

我正在使用proguard缩小和混淆使用facebook sdk 3.0的应用程序(我正在使用sdk-version-3.0.2.b标记).我没有使用JAR文件.相反,我按照文档中的说明在我的工作区中导入了sdk .

在执行的某个时刻,应用程序加载PlacePickerFragment以让用户选择他所在的位置.为了编写代码,我完全遵循了美味的教程.当我生成调试apk而不使用proguard一切按预期工作.但是当我使用生成签名的apk时proguard,它会在PlacePickerFragment使用以下跟踪加载附近的地方时崩溃:

E/AndroidRuntime(27472): FATAL EXCEPTION: main
E/AndroidRuntime(27472): com.facebook.FacebookGraphObjectException: can't infer generic type of: interface com.facebook.model.GraphObjectList
E/AndroidRuntime(27472):    at com.facebook.model.GraphObject$Factory.coerceValueToExpectedType(Unknown Source)
E/AndroidRuntime(27472):    at com.facebook.model.GraphObject$Factory$GraphObjectProxy.proxyGraphObjectGettersAndSetters(Unknown Source)
E/AndroidRuntime(27472):    at com.facebook.model.GraphObject$Factory$GraphObjectProxy.invoke(Unknown Source)
E/AndroidRuntime(27472):    at com.facebook.widget.$Proxy2.getData(Native Method)
E/AndroidRuntime(27472):    at com.facebook.widget.GraphObjectPagingLoader.addResults(Unknown Source)
E/AndroidRuntime(27472):    at com.facebook.widget.GraphObjectPagingLoader.requestCompleted(Unknown Source)
E/AndroidRuntime(27472):    at com.facebook.widget.GraphObjectPagingLoader.access$1(Unknown Source)
E/AndroidRuntime(27472):    at com.facebook.widget.GraphObjectPagingLoader$2.onCompleted(Unknown Source)
E/AndroidRuntime(27472):    at com.facebook.Request$4.run(Unknown Source)
E/AndroidRuntime(27472):    at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime(27472):    at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime(27472):    at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime(27472):    at android.app.ActivityThread.main(ActivityThread.java:3687)
E/AndroidRuntime(27472):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(27472):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime(27472):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
E/AndroidRuntime(27472):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
E/AndroidRuntime(27472):    at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

为了避免这个错误,我保持所有的facebook课程都不受影响,但没有奏效.我目前的proguard-project.txt档案:

-keep class com.facebook.** {
   *;
}
Run Code Online (Sandbox Code Playgroud)

我当前的projet.properties文件(摘录):

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
Run Code Online (Sandbox Code Playgroud)

如您所见,我的proguard配置是此文件的"特化" .

如果我把-dontobfuscateproguard-project.txt文件中,它会工作.但我不明白的是keep class com.facebook.**应该已经防止与facebook相关的类被混淆了.这表明问题与facebook类没有直接关系.

代码摘录抛出com.facebook.FacebookGraphObjectException是:

static <U> U coerceValueToExpectedType(Object value, Class<U> expectedType, 
        ParameterizedType expectedTypeAsParameterizedType) {

    // [...]

    } else if (Iterable.class.equals(expectedType) || Collection.class.equals(expectedType)
        || List.class.equals(expectedType) || GraphObjectList.class.equals(expectedType)) {
        if (expectedTypeAsParameterizedType == null) {
            throw new FacebookGraphObjectException("can't infer generic type of: " + expectedType.toString());
        }
    // [...]
}
Run Code Online (Sandbox Code Playgroud)

显然,expectedTypeAsParameterizedTypenull在发布版本中.但是在两个版本(调试和发布)中expectedType都是一个com.facebook.model.GraphObjectList接口.不幸的是,我对Java反射概念几乎一无所知.

我该如何解决这个问题?

Ale*_*ien 30

这将解决您的问题,我希望:

最终获胜者是 .....

-keepattributes Signature
Run Code Online (Sandbox Code Playgroud)

来自Proguard主页:

在JDK 5.0及更高版本中进行编译时,"Signature"属性必须能够访问泛型类型.


小智 15

如果你想进入Facebook,下面的配置对我有用

#modify for Facebook
-keepattributes Signature
-keep class com.facebook.model.** { *; }

-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
Run Code Online (Sandbox Code Playgroud)