U ovom ću blog postu pokazati kako unutar Ionic aplikacije postaviti API za prikaz vremenske prognoze koristeći OpenWeatherMap.
Iako svaki Android mobilni uređaj sam po sebi već ima prikaz vremenske prognoze, koji je moguće dodatno prilagoditi, na početnom zaslonu ipak može biti korisno ubaciti i ovakav način prikaza takvih informacija.
Npr. ako je u pitanju nekakva turistička aplikacije dobro je prikazati trenutnu vremensku prognozu mjesta u koje smo stigli ili gdje planiramo putovati.
Uvod
Prije svega potrebno je kreirati korisnički račun na https://home.openweathermap.org/users/sign_up
Postoji nekoliko različitih opcija od kojih je manji dio besplatan, ali u svakom slučaju i to je dovoljno za osnovni prikaz vremenske prognoze. U slučaju potrebe za dodatnim informacijama moguće je koristiti neki od oblika mjesečne pretplate.
Kreiranje aplikacije
Kreiram novi Ionic, u ovom slučaju Ionic 4, projekt i odmah dodajem podršku za Android platformu.
1 2 3 |
$ ionic start IonicWeather blank--type=angular $ cd IonicWeather $ ionic cordova platform add android |
OpenWeatherMap API
S obzirom da sam se registrirao za besplatnu verziju API-ja mogu, od onoga što je meni trenutno zanimljivo, koristiti samo “Current weather data” API i “5 day / 3 hour forecast” API.
Current weather data
Ovaj API prikazuje trenutnu vremensku prognozu za odabrani grad, a pozivam ga na adresi
1 |
http://api.openweathermap.org/data/2.5/weather?q= |
U sljedećem primjeru pozivam ovaj API s dva osnovna parametra, a to su: moj API ključ koji sam dobio nakon registracije te ime grada za koji želim dobiti vremensku prognozu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'], }) export class HomePage { vrijemeObjekt = { temperatura: 0, opis: '', slika: ''}; grad: string = "Vinkovci"; constructor( private _http: HttpClient) { } ionViewDidEnter(){ this.prikaziVrijeme(); } prikaziVrijeme(){ this._http.get("http://api.openweathermap.org/data/2.5/weather?q=" + this.grad + "&appid=********************************") .subscribe((data) => { console.log(data); this.vrijemeObjekt.temperatura = data['main']['temp']; this.vrijemeObjekt.opis = data['weather'][0]['description']; this.vrijemeObjekt.slika = 'http://openweathermap.org/img/w/' + data['weather'][0]['icon'] + ".png"; console.log(this.vrijemeObjekt); }); } } |
I odmah dobijem željene podatke na kojima se mogu primijetiti dva detalja. Prvi se tiče opisa vremenske prognoze koji je na engleskom jeziku, a drugi se tiče mjerne jedinice koja nije u °C.
Kako bi to promijenio dodat ću još dva parametra u API URL.
1 2 3 4 5 6 7 8 9 10 |
prikaziVrijeme(){ this._http.get("http://api.openweathermap.org/data/2.5/weather?q=" + this.grad + "&appid=********************************" + "&units=metric" + "&lang=hr") .subscribe((data) => { console.log(data); this.vrijemeObjekt.temperatura = data['main']['temp']; this.vrijemeObjekt.opis = data['weather'][0]['description']; this.vrijemeObjekt.slika = 'http://openweathermap.org/img/w/' + data['weather'][0]['icon'] + ".png"; console.log(this.vrijemeObjekt); }); } |
Nakon toga mogu vidjeti da je sada opis vremenske prognoze na hrvatskom jeziku i da je mjerna jedinica °C.
Ikona se prikazuje na način da se na URL 'http://openweathermap.org/img/w/' doda naziv slike data['weather'][0]['icon'] + ".png" koji se dobije kao odgovor na API zahtjev. Više o tome na poveznici https://openweathermap.org/weather-conditions
Na ekranu to može izgledati ovako, ali je i dalje malo čudno zbog decimalnog prikaza.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<ion-header> <ion-toolbar> <ion-title> Ionic Weather App </ion-title> </ion-toolbar> </ion-header> <ion-content padding> <ion-card> <ion-row> <ion-col> <img src="{{vrijemeObjekt.slika}}"> </ion-col> <ion-col> <h1>{{vrijemeObjekt.temperatura}}°C</h1> {{vrijemeObjekt.opis}} </ion-col> </ion-row> </ion-card> </ion-content> |
To se vrlo lako riješi pomoću Math.round().
1 |
this.vrijemeObjekt.temperatura = Math.round(data['main']['temp']); |
Što daje sljedeći rezultat
5 day / 3 hour forecast
Ovaj API prikazuje vremensku prognozu za pet dana unaprijed u razmacima od po tri sata, a pozivam ga na adresi
1 |
http://api.openweathermap.org/data/2.5/forecast?q= |
Nakon svega navedenog u primjeru iznad u ovom se primjeru neće puno toga promijeniti. Rezultat će ostati na hrvatskom jeziku te u obliku °C.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
prikaziVrijeme(){ this._http.get("http://api.openweathermap.org/data/2.5/forecast?q=" + this.grad + "&appid=********************************" + "&units=metric" + "&lang=hr") .subscribe((data) => { console.log(data); // Sada this.vrijemeObjekt.slikaDanas = 'http://openweathermap.org/img/w/' + data['list'][0]['weather'][0]['icon'] + ".png"; this.vrijemeObjekt.temperaturaDanas = Math.round(data['list'][0]['main']['temp']); this.vrijemeObjekt.opisDanas = data['list'][0]['weather'][0]['description']; // Za 3 sata this.vrijemeObjekt.slikaDanas3 = 'http://openweathermap.org/img/w/' + data['list'][1]['weather'][0]['icon'] + ".png"; this.vrijemeObjekt.temperaturaDanas3 = Math.round(data['list'][1]['main']['temp']); // Za 6 sati this.vrijemeObjekt.slikaDanas6 = 'http://openweathermap.org/img/w/' + data['list'][2]['weather'][0]['icon'] + ".png"; this.vrijemeObjekt.temperaturaDanas6 = Math.round(data['list'][2]['main']['temp']); // Za 9 sati this.vrijemeObjekt.slikaDanas9 = 'http://openweathermap.org/img/w/' + data['list'][3]['weather'][0]['icon'] + ".png"; this.vrijemeObjekt.temperaturaDanas9 = Math.round(data['list'][3]['main']['temp']); // Za 12 sati this.vrijemeObjekt.slikaDanas12 = 'http://openweathermap.org/img/w/' + data['list'][4]['weather'][0]['icon'] + ".png"; this.vrijemeObjekt.temperaturaDanas12 = Math.round(data['list'][4]['main']['temp']); console.log(this.vrijemeObjekt); }); } |
Na ekranu to može izgledati ovako
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<ion-content padding> <ion-card> <ion-row> <ion-col> <img src='{{vrijemeObjekt.slikaDanas}}'> </ion-col> <ion-col> <h6>{{vrijemeObjekt.temperaturaDanas}}°C<br> {{vrijemeObjekt.opisDanas}}</h6> </ion-col> <ion-col text-center> <img src='{{vrijemeObjekt.slikaDanas3}}'> {{vrijemeObjekt.temperaturaDanas3}}°C </ion-col> <ion-col text-center> <img src='{{vrijemeObjekt.slikaDanas6}}'> {{vrijemeObjekt.temperaturaDanas6}}°C </ion-col> <ion-col text-center> <img src='{{vrijemeObjekt.slikaDanas9}}'> {{vrijemeObjekt.temperaturaDanas9}}°C </ion-col> <ion-col text-center> <img src='{{vrijemeObjekt.slikaDanas12}}'> {{vrijemeObjekt.temperaturaDanas12}}°C </ion-col> </ion-row> </ion-card> </ion-content> |
Zaključak
Struktura projekta prema package.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
{ "name": "IonicWeather", "version": "0.0.1", "author": "Tomislav Stanković", "homepage": "https://www.tomislavstankovic.com/", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/common": "~7.0.0", "@angular/core": "~7.0.0", "@angular/forms": "~7.0.0", "@angular/http": "~7.0.0", "@angular/platform-browser": "~7.0.0", "@angular/platform-browser-dynamic": "~7.0.0", "@angular/router": "~7.0.0", "@ionic-native/core": "5.0.0-beta.21", "@ionic-native/splash-screen": "5.0.0-beta.21", "@ionic-native/status-bar": "5.0.0-beta.21", "@ionic/angular": "4.0.0-beta.16", "cordova-android": "7.0.0", "cordova-plugin-device": "^2.0.2", "cordova-plugin-ionic-keyboard": "^2.1.3", "cordova-plugin-ionic-webview": "^2.2.3", "cordova-plugin-splashscreen": "^5.0.2", "cordova-plugin-statusbar": "^2.4.2", "cordova-plugin-whitelist": "^1.3.3", "core-js": "^2.5.4", "rxjs": "~6.3.3", "zone.js": "~0.8.26" }, "devDependencies": { "@angular-devkit/architect": "~0.10.0", "@angular-devkit/build-angular": "~0.10.0", "@angular-devkit/core": "~7.0.0", "@angular-devkit/schematics": "~7.0.0", "@angular/cli": "~7.0.0", "@angular/compiler": "~7.0.0", "@angular/compiler-cli": "~7.0.0", "@angular/language-service": "~7.0.0", "@ionic/angular-toolkit": "~1.2.0", "@types/node": "~10.12.0", "@types/jasmine": "~2.8.8", "@types/jasminewd2": "~2.0.3", "codelyzer": "~4.5.0", "jasmine-core": "~2.99.1", "jasmine-spec-reporter": "~4.2.1", "karma": "~3.0.0", "karma-chrome-launcher": "~2.2.0", "karma-coverage-istanbul-reporter": "~2.0.1", "karma-jasmine": "~1.1.2", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.4.0", "ts-node": "~7.0.0", "tslint": "~5.11.0", "typescript": "~3.1.6" }, "description": "An Ionic Weather project", "cordova": { "plugins": { "cordova-plugin-whitelist": {}, "cordova-plugin-statusbar": {}, "cordova-plugin-device": {}, "cordova-plugin-splashscreen": {}, "cordova-plugin-ionic-webview": { "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+" }, "cordova-plugin-ionic-keyboard": {} }, "platforms": [ "android" ] } } |