24 de febrer del 2018

Ionic: aplicació per saber l'hora de sortida/posta del sol (II)

Part II: Versió "clavada a ferro"

Aquest article ens mostrarà com fer una aplicació amb Ionic per saber l'hora de sortida i posta de sol en un lloc determinat.

En la primera part vàrem preparar el projecte inicial.

Ara farem una primera versió senzilla, on fixarem el lloc i el dia. Més endavant anirem modificant el codi per fer-lo més útil en general (i de passada anirem veien diferents tècniques).

En lloc de fer el càlcul de l'hora de sortida/posta de sol directament, l'aplicació es connectarà a internet per a obtenir-la. Amb una cerca ràpida a Google podem trobar una API que sembla feta a mida a https://sunrise-sunset.org/api.

En una primera versió, podem fer una petició simple amb:
 https://api.sunrise-sunset.org/json?
             lat=36.7201600&lng=-4.4203400&formatted=0

I obtindrem una resposta en JSON similar a:


Fixeu-vos que només necessitem la latitud i la longitud i fer una petició a l'API anterior per obtenir les dades que necessitem en la nostre aplicació.

En una aplicació Ionic, per poder fer peticions web, primer hem d'importar el mòdul HttpClientModule al fitxer app.module.ts. Quedaria com segueix:
 ...
 import { SplashScreen } from '@ionic-native/splash-screen';

 import { HttpClientModule } from '@angular/common/http';

 @NgModule({
  declarations: [
   ...
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  ...

Amb això ja podem implementar la funcionalitat desitjada en la pàgina home.ts:
 import { Component } from '@angular/core';
 import { NavController } from 'ionic-angular';

 import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';

 @Component({
  selector: 'page-home',
  templateUrl: 'home.html'
 })
 export class HomePage {
  API: string = "https://api.sunrise-sunset.org/json";
  
  // Estany de Sant Maurici
  lat: number = 42.582104;
  lon: number = 1.0008419;

  sunrise : string;
  sunset : string;

  constructor(  public navCtrl: NavController,
                public http: HttpClient )
  { }

  ionViewDidLoad() {
    console.log("Calling API...");

    let data = {  lat: this.lat.toString(), 
                  lng: this.lon.toString(),
                  formatted: "0"
                };

    const params = new HttpParams({fromObject: data});
    const headers = new HttpHeaders().set("Accept", "application/json");
    let options = { headers: headers, 
                    params: params, 
                    withCredentials: false
                  };

    this.http.get(this.API, options).subscribe(answer => {
      console.log(answer);

      if (answer['status']=="OK") {
        let date_options = {hour: "2-digit", minute: "2-digit"};

        this.sunrise = new Date(answer['results'].sunrise)
                               .toLocaleTimeString("ca-ES", date_options);
        this.sunset = new Date(answer['results'].sunset)
                               .toLocaleTimeString("ca-ES", date_options);

        console.log(this.sunrise);
        console.log(this.sunset);
      }
    },
    err => console.log(err)
    );
  }
 }

Observem l'estructura:
  • [4] Hem importat les classes que necessitarem.
  • [11-18] Declarem les variables internes a la classe, amb el seu tipus (gràcies, Typescript !) i opcionalment amb un valor per defecte. Aquí fixarem el valor de la latitud i la longitud del lloc que ens interessi a partir de les dades GPS (que podem obtenir a través de google maps, per exemple).
  • [21] Afegim el proveïdor per a les connexions a internet en el constructor.
  • [24] ionViewDidLoad és una funció que es crida una sola vegada, i és el lloc ideal per posar-hi codi d'inicialització. En aquest cas, com que les nostres dades no varien gaire sovint, les podem inicialitzar aquí. Val la pena consultar els cicles de vida d'una pàgina a Ionic a NavController.
  • [27-30] Preparem les dades en el format requerit per l'API. Necessitem convertir els números en strings.
  • [32-37] Generem els paràmetre i capçaleres de la nostre petició a l'API, i finalment ho posem tot plegat en un objecte options.
  • [39-55] Fem la petició i quan obtenim la resposta, extraiem les dades que volem mostrar. En cas d'error, traiem un missatge per la consola.
Val la pena comentar que la petició web retornarà les dades al cap d'un temps indeterminat. Per això, el valor es retorna a través d'un Observable, al qual ens subscrivim per rebre el seu valor quan estigui disponible.

Fixem-nos com el fitxer home.ts actua com a controlador de les dades de la classe. Per la seva banda, la visualització d'aquestes es fa en el fitxer home.html:
<ion-header>
  <ion-navbar>
    <ion-title>Sortida/posta de Sol</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-list>
    <ion-item-divider color="light">Lloc</ion-item-divider>
    <ion-item>
      <ion-label>Latitud</ion-label>
      <ion-note item-right>{{ lat }}</ion-note>
    </ion-item>
    <ion-item>
        <ion-label>Longitud</ion-label>
        <ion-note item-right>{{ lon }}</ion-note>
      </ion-item>
  
    <ion-item-divider color="light">Data</ion-item-divider>
    <ion-item>
      <ion-note item-right>Avui</ion-note>
    </ion-item>

    <ion-item-divider color="light">Horari</ion-item-divider>
    <ion-item>
      <ion-icon name="sunny" color="orange" item-left></ion-icon>
      <ion-note item-right>{{ sunrise }}</ion-note>
    </ion-item>
    <ion-item>
      <ion-icon name="moon" color="blue" item-left></ion-icon>
      <ion-note item-right>{{ sunset }}</ion-note>
    </ion-item>

  </ion-list>
</ion-content>

L'estructura utilitza tags tipus html que, de fet, són components pre-definits de Ionic. Amb això podem construir una interfície d'usuari agradable sense molt d'esforç: amb llistes, icones, etiquetes, etc...

El més destacable és com podem utilitzar en el fitxer html les variables que tenim definides en el nostre controlador, gràcies als operadors d'enllaç de dades d'Angular. En la nostre aplicació només utilitzem l'operador d'interpolació, {{ var }}, que serà substituït en la pàgina de sortida pel valor que tingui la variable en la classe en cada moment.

Bé, ha arribat el moment de veure el resultat:
 $ ionic serve -c -s

El resultat ens apareixerà en una finestra nova al navegador:


Observem com gràcies a les "Eines de desenvolupador" podem veure els missatges que surten per la consola. En el cas d'un objecte com el que obtenim de la petició a l'API [línia 40], el podem expandir i veure'n tots els detalls.

Però anem a veure com es genera l'aplicació mòbil. De fet, si tenim els SDK d'Android i el XCode ja instal·lats i configurats, és tan senzill com:
 $ ionic cordova build android
 $ ionic cordova build ios

El resultat es pot veure a continuació:


A l'esquerra hi ha una captura de pantalla directe des d'un Samsung S6, i a la dreta el resultat en l'emulador d'un iPhone 7.

Tal com es pot observar, Ionic ens permet obtenir una aplicació que corre en els dos principals sistemes operatius mòbils (i en la web, tot sigui dit de passada) a partir d'un mateix codi.

I parlant de codi, si us animeu a provar l'aplicació, la teniu disponible al GitHub: v0.1 (clavada a ferro). Proveu-la, i ja em comentareu.

Més endavant anirem modificant l'aplicació per permetre variar el lloc i la data, la qual cosa ens permetrà veure noves tècniques de programació, ús del GPS en els dispositius mòbils, etc...
Seguiu l'evolució de l'aplicació:

Cap comentari:

Publica un comentari a l'entrada