Showing posts with label weather app. Show all posts

How to create Weather App using Retrofit 2 in Android

weather

Introduction: 

In this article, we will learn How to create our own weather app using Retrofit 2. There are a lot of providers available to provide weather data. In this tutorial we will use the famous provider “OpenWeatherMap” Api to build our own weather app. 

Coding Part: 

I have detailed the article as in the following steps. 
Step 1: Creating New Project with Empty Activity. 
Step 2: Setting up the Retrofit HTTP Library and Manifest. 
Step 3: Getting App ID from Open Weather API. 
Step 4: Implementation of consumption of Weather API using Retrofit.

Step 1: Creating New Project with Empty Activity.

  1. Creating New Project with Android Studio Open Android Studio and Select Create new project. 
  2. Name the project as your wish and select your activity template.

  3. Click “finish” button to create new project in Android Studio.

Step 2: Setting up the Retrofit Http Library and Manifest

In this part, we will see how to setup the library for the project.
  1. Then add the following lines in app level build.gradle file to apply google services to your project.
    dependencies {
        ...
        implementation 'com.squareup.retrofit2:retrofit:2.0.0'
        implementation 'com.squareup.retrofit2:converter-gson:2.0.0' 
    }
  2. Then click “Sync Now” to setup your project.
  3. Don't forget to add the following permission in your manifest file.
    <uses-permission android:name="android.permission.INTERNET"/>

Step 3: Getting App Id from Open Weather Map

  1. Open OpenWeatherMap Site and sign up for free to get your app id.

  2. You can find or create your app id in API Keys tab of the site after logged in. Find the screenshot for your reference.

Step 4: Implementation of consumption of Weather API using Retrofit

The following API link is used to get the current weather report respect to the geo-coordinates. The Sample API link is
https://openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=b6907d289e10d714a6e88b30761fae22
We will see, how to use the link to access the weather data.
  1. Create an interface file named as “WeatherService.java” and add the following lines
    public interface WeatherService {
        @GET("data/2.5/weather?")
        Call getCurrentWeatherData(@Query("lat") String lat, @Query("lon") String lon, @Query("APPID") String app_id);
    }
  2. Create a class file named as “WeatherResponse.java” and add the following lines. We will get the response as json as in the following.
    {
      "coord": {
        "lon": 139,
        "lat": 35
      },
      "sys": {
        "country": "JP",
        "sunrise": 1369769524,
        "sunset": 1369821049
      },
      "weather": [
        {
          "id": 804,
          "main": "clouds",
          "description": "overcast clouds",
          "icon": "04n"
        }
      ],
      "main": {
        "temp": 289.5,
        "humidity": 89,
        "pressure": 1013,
        "temp_min": 287.04,
        "temp_max": 292.04
      },
      "wind": {
        "speed": 7.31,
        "deg": 187.002
      },
      "rain": {
        "3h": 0
      },
      "clouds": {
        "all": 92
      },
      "dt": 1369824698,
      "id": 1851632,
      "name": "Shuzenji",
      "cod": 200
    }
  3. I have used json to java converter in online to generate the Response class and the equivalent java class should be should be shown below.
    public class WeatherResponse {
    
        @SerializedName("coord")
        public Coord coord;
        @SerializedName("sys")
        public Sys sys;
        @SerializedName("weather")
        public ArrayList weather = new ArrayList();
        @SerializedName("main")
        public Main main;
        @SerializedName("wind")
        public Wind wind;
        @SerializedName("rain")
        public Rain rain;
        @SerializedName("clouds")
        public Clouds clouds;
        @SerializedName("dt")
        public float dt;
        @SerializedName("id")
        public int id;
        @SerializedName("name")
        public String name;
        @SerializedName("cod")
        public float cod;
    }
    
    class Weather {
        @SerializedName("id")
        public int id;
        @SerializedName("main")
        public String main;
        @SerializedName("description")
        public String description;
        @SerializedName("icon")
        public String icon;
    }
    
    class Clouds {
        @SerializedName("all")
        public float all;
    }
    
    class Rain {
        @SerializedName("3h")
        public float h3;
    }
    
    class Wind {
        @SerializedName("speed")
        public float speed;
        @SerializedName("deg")
        public float deg;
    }
    
    class Main {
        @SerializedName("temp")
        public float temp;
        @SerializedName("humidity")
        public float humidity;
        @SerializedName("pressure")
        public float pressure;
        @SerializedName("temp_min")
        public float temp_min;
        @SerializedName("temp_max")
        public float temp_max;
    }
    
    class Sys {
        @SerializedName("country")
        public String country;
        @SerializedName("sunrise")
        public long sunrise;
        @SerializedName("sunset")
        public long sunset;
    }
    
    class Coord {
        @SerializedName("lon")
        public float lon;
        @SerializedName("lat")
        public float lat;
    }
    
  4. The SerializedName annotation is used to parsing the server response and their name & type should be same as the Json Response received from the server.
  5. Then initialize Retrofit to call the weather service. The following code snippet will help us to call the service.
    void getCurrentData() {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BaseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            WeatherService service = retrofit.create(WeatherService.class);
            Call call = service.getCurrentWeatherData(lat, lon, AppId);
            call.enqueue(new Callback() {
                @Override
                public void onResponse(@NonNull Call call, @NonNull Response response) {
                    if (response.code() == 200) {
                        WeatherResponse weatherResponse = response.body();
                        assert weatherResponse != null;
    
                        String stringBuilder = "Country: " +
                                weatherResponse.sys.country +
                                "\n" +
                                "Temperature: " +
                                weatherResponse.main.temp +
                                "\n" +
                                "Temperature(Min): " +
                                weatherResponse.main.temp_min +
                                "\n" +
                                "Temperature(Max): " +
                                weatherResponse.main.temp_max +
                                "\n" +
                                "Humidity: " +
                                weatherResponse.main.humidity +
                                "\n" +
                                "Pressure: " +
                                weatherResponse.main.pressure;
    
                        weatherData.setText(stringBuilder);
                    }
                }
    
                @Override
                public void onFailure(@NonNull Call call, @NonNull Throwable t) {
                    weatherData.setText(t.getMessage());
                }
            });
        }
    
    Here we used Gson Converter and so the json response automatically converted to the respective and the converter will compare the response tree with the serialized name.
  6. Our own developed weather app is ready.

Full Code:

You can find the full code implementation of the app here.
public class MainActivity extends AppCompatActivity {

    public static String BaseUrl = "http://api.openweathermap.org/";
    public static String AppId = "2e65127e909e178d0af311a81f39948c";
    public static String lat = "35";
    public static String lon = "139";

    private TextView weatherData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        weatherData = findViewById(R.id.textView);

        Typeface typeface = Typeface.createFromAsset(getAssets(), "Lato-Bold.ttf");
        FontUtils fontUtils = new FontUtils();
        fontUtils.applyFontToView(weatherData, typeface);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getCurrentData();
            }
        });
    }

    void getCurrentData() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BaseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        WeatherService service = retrofit.create(WeatherService.class);
        Call call = service.getCurrentWeatherData(lat, lon, AppId);
        call.enqueue(new Callback() {
            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) {
                if (response.code() == 200) {
                    WeatherResponse weatherResponse = response.body();
                    assert weatherResponse != null;

                    String stringBuilder = "Country: " +
                            weatherResponse.sys.country +
                            "\n" +
                            "Temperature: " +
                            weatherResponse.main.temp +
                            "\n" +
                            "Temperature(Min): " +
                            weatherResponse.main.temp_min +
                            "\n" +
                            "Temperature(Max): " +
                            weatherResponse.main.temp_max +
                            "\n" +
                            "Humidity: " +
                            weatherResponse.main.humidity +
                            "\n" +
                            "Pressure: " +
                            weatherResponse.main.pressure;

                    weatherData.setText(stringBuilder);
                }
            }

            @Override
            public void onFailure(@NonNull Call call, @NonNull Throwable t) {
                weatherData.setText(t.getMessage());
            }
        });
    }

}
To know more about Retrofit and Open Weather API
  1. https://openweathermap.org/api
  2. https://square.github.io/retrofit/

Download Code

You can download the full source code of the article in GitHub. If you like this article, do star the repo in GitHub. Hit like the article.