Android · Utility · 3 min read

Weather Checker

Forecasts for anywhere on the map, built to keep working when permission or signal doesn’t.

I built Weather Checker, an Android app that keeps forecasts, favourites, and alarms working even when location permission or network signal doesn’t cooperate.

My role
I built the Android application end to end during the ITI Android Mobile Development track.
Context
ITI Android Mobile Development track
Period
Mar – Jul 2023 (ITI cohort)
Status
ITI project · 2023
Platform
Android

ITI project · 2023

  • 9Unit-test filesCovering the ViewModels against fake data sources
  • Android (Kotlin)
  • MVVM
  • Coroutines
  • Retrofit
  • Room
  • Google Maps

Roles: Android Developer.

The problem

A weather app breaks in the moments it matters most: no location permission, no signal, or a forecast request that just times out. Treating those as crash conditions instead of normal product states means the app fails exactly when someone actually needs to check the forecast before heading out.

Most weather apps assume the happy path: permission granted, signal available, request succeeds. In practice, a phone in a basement, a user who declined location access, or a request that simply takes too long are all routine, not edge cases. An app built during a training track is still a real app someone will open on a real phone, so those states needed real screens rather than being left to whatever the underlying library happened to do.

Who it was for

Anyone checking the forecast for more than one place, who still needs the app to behave sensibly when permission or connectivity isn’t available. That covers a user who wants to compare a home location against a place they’re travelling to, and one who has simply declined location permission and still expects the app to be useful.

My role

I built the Android application end to end during the ITI Android Mobile Development track, from the forecast screens and map picking through the alarms and the offline and permission-denied handling.

What I built

  • Current, hourly, and daily forecasts

    Forecast charts cover the immediate hours and the days ahead, not just the current temperature.

  • Favourite places

    A user can save more than one location and switch between them instead of only ever checking one.

  • Map picking

    A place can be chosen directly from a map instead of typing a name and hoping it resolves correctly.

  • Weather alarms

    Alarms built on broadcast receivers can notify a user of conditions worth planning around.

  • Units and language settings

    Units and language are user preferences, not fixed at build time.

  • Connectivity and error handling

    Permission denial and no network are treated as normal states with their own screens, not as crashes.

Favourite places and map picking both feed the same forecast pipeline, so switching locations never means a different code path for a saved place versus a newly picked one. Weather alarms sit on top of that same forecast data rather than a separate polling system. The parts that mattered most in practice were the states that show up when something isn’t available: no permission, no network, or a forecast that failed to load, each with its own screen instead of a silent failure.

Units and language are stored as preferences rather than fixed at build time, so switching from metric to imperial, or between languages, doesn’t require reinstalling or resetting anything else the user has already set up, including their favourite places and alarms.

How it works

A ViewModel sits between the screens and a repository that separates forecast networking from cached and preferred state, with alarms and map picking alongside it.

A ViewModel and repository separate forecast networking from cached and preferred state, with alarms and map picking alongside. Relationships: Views to ViewModel; ViewModel to Repository; Repository to Forecast API; Repository to Room; Repository to Preferences; Alarms to Notifications; ViewModel to Maps.

Keeping the repository as the single boundary between the ViewModel and the outside world means the ViewModel never has to know whether a forecast came from the network or from the Room cache. That boundary is also what made it possible to substitute a fake data source in tests without touching the ViewModel code at all.

Decisions that mattered

  • I chose repository abstractions with fake data sources over ViewModels that call the network layer directly because it let the ViewModels be unit-tested against predictable fake data instead of a real network call every time a test ran.

Tech stack

Location
  • Google Maps: Map-based place picking

Outcome

Weather Checker was built during the ITI Android Mobile Development track. The ViewModels are covered by nine unit-test files, made possible by testing against fake data sources instead of live network calls.

What I learned

Permission denial and no network are normal product states, not error screens.

Building the repository abstraction first, before wiring it to a real network call, forced every failure mode to have a deliberate answer instead of an afterthought. That discipline is also what made the ViewModels straightforward to unit-test.