Search code examples
androidretrofit2weather-api

Retrofit- handle invalid data in search option


I'm creating weather app where I'm giving option to user to search weather by any city. when user enter valid city name my app work fine , but when user enter invalid string ex: asndfs,bdfbsj then my app terminate .

how to handle this? so that my app wont terminate instead give message to user saying that please enter valid city name

here is my code when user enter string and i make call to openWeatherApi.

private void getWeatherDataByCity(String city) {
    params = new HashMap<>();
    params.put(Constants.CITY, city);
    params.put(Constants.UNIT, Constants.UNITS);
    params.put(Constants.APP_ID, Constants.API_KEY);
    RetrofitClient.getData(params).enqueue(new Callback<Result>() {
        @Override
        public void onResponse(Call<Result> call, Response<Result> response) {
            cityName.setText(response.body().getCityName() + "," + response.body().getSys().getCounty());
            String temperature = String.format("%.2f", response.body().getMain().getTemp()) + "°C";
            temp.setText(temperature);

        }

        @Override
        public void onFailure(Call<Result> call, Throwable t) {
        }
    });
}

Json response when user enter valid city:

{
    "coord": {
        "lon": 77.22,
        "lat": 28.65
    },
    "weather": [
        {
            "id": 721,
            "main": "Haze",
            "description": "haze",
            "icon": "50d"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 305.15,
        "pressure": 1008,
        "humidity": 43,
        "temp_min": 305.15,
        "temp_max": 305.15
    },
    "visibility": 3000,
    "wind": {
        "speed": 5.7,
        "deg": 110
    },
    "clouds": {
        "all": 20
    },
    "dt": 1525413600,
    "sys": {
        "type": 1,
        "id": 7809,
        "message": 0.0996,
        "country": "IN",
        "sunrise": 1525392476,
        "sunset": 1525440495
    },
    "id": 1273294,
    "name": "Delhi",
    "cod": 200
}

Json respone when user enter invalid city:

{
    "cod": "404",
    "message": "city not found"
}

Result.java

public class Result {
    @SerializedName("main")
    private Temprature main;
    @SerializedName("sys")
    private Sys sys;
    @SerializedName("cod")
    private int cod;
    @SerializedName("message")
    private String message;
    @SerializedName("name")
    private String cityName;
    @SerializedName("weather")
    private List<Weather> weather = new ArrayList<>();

    public List<Weather> getWeather() {
        return weather;
    }

    public Temprature getMain() {
        return main;
    }

    public Sys getSys() {
        return sys;
    }

    public String getCityName() {
        return cityName;
    }

    public int getCod() {
        return cod;
    }

    public String getMessage() {
        return message;
    }
}

Solution

  • Your app terminates because it is looking for a json field that does not exist because of the wrong name. try this:

     public void onResponse(Call<Result> call, Response<Result> response) {
                if (response.code() == 404) {
                    Toast.makeText(MainActivity.this, response.message(), Toast.LENGTH_SHORT).show();
                    cityName.setText(response.message());
                    temp.setText("0" + "°C");
                } else {
                    cityName.setText(response.body().getCityName() + "," +
                            response.body().getSys().getCounty());
                    String temperature = String.format("%.2f", response.body().getMain().getTemp()) + "°C";
                    temp.setText(temperature);
                }
            }
    

    EDIT: I don't know how to take the json from a Response of type result and right now i cant keep looking but all you need todo is check if the "cod" of your response is different from 404 before you try to parse the json