简体   繁体   English

Android Volley总是会因Proguard而失败

[英]Android Volley always fails with Proguard

The goal is to deploy an application with obfuscation and minification applied. 目标是部署应用了obfuscationminification应用程序。 Usual builds without minification work fine. 无需minification即可正常构建。 But when minifyEnabled is switched to true, everything compiles too, but all Volley requests fail with error callback ( onErrorResponse ) regardless on successful result. 但是,当minifyEnabled切换为true时,所有内容也会编译,但是无论成功结果如何,所有Volley请求都将失败并出现错误回调( onErrorResponse )。

Minification config in build.gradle : build.gradle缩小配置:

buildTypes {
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    debug {
        debuggable true
    }
}

proguard-rules.pro: proguard-rules.pro:

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }

# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

##---------------End: proguard configuration for Gson  ----------



##---------------Begin: proguard configuration for Spongy Castle  ----------

-keep class org.spongycastle.crypto.* {*;}
-keep class org.spongycastle.crypto.digests.* {*;}
-keep class org.spongycastle.crypto.encodings.* {*;}
-keep class org.spongycastle.crypto.engines.* {*;}
-keep class org.spongycastle.crypto.macs.* {*;}
-keep class org.spongycastle.crypto.modes.* {*;}
-keep class org.spongycastle.crypto.paddings.* {*;}
-keep class org.spongycastle.crypto.params.* {*;}
-keep class org.spongycastle.crypto.prng.* {*;}
-keep class org.spongycastle.crypto.signers.* {*;}

-keep class org.spongycastle.jcajce.provider.digest.** {*;}
-keep class org.spongycastle.jcajce.provider.keystore.** {*;}
-keep class org.spongycastle.jcajce.provider.symmetric.** {*;}
-keep class org.spongycastle.jcajce.spec.* {*;}
-keep class org.spongycastle.jce.** {*;}

-dontwarn javax.naming.**

##---------------End: proguard configuration for Spongy Castle  ----------



# Configuration for Guava 18.0
#
# disagrees with instructions provided by Guava project: https://code.google.com/p/guava-libraries/wiki/UsingProGuardWithGuava

-keep class com.google.common.io.Resources {
    public static <methods>;
}
-keep class com.google.common.collect.Lists {
    public static ** reverse(**);
}
-keep class com.google.common.base.Charsets {
    public static <fields>;
}

-keep class com.google.common.base.Joiner {
    public static com.google.common.base.Joiner on(java.lang.String);
    public ** join(...);
}

-keep class com.google.common.collect.MapMakerInternalMap$ReferenceEntry
-keep class com.google.common.cache.LocalCache$ReferenceEntry

# http://stackoverflow.com/questions/9120338/proguard-configuration-for-guava-with-obfuscation-and-optimization
-dontwarn javax.annotation.**
-dontwarn javax.inject.**
-dontwarn sun.misc.Unsafe

# Guava 19.0
-dontwarn java.lang.ClassValue
-dontwarn com.google.j2objc.annotations.Weak
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement



# Security classes for keystore support
-dontwarn java.awt.**, javax.security.**, java.beans.**



# Volley
-dontwarn com.android.volley.**
-dontwarn com.android.volley.error.**
-keep class com.android.volley.** { *; }
-keep class com.android.volley.toolbox.** { *; }
-keep class com.android.volley.Response$* { *; }
-keep class com.android.volley.Request$* { *; }
-keep class com.android.volley.RequestQueue$* { *; }
-keep class com.android.volley.toolbox.HurlStack$* { *; }
-keep class com.android.volley.toolbox.ImageLoader$* { *; }
-keep interface com.android.volley.** { *; }
-keep class org.apache.commons.logging.*

All used dependencies: 所有使用的依赖项:

compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:design:23.4.0' 

compile 'com.google.code.gson:gson:2.7'
compile 'com.android.volley:volley:1.0.0' 
compile 'com.google.guava:guava:19.0'
compile 'org.apache.directory.studio:org.apache.commons.io:2.4'

compile 'com.madgag.spongycastle:core:1.54.0.0'
compile 'com.madgag.spongycastle:prov:1.54.0.0'
compile 'com.madgag.spongycastle:pkix:1.54.0.0'
compile 'com.madgag.spongycastle:pg:1.54.0.0'

And in addition to Volley failures, EventBus from Guava doesn't work correctly too (subscribe events are not fetching). 除Volley故障外, Guava EventBus也无法正常工作(订阅事件未获取)。 Do we have any solutions for these troubles? 对于这些麻烦,我们有什么解决方案吗? Should I add any additional information here? 我应该在这里添加任何其他信息吗?

Its difficult the pinpoint any error with the logs, however you should try it without using proguard. 很难确定日志中的任何错误,但是您应该在不使用proguard的情况下进行尝试。 skip the proguard file syntax and see if it works fine. 跳过proguard文件语法,然后查看它是否工作正常。 Make sure you have multidex enabled, else your project will fail to execute. 确保已启用multidex,否则您的项目将无法执行。

android {

compileSdkVersion 21
buildToolsVersion "21.1.0"

defaultConfig {
    ...
    minSdkVersion 14
    targetSdkVersion 21
    ...

    // Enabling multidex support.
    multiDexEnabled true
}
...
}

dependencies {
    compile 'com.android.support:multidex:1.0.0'
}

More details : https://developer.android.com/studio/build/multidex.html 更多详细信息: https : //developer.android.com/studio/build/multidex.html

Should admit, that even with all information provided, my question was very difficult to analyze, because of many possible sources of described errors. 应该承认,即使提供了所有信息,我的问题也很难分析,因为存在许多可能的描述错误。

I'll begin from the end of my question. 我将从问题的结尾开始。 Guava didn't work correctly, because ProGuard just excluded Guava's Subscribe-methods from my code to be packed. 番石榴无法正常工作,因为ProGuard只是从我要打包的代码中排除了番石榴的Subscribe-method。 ProGuard removes unused code, and as far as Subscribe-methods are analyzed as unused (even IDE don't highlight them as used ones) ProGuard has decided to remove these methods. ProGuard删除了未使用的代码,并且就订阅方法被分析为未使用(即使IDE也不将它们视为已使用的代码),ProGuard决定删除这些方法。 To solve this issue, we should keep Subscribe-methods from ProGuard's processing: 要解决此问题,我们应保留ProGuard处理过程中的订阅方法:

# Keep subscribe-methods from deletion
-keepclassmembers class ** {
  @com.google.common.eventbus.Subscribe <methods>;
}

And my first problem - when Volley always calls onErrorResponse callbacks in all requests being fired. 我的第一个问题-当Volley在所有被触发的请求中始终调用onErrorResponse回调时。 I used a custom deserializer for Json-repsonses which also checks, if server has provided some required fields (marked with a corresponding annotation). 我为Json-repsonses使用了一个自定义反序列化器,该反序列化器还会检查服务器是否提供了一些必填字段(标有相应的注释)。 And, of course, ProGuard by default could not work correctly with these annotations and deserializer - that's why I had to keep these entities too: 而且,当然,默认情况下,ProGuard无法与这些注释和反序列化器一起正常工作-这就是为什么我也必须保留这些实体的原因:

# To make right deserialization
-keepclassmembers class ** {
  @com.some.package.server.JsonDeserializerWithOptions$FieldRequired public *;
}
-keep @interface com.some.package.server.JsonDeserializerWithOptions$FieldRequired
-keep class com.some.package.server.JsonDeserializerWithOptions

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

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