【问题标题】:Android Release APK Not Parsing JSON From Web Service with SSL Using Retrofit2Android 发布 APK 不使用 Retrofit2 从带有 SSL 的 Web 服务解析 JSON
【发布时间】:2019-01-30 21:40:13
【问题描述】:

我使用 SSL 创建了一个 REST Web 服务,即https://api.bmcstudios.org

我要达到的端点是:

GET https://api.bmcstudios.org/member

预期的反应是

{
    "members": [
        {
            "memberId": "5c4e448d46e0fb0001656a46",
            "email": "email@gmail.com",
            "displayName": "username",
            "firstName": "First",
            "lastName": "Last",
            "address": {
                "street_1": "Street Address 1",
                "street_2": "",
                "city": "City",
                "state": "ST",
                "zipCode": 55555,
                "country": "US"
            },
            "phone": "123-456-7890",
            "roles": [
                {
                    "id": "5c47fe53473d4ad05bdf99f5",
                    "role": "ROLE_MEMBER"
                }
            ]
        }
    ]
}

我在使用 Postman 和运行 Android 模拟器 Pixel 2 XL API 28 时收到此响应。

当我通过最新版本的 Android Studio 3.3 中的 Android App Bundle 将我的构建部署到 Google Play 商店时,通过Internal Test TrackProduction Track 我能够访问我的网络服务。但是我返回的响应是空的!

这是我的日志显示的响应:

I/System.out: appWebservice.getMemberDetails(): {"members":[{},{},{}]}

结构存在,但数组中的成员对象不显示。下面是我的 Java 代码:

Retrofit2 界面

public interface AppWebservice {
    String API_URL = "https://api.bmcstudios.org/";

    Gson gson = new GsonBuilder()
                        .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                        .create();

    Retrofit RETROFIT = new Retrofit.Builder()
                                .baseUrl(API_URL)
                                .addConverterFactory(GsonConverterFactory.create(gson))
                                .build();

    // MEMBER
    @GET("member")
    Call<MemberResponse> getMemberDetails(
            @HeaderMap Map<String, String> headers);
}

成员响应对象

@Getter
@Setter
@NoArgsConstructor
public class MemberResponse implements Serializable {
    @SerializedName("members")
    @Expose
    private List<Member> members;

    @Getter
    @Setter
    @NoArgsConstructor
    public class Member implements Serializable {
        @SerializedName("memberId")
        @Expose
        private String memberId;
        @SerializedName("email")
        @Expose
        private String email;
        @SerializedName("displayName")
        @Expose
        private String displayName;
        @SerializedName("firstName")
        @Expose
        private String firstName;
        @SerializedName("lastName")
        @Expose
        private String lastName;
        @SerializedName("picture")
        @Expose
        private String picture;
        @SerializedName("address")
        @Expose
        private Address address;
        @SerializedName("phone")
        @Expose
        private String phone;
        @SerializedName("roles")
        @Expose
        private List<Role> roles;

        @Getter
        @Setter
        @NoArgsConstructor
        public class Address implements Serializable {
            @SerializedName("street_1")
            @Expose
            private String street1;
            @SerializedName("street_2")
            @Expose
            private String street2;
            @SerializedName("city")
            @Expose
            private String city;
            @SerializedName("state")
            @Expose
            private String state;
            @SerializedName("zipCode")
            @Expose
            private Integer zipCode;
            @SerializedName("country")
            @Expose
            private String country;
        }

        @Getter
        @Setter
        @NoArgsConstructor
        public class Role implements Serializable {
            @SerializedName("id")
            @Expose
            private String id;
            @SerializedName("role")
            @Expose
            private String role;
        }
    }
}

在应用内调用服务:

public void getMemberDetails() {
        if (getIdToken().getValue() == null) {
            updateIdToken();
        } else {
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-type", "application/json");
            headers.put(FIREBASE_AUTH_HEADER, getIdToken().getValue());

            appWebservice.getMemberDetails(headers)
                    .enqueue(new Callback<MemberResponse>() {
                        @Override
                        public void onResponse(
                                @NonNull Call<MemberResponse> call,
                                @NonNull retrofit2.Response<MemberResponse> response) {
                            if (response.body() != null) {
                                System.out.println("appWebservice.getMemberDetails(): " + new Gson().toJson(response.body()));

                                for (MemberResponse.Member member : response.body().getMembers()) {
                                    MemberEntity memberEntity =
                                            toEntity(new Gson().toJson(member));

                                    if (isNotBlank(memberEntity.getMemberId())) {
                                        repository.storeMemberDetails(memberEntity);
                                    }
                                }
                            }
                        }

                        @Override
                        public void onFailure(
                                @NonNull Call<MemberResponse> call, @NonNull Throwable t) {
                            System.err.println("appWebservice.getMemberDetails(): " + t.getMessage());
                        }
                    });
        }
    }

我没有接通onFailure 呼叫,因为服务呼叫成功。我收到一个 json 响应,但它似乎没有正确解析,即数组中的对象缺少数据。

仅当我通过 google play 商店部署我的 .apk 时才会出现此问题。

请帮我解决这个问题!谢谢

【问题讨论】:

    标签: android json apk retrofit2 android-webservice


    【解决方案1】:

    这个问题在这里得到了回答Gson Not mapping data in Production Mode APK Android

    将此添加到您的 proguard 规则中

    # 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
    
    # 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.example.YourPackage.** { *; }
    

    【讨论】:

      【解决方案2】:

      我能够使用名为 JsonElement 的 Gson 对象解决此问题

      https://google.github.io/gson/apidocs/com/google/gson/JsonElement.html

      我将MemberResponse 对象替换为JsonElement 对象,然后通过JsonObjectJsonArray 手动解析我的数据。结果很完美。

      这是更新的文件。

      public interface AppWebservice {
          String API_URL = "https://api.bmcstudios.org/";
      
          Gson gson = new GsonBuilder()
                              .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                              .create();
      
          Retrofit RETROFIT = new Retrofit.Builder()
                                      .baseUrl(API_URL)
                                      .addConverterFactory(GsonConverterFactory.create(gson))
                                      .build();
      
          // MEMBER
          @GET("member")
          Call<JsonElement> getMemberDetails(
                  @HeaderMap Map<String, String> headers);
      }
      
      public void getMemberDetails() {
          if (getIdToken().getValue() == null) {
              updateIdToken();
          } else {
              Map<String, String> headers = new HashMap<>();
              headers.put("Content-type", "application/json");
              headers.put(FIREBASE_AUTH_HEADER, getIdToken().getValue());
      
              appWebservice.getMemberDetails(headers)
                      .enqueue(new Callback<JsonElement>() {
                          @Override
                          public void onResponse(
                                  @NonNull Call<JsonElement> call,
                                  @NonNull retrofit2.Response<JsonElement> response) {
                              if (response.body() != null) {
                                  System.out.println("appWebservice.putMemberDetails(): " + new Gson().toJson(response.body()));
      
                                  JsonObject jsonObject = response.body().getAsJsonObject();
                                  if (jsonObject.has("members")) {
                                      JsonArray members = jsonObject.getAsJsonArray("members");
                                      for (JsonElement memberElement : members) {
                                          MemberEntity memberEntity =
                                                  toEntity(new Gson().toJson(memberElement));
      
                                          if (isNotBlank(memberEntity.getMemberId())) {
                                              repository.storeMemberDetails(memberEntity);
      
                                              member.postValue(Member.toMember(memberEntity));
                                          }
                                      }
                                  }
                              }
                          }
      
                          @Override
                          public void onFailure(
                                  @NonNull Call<JsonElement> call, @NonNull Throwable t) {
                              System.err.println("appWebservice.getMemberDetails(): " + t.getMessage());
                          }
                      });
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-07
        • 1970-01-01
        • 2018-12-25
        • 2017-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多