{"id":19388621,"url":"https://github.com/prashantvc/hol-weatherapp","last_synced_at":"2026-06-11T22:31:07.299Z","repository":{"id":144891329,"uuid":"70260567","full_name":"prashantvc/HOL-WeatherApp","owner":"prashantvc","description":null,"archived":false,"fork":false,"pushed_at":"2016-10-23T15:41:04.000Z","size":351,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-24T19:59:15.551Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/prashantvc.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-10-07T15:45:29.000Z","updated_at":"2016-10-07T15:47:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"8c4a68dc-ee49-4958-b37c-6a963145af2d","html_url":"https://github.com/prashantvc/HOL-WeatherApp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/prashantvc/HOL-WeatherApp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashantvc%2FHOL-WeatherApp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashantvc%2FHOL-WeatherApp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashantvc%2FHOL-WeatherApp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashantvc%2FHOL-WeatherApp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/prashantvc","download_url":"https://codeload.github.com/prashantvc/HOL-WeatherApp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashantvc%2FHOL-WeatherApp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34221150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-10T10:13:20.027Z","updated_at":"2026-06-11T22:31:07.279Z","avatar_url":"https://github.com/prashantvc.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Weather App Xamarin.iOS\n\nIn this module we will build a native iOS and Android app using Visual Studio, Xamarin.iOS and Xamarin.Android\nThe app we are building is called Weather App that gets the weather information from a web services\nwhen you tap a location on the Maps.\n\n## Overview\n\nWhat we will learn in this lab?\n\n- Calling web method to get weather data\n- Code sharing between iOS and Android app\n\n### iOS\n- Creating a user interface using iOS Designer\n- Using Maps control in an app \n\n### Android\n- Adding Android permission\n- Accessing device location\n\nIn the _Start_ folder you will find the partially completed Weather App solution.\nThat we will use to complete this exercise\n\n## Pre-requisites \nBefore executing the labs be sure to setup your macOS or Windows machines as mentioned in the Lab Setup guidelines. \nThe steps \u0026 screenshots in this guide focuses on Visual Studio development in Windows. \nHowever, the same labs can be executed in Xamarin Studio on a macOS too. \n\nWhen you rung the app, the iOS simulator should start and load the app with blank screen. Now you are all set up to write some code!\n\n\n### Android \n\nThe project contains layout files for designing UI. Open `Resources\\layout\\Main.axml`, it should open in the Android designer.\nSelect the button, in the property panel change the text to _Get Weather_ and Save.\n\nYou need add locate [permissions](https://developer.android.com/guide/topics/security/permissions.html), before we access the device location.\n\n1. Create a new Xamarin.Android application named GetLocation.\n2. Edit **AssemblyInfo.cs**, and declare the permissions necessary to use the LocationServices:\n\n```    \n[assembly: UsesPermission(Manifest.Permission.AccessFineLocation)]\n[assembly: UsesPermission(Manifest.Permission.AccessCoarseLocation)]\n```\n\n3. Declare the permissions necessary to use the Geocoder class. This is not strictly necessary for obtaining the GPS coordinates of the device, but this example will attempt to provide a street address for the current location:\n```\n[assembly: UsesPermission(Manifest.Permission.Internet)]\n```\n\n4. Edit **Main.axml** so that it contains two TextViews and a Button:\n\n```\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cLinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:paddingTop=\"20dp\"\n    android:paddingLeft=\"8dp\"\n    android:paddingRight=\"8dp\"\u003e\n    \u003cTextView\n        android:layout_width=\"fill_parent\"\n        android:textAppearance=\"?android:attr/textAppearanceMedium\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Location (when available)\"\n        android:id=\"@+id/location_text\"\n        android:layout_marginBottom=\"15dp\" /\u003e\n    \u003cButton\n        android:layout_width=\"fill_parent\"\n        android:textAppearance=\"?android:attr/textAppearanceMedium\"\n        android:layout_height=\"wrap_content\"\n        android:id=\"@+id/get_weather\"\n        android:text=\"Get Weather\" /\u003e\n    \u003cTextView\n        android:layout_width=\"fill_parent\"\n        android:textAppearance=\"?android:attr/textAppearanceMedium\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Address (when available)\"\n        android:id=\"@+id/address_text\"\n        android:layout_marginTop=\"10dp\" /\u003e\n\u003c/LinearLayout\u003e\n```\n\n5. Add some instance variables to **MainActivity.cs**:\n```\nstatic readonly string TAG = \"X:\" + typeof (Activity1).Name;\nTextView _addressText;\nLocation _currentLocation;\nLocationManager _locationManager;\n\nstring _locationProvider;\nTextView _locationText;\n```\n6. Change `OnCreate` method: \n\n```\nprotected override void OnCreate(Bundle bundle)\n{\n    base.OnCreate(bundle);\n    SetContentView(Resource.Layout.Main);\n\n    _addressText = FindViewById\u003cTextView\u003e(Resource.Id.address_text);\n    _locationText = FindViewById\u003cTextView\u003e(Resource.Id.location_text);\n    FindViewById\u003cTextView\u003e(Resource.Id.get_address_button).Click += WeatherButton_OnClick;\n\n    InitializeLocationManager();\n}\n```\nThe handler for button click will be covered below. The logic for initializing the LocationManager is placed in its own method for clarity.\n\n7. Add a method called InitializeLocationManager to **MainActivity.cs**:\n```\nvoid InitializeLocationManager()\n{\n    _locationManager = (LocationManager) GetSystemService(LocationService);\n    Criteria criteriaForLocationService = new Criteria\n                                          {\n                                              Accuracy = Accuracy.Fine\n                                          };\n    IList\u003cstring\u003e acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);\n\n    if (acceptableLocationProviders.Any())\n    {\n        _locationProvider = acceptableLocationProviders.First();\n    }\n    else\n    {\n        _locationProvider = string.Empty;\n    }\n    Log.Debug(TAG, \"Using \" + _locationProvider + \".\");\n}\n```\n\nThe `LocationManager` class will listen for GPS updates from the device and notify the application by way of events. In this example we ask Android for the best location provider that matches a given set of `Criteria` and provide that provider to `LocationManager`.\n\n8. Edit **MyActivity.cs** and have it implement the interface `ILocationListener` and add in the methods required by that interface:\n```\n[Activity(Label = \"Get Location\", MainLauncher = true, Icon = \"@drawable/icon\")]\npublic class Activity1 : Activity, ILocationListener\n{\n    // removed code for clarity\n\n    public void OnLocationChanged(Location location) {}\n\n    public void OnProviderDisabled(string provider) {}\n\n    public void OnProviderEnabled(string provider) {}\n\n    public void OnStatusChanged(string provider, Availability status, Bundle extras) {}\n}\n```\n\n9. Override `OnResume` so that `MyActivity` will begin listening to the `LocationManager` when the activity comes into the foreground:\n```\nprotected override void OnResume()\n{\n    base.OnResume();\n    _locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);\n}\n```\n\n10. Override `OnPause` and unsubscribe `MainActivity` from the `LocationManager` when the activity goes into the background:\n```\nprotected override void OnPause()\n{\n    base.OnPause();\n    _locationManager.RemoveUpdates(this);\n}\n```\nWe reduce the demands on the battery by unsubscribing from the LocationManager when the activity goes into the background.\n\n11. Add an event handler called `WeatherButton_OnClick` to MainActivity. This button allows the user to try and get the address from the latitude and longitude. \nThe snippet below contains the code for `WeatherButton_OnClick`:\n```\nasync void WeatherButton_OnClick(object sender, EventArgs eventArgs)\n{\n    if (_currentLocation == null)\n    {\n        _addressText.Text = \"Can't determine the current address. Try again in a few minutes.\";\n        return;\n    }\n\n    Address address = await ReverseGeocodeCurrentLocation();\n    DisplayAddress(address);\n}\n\nasync Task\u003cAddress\u003e ReverseGeocodeCurrentLocation()\n{\n    Geocoder geocoder = new Geocoder(this);\n    IList\u003cAddress\u003e addressList =\n        await geocoder.GetFromLocationAsync(_currentLocation.Latitude, _currentLocation.Longitude, 10);\n\n    Address address = addressList.FirstOrDefault();\n    return address;\n}\n\nvoid DisplayAddress(Address address)\n{\n    if (address != null)\n    {\n        StringBuilder deviceAddress = new StringBuilder();\n        for (int i = 0; i \u003c address.MaxAddressLineIndex; i++)\n        {\n            deviceAddress.AppendLine(address.GetAddressLine(i));\n        }\n        // Remove the last comma from the end of the address.\n        _addressText.Text = deviceAddress.ToString();\n    }\n    else\n    {\n        _addressText.Text = \"Unable to determine the address. Try again in a few minutes.\";\n    }\n}\n```\n\nThe `ReverseGeocodeCurrentLocation` method will asynchronously lookup a collection of `Address` objects for the currrent location. Depending on factors such as the location and network availability, none, one, or multiple addresses will be returned. The first address (if possible) will be passed to the method `DisplayAddress` which will display the address in the Activity. \n\n12. Update the method `OnLocationChanged` to display the latitude and longitude when GPS updates are received and update the address:\n```\npublic async void OnLocationChanged(Location location)\n{\n    _currentLocation = location;\n    if (_currentLocation == null)\n    {\n        _locationText.Text = \"Unable to determine your location. Try again in a short while.\";\n    }\n    else\n    {\n        _locationText.Text = string.Format(\"{0:f6},{1:f6}\", _currentLocation.Latitude, _currentLocation.Longitude);\n        Address address = await ReverseGeocodeCurrentLocation();\n        DisplayAddress(address);\n    }\n}\n```\nYou will need to add the `System.Xml.Linq` assembly.\n\n13. Add the **WeatherPCL** reference to the project\n\n14. Call `GetWeather` method in `WeatherButton_OnClick`, add the below code after `DisplayAddress` method\n\n```           \nstring tempdata = await _weatherApi.GetWeather(_currentLocation.Longitude, _currentLocation.Latitude);\nvar alert = new AlertDialog.Builder(this);\nalert.SetTitle(\"Weather\").SetMessage(tempdata).Show();\n```            \n\n13. Run the application. After a short while, the location of the GPS should be displayed. Be patient it can take a little while to display the co-ordinates\n\n14. Click the button Get Weather to show the current tempreture for the address\n\n### iOS\n\nThe projects contains a `Main.storyboard` file a interface designer surface where we will \nadd UI controls for Maps, labels and button. A `ViewController.cs` a controller file where\nwe will write the business logic, in this exercise this will be touch handler for `Map` controls\nand code to get the weather data.\n\nAnd finally `AppDelegate.cs` this where the bootstrapping code for app\n\nYou can take a look at completed project in Finish folder, if you get stuck any where during this exercise\n\n## Let's design the interface\n\nPlease follow the instructions to add a controls to the design surface\n\n1. Double click on the `Main.storyboard` file, once designer is loaded you should some iOS `View` rendered on the device\n2. Drag and drop a `Label` control from the Toolbox to the designer surface\n3. Let's give it a meaningful name that we can identify in the `ViewController` code\n4. Now repeat the steps 2 and 3, but add the `Map View` instead\n5. When you're done the Designer should looks something like this: ![Designer](https://github.com/prashantvc/HOL-WeatherApp/blob/master/Screenshots/Designer.PNG)\n6. Finally, lets run it in the simulator to verify that map loads\n\n## Get location co-ordinates from the Map\n\n1. Open the `ViewController.cs`, and locate the `ViewDidLoad` method. \u003cbr/\u003e `ViewDidLoad` method is called when the screen loads on the screen\n2. Create an event handler for `RegionChanged` event for the Map, lets call it `MyMap_RegionChanged`\n3. We want to access the Geo coordinates for center of the displayed region, `MyMap.Region.Center` gives the value\n4. Add the **WeatherPCL** project reference to your project\n5. Pass the _longitude_ and _latitude_ values from `MyMap.Region.Center` value to the `GetWeather` method from `WeatherAPI` classs, where we get weather information from the web service\n6. Update the `MyMap_RegionChanged` code to:\n```\nasync void MyMap_RegionChanged(object sender, MKMapViewChangeEventArgs e)\n{\n    var weatherApi = new WeatherAPI();\n\n    string tempData = await _weatherApi.GetWeather(MyMap.CenterCoordinate.Latitude, MyMap.CenterCoordinate.Latitude);\n    Description.Text = tempData;\n}\n```\n\n\n## Parse the weather data\n\nWe are using the OpenWeatherMap service to get the weather data, please take a look at the `GetWeather` method in `ViewController.cs` file.\nOnce we parsed the data returned from the web service we assign it to the `Description` label\n\n`Description.Text = $\"City {city}, {temperature}°C\";`\n\n## What's next?\n\nOnce you competed this exercise, you can try extend the app with:\n\n- Display current weather icon\n- Add forecast details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprashantvc%2Fhol-weatherapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprashantvc%2Fhol-weatherapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprashantvc%2Fhol-weatherapp/lists"}