简体   繁体   English

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

[英]Error on using proguard with Android Facebook sdk 3.0

Warning: I removed a lot of "old text" to keep the question more clean. 警告:我删除了很多“旧文本”以使问题更加清晰。 Just check the history if needed. 如果需要,只需查看历史记录。

I'm using proguard to both shrink and obfuscate an app that uses the facebook sdk 3.0 (I'm using the sdk-version-3.0.2.b tag ). 我正在使用proguard缩小和混淆使用facebook sdk 3.0的应用程序(我正在使用sdk-version-3.0.2.b标记 )。 I'm not using a JAR file. 我没有使用JAR文件。 Instead, I imported the sdk inside my workspace, as taught by the documentation . 相反,我按照文档中的说明在我的工作区中导入了sdk。

At a certain point in the execution, the app loads a PlacePickerFragment to let the user choose the place where he is. 在执行的某个时刻,应用程序加载PlacePickerFragment以让用户选择他所在的位置。 To code this, I follow exactly the Scrumptious tutorial . 为了编写代码,我完全遵循了美味的教程 When I generate the debug apk without using proguard everything works as expected. 当我在不使用proguard情况下生成调试apk时,一切都按预期工作。 But when I generate the signed apk using proguard , it crashes when the PlacePickerFragment loads nearby places with the following trace: 但是当我使用proguard生成签名的apk时,它会在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)

Trying to avoid this error, I kept all facebook classes untouched, but didn't work. 为了避免这个错误,我保持所有的facebook课程都不受影响,但没有奏效。 My current proguard-project.txt file: 我目前的proguard-project.txt文件:

-keep class com.facebook.** {
   *;
}

My current projet.properties file (excerpt): 我当前的projet.properties文件(摘录):

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

As you can see, my proguard configuration is a "specialization" of this file . 如您所见,我的proguard配置是此文件的“特化”。

If I put -dontobfuscate in proguard-project.txt file, it will work. 如果我把-dontobfuscate放在proguard-project.txt文件中,它会起作用。 But what I don't understand is that the keep class com.facebook.** should already prevent classes related to facebook to be obfuscated. 但我不明白的是, keep class com.facebook.**应该已经阻止了与facebook相关的类的混淆。 Which suggests that the problem is not directly related to the facebook classes. 这表明问题与facebook类没有直接关系。

The excerpt of code that throws com.facebook.FacebookGraphObjectException is: 抛出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());
        }
    // [...]
}

Clearly, expectedTypeAsParameterizedType is null in release build. 显然, expectedTypeAsParameterizedType在发布版本中为null But in both builds (debug and release) expectedType is a com.facebook.model.GraphObjectList interface. 但是在两个版本(调试和发布)中, expectedType是一个com.facebook.model.GraphObjectList接口。 Unfortunately, I don't understand almost nothing about Java reflection concepts. 不幸的是,我对Java反射概念几乎一无所知。

How can I fix this problem? 我该如何解决这个问题?

This will solve your problem, i hope: 这将解决您的问题,我希望:

And the winner is ..... 最终获胜者是 .....

-keepattributes Signature

From Proguard Homepage: 来自Proguard主页:

The "Signature" attribute is required to be able to access generic types when compiling in JDK 5.0 and higher. 在JDK 5.0及更高版本中进行编译时,“Signature”属性必须能够访问泛型类型。

if you want to proguard Facebook, the config below is working for me 如果你想进入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();
}

这可能有用(未经测试)

-keep class com.facebook.** { *; }

Try 尝试

-keep class com.facebook.** {
   *;
}

The reason being, is that when specifying private, public, protected you're still opening up default (package private) access to obfuscation. 原因是,当指定private,public,protected时,您仍然会打开默认(包私有)访问混淆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM