Wstęp:
Tutaj podobnie jak w przypadku programu aplikacji pogodowej dla C# będę wykorzystywał serwis appweather.org. Dane będą pobierane na podstawie podanej nazwy miasta (Warszawa) bądź połączenia nazwy miasta ze skrótem danego kraju (Warszawa,pl).
Aplikacja w emulatorze prezentuje się następująco:
Teraz przejdę przez plik .xaml zawierający szablon projektu:
Deklaracja nagłówka z nazwą aplikacji:
Deklaracja nagłówka z nazwą aplikacji:
- <Label
- FontSize="20"
- FontAttributes="Bold"
- TextColor="Black"
- XAlign="Center"
- Text="Weather App"/>
Najpierw ustalana jest wielkość czcionki, pogrubienie, pozycjonowanie a na końcu sam tekst aplikacji.
Nazwa miasta wpisywana jest do kontrolki Entry.
- <Entry
- Text="{Binding City, Mode=Default}"
- HorizontalTextAlignment="Center"
- FontSize="20"
- TextColor="Black"
- FontAttributes="Bold"
- Placeholder="Write search city"/>
- <ActivityIndicator
- IsRunning="{Binding CheckWhenTaskInitializing,Mode=TwoWay}"/>
Poniżej definicji pola tekstowego znajduje się ActivityIndicator, odpowiada on za uruchamianie pobierania informacji o pogodzie.
Pod kontrolką będzie znajdowała się ikona z aktualną pogodą. Jej załadowanie wygląda następująco:
- <Image Source="{Binding WeatherIcon}"
- Aspect="AspectFit"
- WidthRequest="50"
- HeightRequest="50"/>
Do tej kontrolki wprowadzane są dane do wyświetlenie, sposób dopasowania obrazka oraz jego rozmiar.
Teraz część zawierająca kontrolki do wyświetlania danych dla miasta, temperatury, wilgotności itp:
- <StackLayout Spacing="10" x:Name="Country" Orientation="Horizontal" BackgroundColor="Aqua">
- <StackLayout HorizontalOptions="StartAndExpand">
- <Label
- FontSize="16"
- TextColor="Black"
- FontAttributes="Bold"
- Text="Country:"/>
- </StackLayout>
- <StackLayout HorizontalOptions="EndAndExpand">
- <Label
- FontSize="16"
- TextColor="Black"
- FontAttributes="Bold"
- Text="{Binding JsonWeatherReport.Sys.Country}"/>
- </StackLayout>
- </StackLayout>
- <StackLayout Spacing="10" x:Name="Position" Orientation="Horizontal" BackgroundColor="Aqua">
- <StackLayout HorizontalOptions="StartAndExpand">
- <Label
- FontSize="16"
- TextColor="Black"
- FontAttributes="Bold"
- Text="Position:"/>
- </StackLayout>
- <StackLayout HorizontalOptions="EndAndExpand">
- <Label
- FontSize="16"
- TextColor="Black"
- FontAttributes="Bold"
- Text="{Binding PositionString}"/>
- </StackLayout>
- </StackLayout>
Całość została przygotowana w oparciu o StackLayout. Każda linia zawiera po lewej stronie opis, po prawie znajduje się odczytany parametr. Dane do kontrolek przypisywane są ze zmiennej sformatowanej z dodatkowymi znakami, bądź bezpośrednio z odebranego JSON'a.
Kod Programu:
Na początku funkcja dekodująca dane JSON otrzymane z strony z aplikacją pogodową:
- public class JsonWeatherReport
- {
- [JsonProperty("name")]
- public string Name { get; set; }
- [JsonProperty("coord")]
- public Coord Coord { get; set; }
- [JsonProperty("weather")]
- public List<Weather> Weather { get; set; }
- [JsonProperty("base")]
- public string Base { get; set; }
- [JsonProperty("main")]
- public Main Main { get; set; }
- [JsonProperty("visibility")]
- public int Visibility { get; set; }
- [JsonProperty("wind")]
- public Wind Wind { get; set; }
- [JsonProperty("clouds")]
- public Clouds Clouds { get; set; }
- [JsonProperty("dt")]
- public int Dt { get; set; }
- [JsonProperty("sys")]
- public Sys Sys { get; set; }
- [JsonProperty("id")]
- public int Id { get; set; }
- [JsonProperty("cod")]
- public int Cod { get; set; }
- }
Powyżej znajduje się główna klasa zawierająca dane do wpisywania do klas pomocniczych przechowujących pogrupowane wartości zgodne z formatem JSON zwracanym przez stronę.
Za przesłanie zapytania odpowiada następująca funkcja:
Za przesłanie zapytania odpowiada następująca funkcja:
- public class GetWeatherApp<T>
- {
- private const string OPENWEATHERAPI = "http://api.openweathermap.org/data/2.5/weather?q=";
- private const string KEY = "f0f932e4dca4cb03bb603c7ce35e5f4a";
- private const string APPIDStart = "&APPID=";
- HttpClient httpClient = new HttpClient();
- public async Task<T> getWeatherJson(string city)
- {
- string url = OPENWEATHERAPI + city + APPIDStart + KEY;
- try
- {
- var jsonData = await httpClient.GetStringAsync(url);
- var weatherData = JsonConvert.DeserializeObject<T>(jsonData);
- return weatherData;
- }
catch(ArgumentNullException e) { }
- catch(HttpRequestException e)
- {
- //ex: no internet connection, DNS error
- }
- return (T)Convert.ChangeType("", typeof(T)) ;
- }
- }
Na samym początku deklarowane są stałe z adresem strony oraz kluczem. Po nich tworzony jest obiekt klasy HttpClient. W deklaracji zadania asynchronicznego tworzony jest adres url do przesłania. Następnie w bloku try, wysyłany jest adres ip, po czym następuje przetworzenie obiektu oraz jego zwrócenie. Gdy nastąpi błąd zwracany jest pusty element.
Ustawienie danych z informacjami które potrzebują edycji aby je przedstawić użytkownikowi wygląda następująco:
- public JsonWeatherReport JsonWeatherReport
- {
- get { return jsonWeatherReport; }
- set
- {
- jsonWeatherReport = value;
- WeatherIcon = "http://openweathermap.org/img/w/" + jsonWeatherReport.Weather[0].Icon + ".png";
- OnPropertyChanged();
- TemperatureString = string.Format("{0}°K / {1}°C", jsonWeatherReport.Main.Temp, (Math.Truncate((jsonWeatherReport.Main.Temp - 273) *100) / 100));
- HumidityString = string.Format("{0}%", jsonWeatherReport.Main.Humidity);
- PressureString = string.Format("{0}hPa", jsonWeatherReport.Main.Pressure);
- PositionString = string.Format("Long: {0} - Lon: {1}", jsonWeatherReport.Coord.Lon, jsonWeatherReport.Coord.Lat);
- SunriseString = string.Format("{0}", UnixTimeStampToDateTime(jsonWeatherReport.Sys.Sunrise));
- SunsetString = string.Format("{0}", UnixTimeStampToDateTime(jsonWeatherReport.Sys.Sunset));
- }
- }
Pozostałe informacje są pobierane bezpośrednio z JSON'a.
W celu weryfikacji czy dane miasto zostało już wprowadzone ustawiana jest flaga. Gdy jest ona ustawiana wywoływane jest przesłanie zapytania do serwisu.
- public class WeatherGetData
- {
- GetWeatherApp<JsonWeatherReport> getWeatherApp = new GetWeatherApp<JsonWeatherReport>();
- public async Task<JsonWeatherReport> GetWeatherDetails(string cityName)
- {
- var getWeatherDetails = await getWeatherApp.getWeatherJson(cityName);
- return getWeatherDetails;
- }
- }
- private async Task getWeatherAsyn()
- {
- try
- {
- CheckIfTaskInitializing = true;
- JsonWeatherReport = await weatherGetCityData.GetWeatherDetails(cityName);
- }
- finally
- {
- CheckIfTaskInitializing = false;
- }
- }
Cały projekt można pobrać pod tym linkiem.