【问题标题】:Retro fit responses crashes with pro guard复古合身响应与专业后卫崩溃
【发布时间】:2016-02-03 20:50:18
【问题描述】:

我有一个使用改造来进行 api 调用的应用程序。我正在尝试添加专业守卫,但其中一个响应一直失败。

FATAL EXCEPTION: main Process: com.karriapps.smartsiddurlite, PID: 13387
  java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object reference
       at com.karriapps.smartsiddur.util.b$3.a(SourceFile:255)
       at com.karriapps.smartsiddur.util.b$3.success(SourceFile:252)
       at retrofit.CallbackRunnable$1.run(SourceFile:45)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:135)
       at android.app.ActivityThread.main(ActivityThread.java:5431)
       at java.lang.reflect.Method.invoke(Native Method)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)

我知道响应包含数据,但它似乎无法反序列化它

这是失败的代码

mElavationService.getElevation(new ElavationService.LatLng(mLocation.getLatitude(), mLocation.getLongitude()),
            BING_KEY,
            new Callback<BingElevationResponse>() {
                @Override
                public void success(BingElevationResponse bingElevationResponse, Response response) {
                    double elavation = bingElevationResponse.getResourceSets().get(0)
                            .getResources().get(0).getOffsets().get(0);
                    if (elavation > 0) {
                        mLocation.setElevation(elavation);
                    } else {
                        mLocation.setElevation(0);
                    }
                    responsesCount++;
                    if (requestsCount == responsesCount) {
                        setZmanimToLocation(mLocation);
                    }
                }

                @Override
                public void failure(RetrofitError error) {
                    Log.e(TAG, error.toString(), error.fillInStackTrace());
                    mLocation.setElevation(0);
                    responsesCount++;
                    if (requestsCount == responsesCount) {
                        setZmanimToLocation(mLocation);
                    }
                }
            });

还有我的专业保护文件

# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/orel/Android/Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Proguard Configuration for Realm (http://realm.io)
# For detailed discussion see: https://groups.google.com/forum/#!topic/realm-java/umqKCc50JGU
# Additionally you need to keep your Realm Model classes as well
# For example:
# -keep class com.yourcompany.realm.** { *; }

-keep class io.realm.annotations.RealmModule
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep @io.realm.internal.Keep class *
-keepnames public class * extends io.realm.RealmObject
-dontwarn javax.**
-dontwarn io.realm.**

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

# Allow obfuscation of android.support.v7.internal.view.menu.**
# to avoid problem on Samsung 4.2.2 devices with appcompat v21
# see https://code.google.com/p/android/issues/detail?id=78377
-keep class !android.support.v7.internal.view.menu.**,android.support.** {*;}


# Crashlytics 2.+

-keep class com.crashlytics.** { *; }
-keep class com.crashlytics.android.**
-keepattributes SourceFile, LineNumberTable, *Annotation*

# If you are using custom exceptions, add this line so that custom exception types are skipped during obfuscation:
-keep public class * extends java.lang.Exception

# In App Billing
-keep class com.android.vending.billing.**

## Google Play Services 4.3.23 specific rules ##
## https://developer.android.com/google/play-services/setup.html#Proguard ##

-keep class * extends java.util.ListResourceBundle {
    protected Object[][] getContents();
}

-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
    public static final *** NULL;
}

-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
    @com.google.android.gms.common.annotation.KeepName *;
}

-keepnames class * implements android.os.Parcelable {
    public static final ** CREATOR;
}

## GSON 2.2.4 specific rules ##

# 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*

-keepattributes EnclosingMethod

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

## Joda Time 2.3

-dontwarn org.joda.convert.**
-dontwarn org.joda.time.**
-keep class org.joda.time.** { *; }
-keep interface org.joda.time.** { *; }

# OkHttp
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**

# Retrofit 1.X

-keep class retrofit.** { *; }
-keep class retrofit.http.** { *; }
-keep class retrofit.client.** { *; }
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }

-dontwarn com.squareup.okhttp.**
-dontwarn okio.**
-dontwarn retrofit.**
-dontwarn rx.**

-keepclasseswithmembers class * {
    @retrofit.http.* <methods>;
}

# If in your rest service interface you use methods with Callback argument.
-keepattributes Exceptions

#support design
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }

# http://stackoverflow.com/questions/29679177/cardview-shadow-not-appearing-in-lollipop-after-obfuscate-with-proguard/29698051
-keep class android.support.v7.widget.RoundRectDrawable { *; }

# mixpanel
-dontwarn com.mixpanel.**

# for play services
-dontwarn org.apache.http.**
-dontwarn android.net.http.AndroidHttpClient
-dontwarn com.google.android.gms.**

##---------------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.** { *; }
-keep class com.karriapps.smartsiddur.model.response.** { *; }
-keepnames public class com.karriapps.smartsiddur.model.response.**

# debug
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

编辑:我自己添加了 pojo 类

public class BingElevationResponse {

    private List<ResourceSet> resourceSets;

    public List<ResourceSet> getResourceSets() {
        return resourceSets;
    }

    public class ResourceSet {
        private List<Resource> resources;

        public List<Resource> getResources() {
            return resources;
        }
    }

    public class Resource {
        private List<Integer> elevations;

        public List<Integer> getOffsets() {
            return elevations;
        }
    }
}

它的路径是

com.karriapps.smartsiddur.model.response.BingElevationResponse

非常感谢 ant 的帮助 谢谢

【问题讨论】:

  • 您说其中一个响应失败了您能否给出用于该响应的 json 解析的类的全名?并尝试明确或更好地保留该类及其字段,但使用注释(@Serializedname for gson)将名称与 json 响应字段名称匹配
  • 使用注解更好?我会试试的
  • 是的,当然,然后 gson 不必反映获取字段名称,当字段名称被混淆时,它不会影响用于 psrsing 的 json 字段名称,因为 gson 将使用注释中的名称
  • 嗯,这没有帮助。我添加了注释,但它仍然崩溃并出现相同的异常
  • 啊,这是因为内部类尝试将 Resource 类重构到单独的类文件中,或者您需要添加它以保持这样-keep class com.karriapps.smartsiddur.model.response. BingElevationResponse$Resource 我建议重构为适当的类文件

标签: android retrofit android-proguard


【解决方案1】:

如果您正在使用 gson jackson 或任何此类 json 解析器库(我认为改造在内部使用一个我不确定)您需要 -keep 任何和所有 Pojo 类及其字段和名称!

编辑

在 java pojo 类字段中添加@SerializedName(在 gson 的情况下)注释也有帮助,因为 gson 不必反映和获取字段名称(其 proguard 更改,因此 gson 将使用错误的 json 字段名称来解析json)。此外,为了使注释起作用,您还需要将 -keepattributes *Annotation* 添加到您的 proguard 规则中。

【讨论】:

  • 谢谢。如果您可以查看我的专业保护文件的底部,我已尝试将其包含在内 -keep class com.karriapps.smartsiddur.model.response.** { ; } -keepnames 公共类 com.karriapps.smartsiddur.model.response.*
猜你喜欢
  • 2016-05-14
  • 2016-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-14
  • 1970-01-01
相关资源
最近更新 更多