There are a lots of weather application available in Google Play Store. Bt you may want to develop your own weather application in Android Studio. Oh, don’t worry, you don’t need to setup a weather station in each city on each country to get weather information in your app. There are free APIs available in the market to use them to get weather information like Temperature, Pressure, Humidity, Weather status, Time of Sunrise and Sunset etc. Today in this tutorial I’ll walk you through creating an android weather app using JAVA in Android Studio.

There are many websites you can get by searching on the Google which supply free weather API, but In this tutorial we are going to use a API provided by OpenWeatherMap. So let’s start to create a weather app.

You can directly download the full Android Studio Project below, but I would suggest to read the article first for your better understanding.

Download Weather App in Java Source Code

Download the Android Studio source code of Weather App using Java in Android
Size: 169.83 Kb

You can also find the project in GitHub.

Get an API key from OpenWeatherMap

For retrieving data we will use OpenWeather API, and we will be needing an API key for it. Before proceeding please get an API key by registering. You can either follow the attached video above or steps below.

  • Create a New Account from here.
  • After login go to here to get the API Key.

Request Internet Access Permission

Apps that need to access Internet must request Internet permission. You can request for INTERNET permission in your AndroidManifest.xml

Add these permissions in your AndroidManifest.xml like below:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.frsarker.weatherapp">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Now we will modify the default design of AppTheme style to remove android’s default ActionBar.

Change Default Theme Style

We will be using a custom style to disable the default ActionBar, we can use Theme.AppCompat.Light.NoActionBar to implement the theme. Also I’ll set the default text color to White so that I need not write the text color in all views later.

This is my styles.xml looks like after modifying the default theme.

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">#122259</item>
    <item name="colorPrimaryDark">#122259</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:textColor">#FFFFFF</item>
</style>

Please remember that I only did this for my design purpose. If you need the default action bar you shouldn’t do that.

Designing the Layout

You have already noticed from the demo design of this article that we will use a gradient background in this weather app tutorial. But we’ll not use any image for this gradient background. Rather this can be implemented using a Drawable Resource file. You can create this from Right click on “app” => “New” => “Android Resource file“. Then select Drawble as Resource type. I named it bg_gradient.xml

This is the code for our bg_gradient.xml file:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:angle="90"
        android:startColor="#9561a1"
        android:endColor="#122259"
        android:type="linear"/>
</shape>

Now for our designing purpose we’ll need to use some icons like for humidity, pressure, sunrise, sunset etc. Download the images I used for this tutorial. Extract the zip file and paste the images into your “res” => “drawable” directory.

Drawable images for Weather App

Download the images and place them into your res -> drawable directory.
Size: 26.53 Kb

Finally we’ll design our activity_main.xml layout resource file.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_gradient"
    android:orientation="vertical"
    android:padding="25dp">

    <RelativeLayout
        android:id="@+id/mainContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="visible">

        <LinearLayout
            android:id="@+id/addressContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/address"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="DHAKA, BD"
                android:textSize="24dp" />

            <TextView
                android:id="@+id/updated_at"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="20 April 2012, 20:08 PM"
                android:textSize="14dp" />
        </LinearLayout>


        <LinearLayout
            android:id="@+id/overviewContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:orientation="vertical">

            <TextView
                android:id="@+id/status"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="Clear Sky"
                android:textSize="18dp" />

            <TextView
                android:id="@+id/temp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:fontFamily="sans-serif-thin"
                android:text="29°C"
                android:textSize="90dp" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/temp_min"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Min Temp: 05:05 AM" />

                <Space
                    android:layout_width="50dp"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/temp_max"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Max Temp: 05:05 PM" />
            </LinearLayout>

        </LinearLayout>


        <LinearLayout
            android:id="@+id/detailsContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:weightSum="3">

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#3CF1EBF1"
                    android:gravity="center"
                    android:orientation="vertical"
                    android:padding="8dp">

                    <ImageView
                        android:layout_width="25dp"
                        android:layout_height="25dp"
                        android:src="@drawable/sunrise"
                        android:tint="#FFFFFF" />

                    <Space
                        android:layout_width="wrap_content"
                        android:layout_height="5dp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Sunrise"
                        android:textSize="12dp" />

                    <TextView
                        android:id="@+id/sunrise"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="06:40 AM"
                        android:textSize="14dp" />
                </LinearLayout>

                <Space
                    android:layout_width="10dp"
                    android:layout_height="wrap_content" />

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#3CF1EBF1"
                    android:gravity="center"
                    android:orientation="vertical"
                    android:padding="8dp">

                    <ImageView
                        android:layout_width="25dp"
                        android:layout_height="25dp"
                        android:src="@drawable/sunset"
                        android:tint="#FFFFFF" />

                    <Space
                        android:layout_width="wrap_content"
                        android:layout_height="5dp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Sunset"
                        android:textSize="12dp" />

                    <TextView
                        android:id="@+id/sunset"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="06:40 AM"
                        android:textSize="14dp" />
                </LinearLayout>

                <Space
                    android:layout_width="10dp"
                    android:layout_height="wrap_content" />

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#3CF1EBF1"
                    android:gravity="center"
                    android:orientation="vertical"
                    android:padding="8dp">

                    <ImageView
                        android:layout_width="25dp"
                        android:layout_height="25dp"
                        android:src="@drawable/wind"
                        android:tint="#FFFFFF" />

                    <Space
                        android:layout_width="wrap_content"
                        android:layout_height="5dp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Wind"
                        android:textSize="12dp" />

                    <TextView
                        android:id="@+id/wind"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="06:40 AM"
                        android:textSize="14dp" />
                </LinearLayout>
            </LinearLayout>

            <Space
                android:layout_width="wrap_content"
                android:layout_height="10dp" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:weightSum="3">

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#3CF1EBF1"
                    android:gravity="center"
                    android:orientation="vertical"
                    android:padding="8dp">

                    <ImageView
                        android:layout_width="25dp"
                        android:layout_height="25dp"
                        android:src="@drawable/pressure"
                        android:tint="#FFFFFF" />

                    <Space
                        android:layout_width="wrap_content"
                        android:layout_height="5dp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Pressure"
                        android:textSize="12dp" />

                    <TextView
                        android:id="@+id/pressure"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="06:40 AM"
                        android:textSize="14dp" />
                </LinearLayout>

                <Space
                    android:layout_width="10dp"
                    android:layout_height="wrap_content" />

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#3CF1EBF1"
                    android:gravity="center"
                    android:orientation="vertical"
                    android:padding="8dp">

                    <ImageView
                        android:layout_width="25dp"
                        android:layout_height="25dp"
                        android:src="@drawable/humidity"
                        android:tint="#FFFFFF" />

                    <Space
                        android:layout_width="wrap_content"
                        android:layout_height="5dp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Humidity"
                        android:textSize="12dp" />

                    <TextView
                        android:id="@+id/humidity"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="06:40 AM"
                        android:textSize="14dp" />
                </LinearLayout>

                <Space
                    android:layout_width="10dp"
                    android:layout_height="wrap_content" />

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#3CF1EBF1"
                    android:gravity="center"
                    android:orientation="vertical"
                    android:padding="8dp">

                    <ImageView
                        android:layout_width="25dp"
                        android:layout_height="25dp"
                        android:src="@drawable/info"
                        android:tint="#FFFFFF" />

                    <Space
                        android:layout_width="wrap_content"
                        android:layout_height="5dp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Created By"
                        android:textSize="12dp" />

                    <TextView
                        android:id="@+id/about"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="frsarker"
                        android:textSize="14dp" />
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    </RelativeLayout>


    <ProgressBar
        android:id="@+id/loader"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:visibility="gone" />

    <TextView
        android:id="@+id/errorText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Something went wrong"
        android:visibility="gone" />


</RelativeLayout>

You can always do your necessary modifications in your own way.

Fetch and Populate Weather Data using OpenWeatherMap

We have already found our API Key from OpenWeatherMap. The API key will be used to fetch weather data from a Rest API. To fetch data from a Rest API, we will have to use HttpURLConnection and make a request to the URL of the api. For making the request, we will create a Java Class and write the codes that will help us to fetch data from an API using GET method.

This is our HttpRequest.java class.

package com.frsarker.weatherapp;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpRequest {
    public static String excuteGet(String targetURL) {
        URL url;
        HttpURLConnection connection = null;
        try {
            url = new URL(targetURL);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");

            InputStream is;
            int status = connection.getResponseCode();
            if (status != HttpURLConnection.HTTP_OK)
                is = connection.getErrorStream();
            else
                is = connection.getInputStream();

            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuffer response = new StringBuffer();
            while ((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            return response.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}

Now we will use the HttpRequest class to fetch data from API into our MainActivity.java using AsyncTask and the returned data will be populated into our views.

This is our MainActivity.java class. I’ll describe them later.

package com.frsarker.weatherapp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import org.json.JSONException;
import org.json.JSONObject;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    String CITY = "dhaka,bd";
    String API = "8118ed6ee68db2debfaaa5a44c832918";

    TextView addressTxt, updated_atTxt, statusTxt, tempTxt, temp_minTxt, temp_maxTxt, sunriseTxt,
            sunsetTxt, windTxt, pressureTxt, humidityTxt;

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

        addressTxt = findViewById(R.id.address);
        updated_atTxt = findViewById(R.id.updated_at);
        statusTxt = findViewById(R.id.status);
        tempTxt = findViewById(R.id.temp);
        temp_minTxt = findViewById(R.id.temp_min);
        temp_maxTxt = findViewById(R.id.temp_max);
        sunriseTxt = findViewById(R.id.sunrise);
        sunsetTxt = findViewById(R.id.sunset);
        windTxt = findViewById(R.id.wind);
        pressureTxt = findViewById(R.id.pressure);
        humidityTxt = findViewById(R.id.humidity);

        new weatherTask().execute();

    }


    class weatherTask extends AsyncTask<String, Void, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            /* Showing the ProgressBar, Making the main design GONE */
            findViewById(R.id.loader).setVisibility(View.VISIBLE);
            findViewById(R.id.mainContainer).setVisibility(View.GONE);
            findViewById(R.id.errorText).setVisibility(View.GONE);
        }

        protected String doInBackground(String... args) {
            String response = HttpRequest.excuteGet("https://api.openweathermap.org/data/2.5/weather?q=" + CITY + "&units=metric&appid=" + API);
            return response;
        }

        @Override
        protected void onPostExecute(String result) {


            try {
                JSONObject jsonObj = new JSONObject(result);
                JSONObject main = jsonObj.getJSONObject("main");
                JSONObject sys = jsonObj.getJSONObject("sys");
                JSONObject wind = jsonObj.getJSONObject("wind");
                JSONObject weather = jsonObj.getJSONArray("weather").getJSONObject(0);

                Long updatedAt = jsonObj.getLong("dt");
                String updatedAtText = "Updated at: " + new SimpleDateFormat("dd/MM/yyyy hh:mm a", Locale.ENGLISH).format(new Date(updatedAt * 1000));
                String temp = main.getString("temp") + "°C";
                String tempMin = "Min Temp: " + main.getString("temp_min") + "°C";
                String tempMax = "Max Temp: " + main.getString("temp_max") + "°C";
                String pressure = main.getString("pressure");
                String humidity = main.getString("humidity");

                Long sunrise = sys.getLong("sunrise");
                Long sunset = sys.getLong("sunset");
                String windSpeed = wind.getString("speed");
                String weatherDescription = weather.getString("description");

                String address = jsonObj.getString("name") + ", " + sys.getString("country");


                /* Populating extracted data into our views */
                addressTxt.setText(address);
                updated_atTxt.setText(updatedAtText);
                statusTxt.setText(weatherDescription.toUpperCase());
                tempTxt.setText(temp);
                temp_minTxt.setText(tempMin);
                temp_maxTxt.setText(tempMax);
                sunriseTxt.setText(new SimpleDateFormat("hh:mm a", Locale.ENGLISH).format(new Date(sunrise * 1000)));
                sunsetTxt.setText(new SimpleDateFormat("hh:mm a", Locale.ENGLISH).format(new Date(sunset * 1000)));
                windTxt.setText(windSpeed);
                pressureTxt.setText(pressure);
                humidityTxt.setText(humidity);

                /* Views populated, Hiding the loader, Showing the main design */
                findViewById(R.id.loader).setVisibility(View.GONE);
                findViewById(R.id.mainContainer).setVisibility(View.VISIBLE);


            } catch (JSONException e) {
                findViewById(R.id.loader).setVisibility(View.GONE);
                findViewById(R.id.errorText).setVisibility(View.VISIBLE);
            }

        }
    }
}

First of all, as we need to grab weather information from an API, so we’ll make a http request to the URL of the API, and this is where we’ll use AsyncTask.

AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

As you can see in our AsyncTask named as “weatherTask()”, we displayed the ProgressBar in onPreExecute() so that user can understand that the app is making request to the url for getting weather information.

Then in the doInBackground(Params) we create a http request to the API url. As you imported my library into your project, now you can easily make a HTTP Request to return the result only using HttpRequest.excuteGet() method. CITY is the value of our search query to find weather information of a specific place and API is the API Key that we got from OpenWeatherMap. Both of them are declared as:

String CITY = "dhaka,bd";
String API = "8118ed6ee68db2debfaaa5a44c832918";

I have requested Weather Information for Dhaka city of Bangladesh. If you want the information of Delhi of India then it will be delhi,in. You can also find the city and country name from OpenWeatherMap’s Weather in your city page.

We requested the API as:

String response = HttpRequest.excuteGet("https://api.openweathermap.org/data/2.5/weather?q=" + CITY + "&units=metric&appid=" + API);

Suppose you want to request weather information using a Latitude & Longitude of a place, then you should use:

String response = HttpRequest.excuteGet("https://api.openweathermap.org/data/2.5/weather?lat=" + LAT + "&lon=" + LON + "&units=metric&appid=" + API);

where LAT and LON will be the Latitude & Longitude respectively. If you want to implement this project to display weather information of user’s current location you’ll just need detect the current latitude & longitude. I’ve already posted an article on Detect Current Latitude & Longitude using Java in Android.

Then the response from the url will be passed to the onPostExecute(Result). As the API passes weather information in JSON format, we’ll extract the data so that we can later set the extracted data into our views.

At last we called the AsyncTask class from our onCreate() method using new weatherTask().execute();

Now run the application and if you find any issues please let me know.