In this blog I'll walk you through creating a fully functional weather app for Android devices. Whether you're a beginner or an experienced developer, this tutorial will help you master the art of building a sleek, user-friendly app to display real-time weather information.
What You'll Learn in This Tutorial:
- Setting up Android Studio and creating a new project
- Designing a Professional user-friendly interface with XML layouts
- Fetching real-time weather data using APIs like OpenWeatherMap
- Parsing JSON data for meaningful weather insights
First create a nice looking UI for showing weather info. The code snippet for android_main.xml is as follows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:background="@drawable/background"
>
<TextView
android:id="@+id/cityNameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:fontFamily="@font/urbanist"
android:text="City"
android:textSize="36sp"
android:textColor="@color/white"
/>
<TextView
android:id="@+id/temperatureText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:fontFamily="@font/urbanist"
android:text="25°"
android:textColor="#FFBF00"
android:textSize="60sp"
android:textStyle="bold"
android:layout_below="@id/cityNameText"/>
</LinearLayout>
<ImageView
android:id="@+id/weatherIcon"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_below="@id/detailsLayout"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:elevation="12dp"
android:src="@drawable/ic_01d"
android:contentDescription="Weather Icon"
/>
<TextView
android:id="@+id/descriptionText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/weatherIcon"
android:textColor="@color/white"
android:layout_centerHorizontal="true"
android:fontFamily="@font/urbanist"
android:text="Sunny"
android:textSize="28sp"
/>
<EditText
android:id="@+id/cityNameInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/descriptionText"
android:textColor="#EFEFEF"
android:padding="12dp"
android:textColorHint="#BFBFBF"
android:gravity="center"
android:fontFamily="@font/urbanist"
android:textSize="24sp"
android:layout_marginTop="20dp"
android:hint="Enter City Name"
/>
<Button
android:id="@+id/fetchWeatherButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/cityNameInput"
android:backgroundTint="#2B3A67"
android:fontFamily="@font/urbanist"
android:text="Change City"
android:textColor="#FFF"
android:textSize="20sp"
/>
</RelativeLayout>
The code snippet for MainActivity.java is as follows:
package com.codingtutorials.weatherapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainActivity extends AppCompatActivity {
private TextView cityNameText, temperatureText, humidityText, descriptionText, windText;
private ImageView weatherIcon;
private Button refreshButton;
private EditText cityNameInput;
private static final String API_KEY = "******************************"; // your own API Key
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cityNameText = findViewById(R.id.cityNameText);
temperatureText = findViewById(R.id.temperatureText);
humidityText = findViewById(R.id.humidityText);
windText= findViewById(R.id.windText);
descriptionText = findViewById(R.id.descriptionText);
weatherIcon = findViewById(R.id.weatherIcon);
refreshButton = findViewById(R.id.fetchWeatherButton);
cityNameInput = findViewById(R.id.cityNameInput);
refreshButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String cityName = cityNameInput.getText().toString();
if(!cityName.isEmpty())
{
FetchWeatherData(cityName);
}
else
{
cityNameInput.setError("Please enter a city name");
}
}
});
FetchWeatherData("Mumbai");
}
private void FetchWeatherData(String cityName) {
String url = "https:api.openweathermap.org/data/2.5/weather?q="+cityName + "&appid="+ API_KEY + "&units=metric";
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(() ->
{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
try {
Response response = client.newCall(request).execute();
String result = response.body().string();
runOnUiThread(() -> updateUI(result));
} catch (IOException e)
{
e.printStackTrace();;
}
}
);
}
private void updateUI(String result)
{
if(result != null)
{
try {
JSONObject jsonObject = new JSONObject(result);
JSONObject main = jsonObject.getJSONObject("main");
double temperature = main.getDouble("temp");
double humidity = main.getDouble("humidity");
double windSpeed = jsonObject.getJSONObject("wind").getDouble("speed");
String description = jsonObject.getJSONArray("weather").getJSONObject(0).getString("description");
String iconCode = jsonObject.getJSONArray("weather").getJSONObject(0).getString("icon");
String resourceName = "ic_" + iconCode;
int resId = getResources().getIdentifier(resourceName, "drawable", getPackageName());
weatherIcon.setImageResource(resId);
cityNameText.setText(jsonObject.getString("name"));
temperatureText.setText(String.format("%.0f°", temperature));
humidityText.setText(String.format("%.0f%%", humidity));
windText.setText(String.format("%.0f km/h", windSpeed));
descriptionText.setText(description);
} catch (JSONException e)
{
e.printStackTrace();
}
}
}
}
Following dependencies needed to be updated in graddle (app level) for accessible web data implementation("com.squareup.okhttp3:okhttp:4.9.3")
dependencies { implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.constraintlayout:constraintlayout:2.2.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
implementation("com.squareup.okhttp3:okhttp:4.9.3")
}
The code snippet for Android_Manifest.xml is as follows:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET">
<application android:allowbackup="true" android:dataextractionrules="@xml/data_extraction_rules" android:fullbackupcontent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundicon="@mipmap/ic_launcher_round" android:supportsrtl="true" android:theme="@style/Theme.WeatherApp" tools:targetapi="31">
<activity android:exported="true" android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN">
<category android:name="android.intent.category.LAUNCHER">
</category></action>
</intent-filter>
</activity>
<meta-data android:name="preloaded_fonts" android:resource="@array/preloaded_fonts"/>
</application>
</manifest>
Comments
Post a Comment