Nella lezione precedente abbiamo implementato le operazioni sui dati in locale sul dispositivo: salvataggio, recupero ed eliminazione. Ma l'obiettivo principale della nostra applicazione è l'invio di questi dati al server centrale. Vediamo come implementare questa funzionalità esplorando allo stesso tempo le relative API di Cordova e le problematiche di gestione della connettività.
Verificare la connettività
Una delle assunzioni che non dobbiamo assolutamente fare nello sviluppo di un'applicazione mobile è che il dispositivo sia sempre online: l'utente potrebbe aver disabilitato la connettività o potrebbe non essere disponibile una rete wireless. Per questo motivo abbiamo previsto il salvataggio dei dati in locale, per consentire all'utente di lavorare indipendentemente dalla connessione e inviare i dati quando la connessione diviene disponibile.
Nello sviluppo dell'interfaccia utente avevamo già predisposto un pulsante per l'invio delle schede al server. Alla pressione su questo pulsante, prima dell'invio effettivo, dovremmo assicurarci che il dispositivo sia connesso ad una rete.
A questo scopo Apache Cordova ci mette a disposizione l'oggetto navigator.connection che ci fornisce informazioni sulla connessione wi-fi o cellulare del dispositivo. L'oggetto prevede la proprietà type
che può assumere uno dei seguenti valori:
Connetion.UNKNOWN
Connection.ETHERNET
Connection.WIFI
Connection.CELL_2G
Connection.CELL_3G
Connection.CELL_4G
Connection.CELL
Connection.NONE
Il loro significato è abbastanza evidente e la distinzione tra i vari tipi di connessione cellulare ci consente anche di valutare se la banda disponibile può essere sufficiente per la quantità di dati che dobbiamo ricevere o inviare.
Utilizziamo l'oggetto navigator.connection
nella nostra applicazione per implementare il metodo isOnline() come mostrato di seguito:
var app = {
// ...
isOnline: function() {
var networkState = navigator.connection.type;
return ((networkState != Connection.NONE) && (networkState != Connection.UNKNOWN));
},
// ...
}
Con questo metodo avremo modo di stabilire in qualsiasi momento se è disponibile una connessione o meno.
Invio dei dati
Una volta che ci siamo assicurati la disponibilità di una connessione, l'invio dei dati al server non è altro che una classica chiamata Ajax al server secondo le specifiche previste dal backend.
Gestiamo l'evento tap
sul pulsante di invio prevedendo le richieste di conferma come mostrato dal seguente codice:
$("#btnInviaSchede").on("tap", function() {
if (app.isOnline()) {
navigator.notification.confirm(
"Confermi l'invio delle schede?",
function(buttonIndex) {
if (buttonIndex == 1) {
// Invio schede
}
},
"Conferma invio",
"Sì,No");
} else {
navigator.notification.alert("Connessione Internet non disponibile!", function(){},"Informazione");
}
});
Per l'invio schede effettivo prevediamo un metodo send()
dell'oggetto scheda
che prevede come parametri l'elenco delle schede da inviare e due callback rispettivamente per l'invio con successo e per l'eventuale fallimento. Il codice in corrispondenza della conferma dell'utente diventa quindi:
function(buttonIndex) {
if (buttonIndex == 1) {
var listaSchede = [];
for (var i=0; i<app.storage.length; i++) {
scheda.load(app.storage.key(i));
listaSchede.push(scheda.data);
}
scheda.send(listaSchede,
function() {
navigator.notification.alert("Schede inviate!", function(){},"Informazione");
},
function() {
navigator.notification.alert("Si è verificato un problema durante l'invio delle schede!", function(){},"Errore");
});
}
}
Abbiamo creato un array di oggetti caricando le schede dal localStorage
e l'abbiamo passato al metodo send()
specificando le funzioni di callback di successo e fallimento.
Il metodo send()
della scheda avrà la seguente forma:
var scheda = {
// ...
send: function(listaSchede, successCallback, failCallback) {
$.ajax({
url: "http://www.backendserver.it/schedeImmobiliari",
type: "POST",
data: listaSchede})
.done(function() {app.storage.clear(); successCallback();})
.fail(failCallback);
}
// ...
}
Quindi niente di più che una chiamata Ajax al server di backend.
Considerazioni sulla sicurezza
Una delle prime osservazioni che qualche lettore potrebbe fare sull'invio di dati al server tramite Ajax riguarda la same origin policy, cioè l'impostazione di sicurezza che impedisce ad un browser di fare una richiesta ad un server diverso da cui si è prelevato il codice JavaScript in modo da prevenire attacchi di tipo cross-site.
Come abbiamo specificato all'inizio di questa guida, l'architettura di un'applicazione Cordova non è altro che un browser immerso in un'applicazione nativa. Ma il nostro codice JavaScript non è stato prelevato da un server, neanche dal server di backend verso cui inviamo i dati.
Trattandosi di codice locale non viene applicata la same origin policy e pertanto è possibile inoltrare richieste HTTP verso qualsiasi dominio.
Il controllo dei domini verso cui inviare richieste HTTP è affidato al file di configurazione web.config
tramite la chiave <access>
. Per impostazione predefinita questa chiave è impostata in modo da consentire l'accesso a qualsiasi dominio:
<access origin="*"/>
Tuttavia in produzione sarebbe opportuno, per precauzione, limitare l'accesso ai soli domini strettamente necessari per l'operatività dell'applicazione. Ad esempio, nel caso della nostra applicazione potremmo configurare la chiave nel seguente modo:
<access origin="http://www.backendserver.it"/>
È importante specificare esplicitamente il protocollo dal momento che questo fa parte integrante del namespace a cui si è autorizzati ad effettuare richieste. Ad esempio, se volessimo inoltrare richieste HTTP e HTTPS allo stesso server dovremmo inserire due chiavi distinte:
<access origin="http://www.backendserver.it"/>
<access origin="https://www.backendserver.it"/>
Analogamente se vogliamo consentire l'accesso a domini diversi dobbiamo inserire una chiave <access>
per ciascun dominio.