Tutorial 2
Tutorial 2
Contents
1 Introduction 1
3 Optional Work 8
3.1 Adding Functionality and Modifying Code in the App . . . . . . . . . . . . 8
3.2 Implementing the Model-View-ViewModel design pattern . . . . . . . . . . 8
Tutorial 2 - Cool Weather Application
List of Figures
1 Portrait Layout for the Application . . . . . . . . . . . . . . . . . . . . . . 3
2 Landscape Layout for the Application . . . . . . . . . . . . . . . . . . . . . 3
3 Latitude Coordinates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4 Longitude Coordinates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Tutorial 2 - Cool Weather Application
1 Introduction
This work aims to introduce the application development environment for Android de-
vices. The tutorial introduces the anatomy of an Android program. From the application
“Hello World” a new application with a more elaborate user interface is built. The
CoolWeatherApp aims to create a user-friendly weather application with a customizable
interface suitable for any screen size and themed content. It displays a range of mete-
orological data for a specific location defined by its latitude and longitude coordinates,
including Sea Level Pressure, Wind Direction,Wind Speed, and Temperature.
The application also presents the date and time the data was obtained, along with an
image representing the current weather conditions at the location. For instance, a sun
icon symbolizes clear skies during the daytime. By default, the app displays weather
information for Lisbon (latitude: 38.076, longitude: -9.12). Users can update the location
by entering new coordinates and pressing the “update” button to view the corresponding
weather information.
This tutorial is designed to walk you through the development of the application,
providing useful guidance on how to proceed. Along with a few code snippets, it aims to
equip students with the necessary knowledge and resources to actively fill in any missing
pieces of the puzzle. As such, it is highly recommended that learners take advantage
of the provided hints and proactively read the relevant documentation to implement the
missing code effectively. You can find all the required documentation at the following
location:
https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t
weather=true&hourly=temperature 2m
Play with the different variables, read the documentation, and see how the API URL
changes. Pay special attention to the information regarding WMO Weather interpretation
codes (bottom of the page). We will be using these codes in our application to describe
the current weather in our location (clear sky, Fog, etc.).
2. Obtain Weather Information Copy and Paste the API URL on youre browser’s ad-
dress bar, execute the request and you should receive a JOSN response with the weather
1
Tutorial 2 - Cool Weather Application
information you requested in the URL string. To have a prettier view of this infor-
mation, copy the JSON string and use the following JSON Pretty Print Online tool:
https://jsonformatter.org/json-pretty-print.
2. Lets use as a starting reference the Google Pixel 3 AVD. The Google Pixel 3 has a
5.5-inch OLED display with a resolution of 1080 x 2160 pixels and a pixel density
of 443 pixels per inch (ppi). It has a viewport size is 393 x 786 PX with 161 actual
pixel density, which means it have 2.75 xxhdpi display pixel density. Search the
Web for a suitable background image with at least 393 x 786 PX. If you have to edit
your images, you can use, for example, Gimp (https://www.gimp.org/). Resize
and crop the image if the original size is larger than 393 x 786 and convert the
image to png format. Copy the image to the drawable folder of the project. Image
names should only contain lower case a-z, 0-9, or underscore or else they will not
appear in the Pick a Resource window. Images should be placed in the drawables
directory (not any other like drawable-v24).
3. Set the image as the background of your main activity. Open the “activity main.xml”
in the res/layout folder. Open the “Split” tab in the lower left corner of the editor
to switch to the Layout Editor. Select the <constraintLayout> element and in the
properties panel (lower right corner) put the name of “container” in the attribute
id of the element. In the “background” attribute, place the image you copied in the
previous point, by pressing the right most vertical rectangular/rounded shape to
open the Pick a Resource window and select the previous image. Run the program
on the Pixel 3 AVD created in the previous tutorial.
4. Create a landscape layout and adapt the background image so that if fits perfectly
to this layout. To accomplish this, crop the higher resolution image that was used
in the previous section in a way that is looks good with a size of 786 x 393.
5. Create and add a new portrait and landscape layout for different screen size and
resolution (select, for example, a tablet). Create a new AVD and test how this
layout look in this new device. Adjust the background images appropriately.
1. To represent the current weather, import the color or black Vector Assets provided in
the “Drawables.zip” file accompanying this tutorial. The icons in this file illustrate
2
Tutorial 2 - Cool Weather Application
different weather conditions. For instance, in our layout, the sun was representing
a “clear day” in Lisbon on the following date: “2023-03-10T12h00”. 1 . To add
the entire directory, go to “Tools/Resource Manager”, press “+”(Add resources to
module) and select “Import Drawables”.
< resources xmlns : tools =" http :// schemas . android . com / tools " >
<! -- Base application theme . -- >
< style name =" Theme . CoolWeatherApp "
parent =" Theme . MaterialComponents . DayNight . NoActionBar " >
<!-- Primary brand color . -- >
< item name =" colorPrimary " > @color / purple_500 </ item >
< item name =" colorPrimaryVariant " > @color / purple_700 </ item >
< item name =" colorOnPrimary " > @color / white </ item >
1
Obtained from: https://github.com/Tomorrow-IO-API/tomorrow-weather-codes
3
Tutorial 2 - Cool Weather Application
< item name =" background " > @color / viewBG </ item >
< item name =" android : textColor " > @color / WeatherLabel </ item >
< item name =" android : textSize " >18 sp </ item >
< item name =" android : textStyle " > bold </ item >
< style name =" Theme . Day " parent =" Theme . CoolWeatherApp " >
< item name =" android : windowBackground " > @drawable / sunny_bg </ item >
</ style >
< style name =" Theme . Day . Land " parent =" Theme . CoolWeatherApp " >
< item name =" android : windowBackground " > @drawable / sunny_bg_land </ item >
</ style >
< style name =" Theme . Night " parent =" Theme . CoolWeatherApp " >
< item name =" android : windowBackground " > @drawable / night_bg </ item >
</ style >
< style name =" Theme . Night . Land " parent =" Theme . CoolWeatherApp " >
< item name =" android : windowBackground " > @drawable / night_bg_land </ item >
</ style >
</ resources >
Listing 2: onCreate
4. Execute the program and check if the UI is close to what you expect. Small changes
in the layout of the elements are expected.
4
Tutorial 2 - Cool Weather Application
5. Navigate to your “strings.xml” file and access the Strings Editor located in the
top right corner. Add two languages (Portuguese and English), and assign the
appropriate text for each string and language. Once this is complete, modify the
language settings on your device and run the application. Verify that all strings
change correctly according to the selected language.
6. Modify the boolean variable “day” and ensure that the Theme changes correctly in
response.
7. Find out how to change the application launcher icon and change it.
1. To get started, create a new Kotlin class file named ’WeatherData.kt’ and add
the code shown in listings 3. Please note that the class arrangement provided is
for demonstration purposes only and should be customized to match the data re-
trieved from the Weather API. The classes WeatherData, CurrentWeather, and
Hourly will store the information obtained from the Weather API. The enumera-
tion WMO weatherCode contains integer codes and drawable icons representing
various weather conditions. You can utilize a MAP to retrieve the name of the
drawable associated with the weather code obtained from the API and use it to
depict the weather in the layout of the Cool Weather Application.
)
data class CurrentWeather (
var temperature : Float ,
var windspeed : Float ,
var winddirection : Int ,
var weathercode : Int ,
var time : String
)
data class Hourly (
var time : ArrayList < String >,
var temperature_2m : ArrayList < Float >,
var weathercode : ArrayList < Int >,
var pressure_msl : ArrayList < Double >
)
5
Tutorial 2 - Cool Weather Application
Listing 3: WeatherData.kt
6
Tutorial 2 - Cool Weather Application
3. In Android, the UI thread is responsible for drawing and updating the user interface.
If any long-running task is performed on this thread, it can cause the UI to freeze,
leading to an unresponsive and poor user experience. Therefore, it is recommended
to run any time-consuming or blocking operations on a separate thread, usually
through the use of AsyncTask or Thread. However, when it is necessary to update
the UI from a background thread, runOnUiThread can be used to execute code
on the UI thread from the background thread. By using this method, we ensure
that any UI updates happen on the UI thread and not on the background thread,
thus avoiding any potential UI freezing issues. Listings 5 shows how you can call
the weather API and update the UI.
At the start of the application and whenever the user presses the update button, you
must invoke the fetchWeatherData method. Updating the UI involves utilizing
the latitude and longitude coordinates to retrieve weather data and using that data
to modify the weather variables, weather image, and background based on the local
hour and sunrise/sunset information for that location.
// TODO ...
pressure . text = request . hourly . pressure_msl . get (12). toString () + " hPa "
// TODO ...
// TODO ...
}
}
7
Tutorial 2 - Cool Weather Application
4. To test your application, modify the latitude and longitude coordinates and observe
how the weather image, background, and weather parameters update accordingly.
To choose suitable latitude and longitude coordinates, refer to Figures 3 and 4,
which demonstrates how the altitude and longitude coordinate system operates.
3 Optional Work
In this section, you will find optional tasks that you can complete to earn up to 30% of
the grade assigned to this tutorial.
• Rather than using a hardcoded enumeration for WeatherCodes, modify the code to
retrieve the relevant information (Weather Code, Description, and Image) from a
resource XML file. Refer to the slides in “DAM 02 Android - Anatomy of Android
Apps.pptx” for more information on using array resources.
8
Tutorial 2 - Cool Weather Application
incorporating the MVVM design pattern into it. Specifically, you will need to refactor
the code in the MainActivity to comply with the MVVM pattern. Here are the steps
you need to follow:
• Extract the business logic from the MainActivity and place it into a ViewModel
class.
• Use the Observer pattern to observe changes in the ViewModel and update the View
accordingly.
• Test your application to ensure that it works as expected and that the code is clean,
efficient, and organized.
By completing this task, you will gain hands-on experience in implementing the
MVVM design pattern in an Android application, which will help you to write better
code and build more sophisticated applications in the future. Below are several helpful
links that can aid you in completing this task:
• https://medium.com/swlh/understanding-mvvm-architecture-in-android-aa66f7e1a70b
• https://www.youtube.com/watch?v=eUQebUJLnXI
• https://www.toptal.com/android/android-apps-mvvm-with-clean-architecture
• https://developer.android.com/codelabs/basic-android-kotlin-training-repository-pattern#0
• https://www.section.io/engineering-education/implementing-a-repository-kotlin/
• https://developer.android.com/topic/libraries/view-binding
• https://developer.android.com/topic/libraries/data-binding
• https://developer.android.com/topic/libraries/architecture/lifecycle