In this tutorial, we will learn how to create a weather app using Kotlin and the Android platform. The app will fetch weather data from an API and display it in a user-friendly format.
Prerequisites
Before getting started, make sure you have the following:
- Android Studio installed on your machine.
- Basic knowledge of Kotlin programming language.
- An API key (we will be using the OpenWeatherMap API in this tutorial).
Setting up the Project
- Open Android Studio and click on “Start a new Android Studio project”.
- Select “Empty Activity” and click “Next”.
- Enter a name for your project and select a package name. Also, make sure the language is set to Kotlin. Click “Finish” to create the project.
Adding necessary dependencies
Open the build.gradle
file of your app module and add the following dependencies:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.google.code.gson:gson:2.8.8'
implementation 'com.github.bumptech.glide:glide:4.12.0'
Once the dependencies are added, sync your project.
Creating the Weather Service
Next, we will create a weather service that fetches weather data from the OpenWeatherMap API. Create a new Kotlin class called WeatherService
and add the following code:
import okhttp3.OkHttpClient
import okhttp3.Request
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.google.gson.Gson
class WeatherService(private val apiKey: String) {
private val client = OkHttpClient()
suspend fun getWeather(city: String): WeatherData {
val url = "https://api.openweathermap.org/data/2.5/weather?q=$city&appid=$apiKey"
val request = Request.Builder().url(url).build()
return withContext(Dispatchers.IO) {
val response = client.newCall(request).execute()
val body = response.body()?.string()
Gson().fromJson(body, WeatherData::class.java)
}
}
}
In the getWeather
function, we use the OkHttpClient
to make a network request to the OpenWeatherMap API. The response is then converted into a WeatherData
object using Gson.
Creating the WeatherData model
Next, we will create a Kotlin data class called WeatherData
that represents the weather data returned by the API. Add the following code to the WeatherData.kt
file:
data class WeatherData(
val name: String,
val main: MainData,
val weather: List<Weather>
)
data class MainData(
val temp: Double,
val humidity: Int
)
data class Weather(
val main: String,
val description: String,
val icon: String
)
The WeatherData
class contains properties like the city name, temperature, humidity, and a list of weather conditions. The MainData
class represents the main weather data, and the Weather
class represents a single weather condition.
Creating the MainActivity layout
Open the activity_main.xml
layout file and replace the default code with the following:
<RelativeLayout xmlns_android="http://schemas.android.com/apk/res/android"
xmlns_tools="http://schemas.android.com/tools"
android_id="@+id/container"
android_layout_width="match_parent"
android_layout_height="match_parent"
android_paddingBottom="@dimen/activity_vertical_margin"
android_paddingLeft="@dimen/activity_horizontal_margin"
android_paddingRight="@dimen/activity_horizontal_margin"
android_paddingTop="@dimen/activity_vertical_margin"
tools_context=".MainActivity">
<EditText
android_id="@+id/cityEditText"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_hint="Enter city name"
android_imeOptions="actionSearch"
android_singleLine="true" />
<Button
android_id="@+id/fetchButton"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_below="@id/cityEditText"
android_layout_centerHorizontal="true"
android_text="Fetch Weather" />
<TextView
android_id="@+id/weatherTextView"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_below="@id/fetchButton"
android_gravity="center"
android_textSize="24sp" />
<ImageView
android_id="@+id/weatherIconImageView"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_below="@id/weatherTextView"
android_layout_centerHorizontal="true"
android_layout_marginTop="16dp"
android_contentDescription="Weather icon" />
</RelativeLayout>
We have added an EditText to enter the city name, a Button to fetch the weather, a TextView to display the weather information, and an ImageView to display the weather icon.
Implementing the MainActivity logic
Open the MainActivity.kt
file and replace the default code with the following:
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 androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
private lateinit var weatherService: WeatherService
private lateinit var cityEditText: EditText
private lateinit var fetchButton: Button
private lateinit var weatherTextView: TextView
private lateinit var weatherIconImageView: ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
weatherService = WeatherService("YOUR_API_KEY")
cityEditText = findViewById(R.id.cityEditText)
fetchButton = findViewById(R.id.fetchButton)
weatherTextView = findViewById(R.id.weatherTextView)
weatherIconImageView = findViewById(R.id.weatherIconImageView)
fetchButton.setOnClickListener {
val city = cityEditText.text.toString()
if (city.isNotEmpty()) {
fetchWeather(city)
}
}
}
private fun fetchWeather(city: String) {
launch {
try {
val weatherData = weatherService.getWeather(city)
val temperature = weatherData.main.temp.toString()
val humidity = weatherData.main.humidity.toString()
val weatherDescription = weatherData.weather.first().description
val weatherIconUrl = "https://openweathermap.org/img/w/${weatherData.weather.first().icon}.png"
weatherTextView.text = "Temperature: $temperature ยฐCnHumidity: $humidity%n$weatherDescription"
Glide.with(this@MainActivity)
.load(weatherIconUrl)
.into(weatherIconImageView)
} catch (e: Exception) {
weatherTextView.text = "Error fetching weather data"
weatherIconImageView.setImageDrawable(null)
}
}
}
}
Replace 'YOUR_API_KEY'
with your actual OpenWeatherMap API key.
In the fetchWeather
function, we make use of the weatherService
to fetch weather data for the specified city. We then update the UI with the temperature, humidity, weather description, and weather icon using the Glide library.
Testing the App
Connect your Android device or start an emulator, and click on the “Run” button in Android Studio to install and run the app. Enter a city name in the EditText and click the “Fetch Weather” button to see the weather data for that city.
Conclusion
In this tutorial, we learned how to create a weather app using Kotlin and Android. We made use of the OpenWeatherMap API to fetch weather data and displayed it in a user-friendly format. You can further enhance this app by adding more features like a forecast for multiple days or a search history. Feel free to explore and experiment with different features to make the app more useful and interactive.