Qualunque sviluppatore che si sia trovato di fronte alla necessita di integrare nei propri applicativi web/mobile concetti come il geocoding, si sarà imbattuto, anche per sbaglio, nel potente e diffuso servizio offerto dalla casa di Montain View: The Google geocoding API. Ma non è di Google che vogliamo parlare, ma ben si di un altrettanto interessante e ricco strumento che ci permette di risolvere problematiche legate alla geolocalizzazione, ovvero i servizi offerti da Yahoo! Developer Network.

Sono diversi i motivi che ci hanno portato a scegliere Yahoo piuttosto che Google. In questa particolare circostanza dovevamo trovare un servizio meteo da incorporare in un App iOS e tra le varie opzioni la scelta è caduta proprio su Yahoo! Weather RSS Feed. Volutamente non scendiamo nei dettagli di questo ottimo servizio che corrispondeva esattamente alle nostre necessità, ma vi mostro una semplice specifica per motivare il tema di questo articolo. Il servizio meteo richiede un parametro WOEID che identifica univocamente una località georeferenziata per ottenere le condizioni meteorologiche contestualizzate. Questo parametro fin’ora lo ottenevamo proprio dal servizio di geolocalizzazione Yahoo! Maps Web Services – Geocoding API. Dandogli “in pasto” un indirizzo o il nome di una località, questo servizio risponde con un elenco di possibili elementi geolocalizzati affini a tale richiesta definiti proprio dal codice univoco corrispettivo (WOEID).

Fin qui tutto chiaro e semplice, supportati dalla chiara ed esaustiva documentazione abbiamo pubblicato l’App e ci siamo goduti il risultato fino a quando la fatidica notizia che il 17 Novembre 2012 tale servizio sarebbe divenuto a pagamento (link) e più precisamente sarebbe diventato il nuovo Boss Geo Service.

Il prezzo del nuovo WS sarà quantificato in base all’utilizzo e più precisamente sul numero di queries effettuate dalla nostra App al servizio Yahoo!

Per tutti coloro quindi, che come noi di Xonne, si sono trovati a dover mettere mano agli applicativi e migrare verso il nuovo WS BOSS, si sono letti la documentazione e hanno provveduto per tempo in modo da prevenire l’ultimatum del 17/11/2012.

Vi riporto quindi una rapida guida per creare un progetto su Yahoo! Developer in modo accedere al nuovo servizio e approccerò nel caso specifico l’implementazione su iOS.

Se non avete ancora una account su Yahoo! per accedere al program developer, assicuratevi le credenziali di accesso e procedete alla creazione di un nuovo project nel portale dedicato: Yahoo! Developer Network. Qui dovrete creare una nuova App, nel nostro caso di tipo client/desktop e tramite il setup Boss associare una carta di credito per il servizio a pagamento. Solo se ultimato questo ultimo passaggio, il nostro progetto ci attiverà i servizi riservati.

La creazione di questo progetto genererà 2 chiavi (stringhe) Consumer Key e Consumer Secret da utilizzare per l’autenticazione delle nostre request da client. Il nuovo servizio sfrutta il sistema di autenticazione OAuth (link ufficiale), tale protocollo permette di abilitare le API di Yahoo per il dialogo con il nostro applicativo. Se volete approfondire come Yahoo! sfrutta l’OAuth vi consiglio questi 2 interessanti documenti: Using OAuth with BOSS Geo e OAuth Autohirization Flow.

Passiamo allo sviluppo su iOS. Come avete potuto vedere l’implementazione di questo protocollo diventa oneroso per lo sviluppatore ed è per questo che vi introduco una libreria open per incorporare tutta questa logica in un unico oggetto: OAuthConsumer. Vediamo un pò di codice:

[sourcecode language=”objc”]
– (void)callYahooServicePlacefinder
{
static NSString const *kAPIYahooKey = @””;
static NSString const *kAPIYahooKeySecret @””;

// — Istanzio oggetto OAuth — //
OAConsumer *oAuth = [[OAConsumer alloc] initWithKey:kAPIYahooKey secret:kAPIYahooKeySecret];

// — URL END-POINT — //
NSURL *url = [NSURL URLWithString:@”http://yboss.yahooapis.com/geo/placefinder”];

// — Creo request — //
OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:url consumer:oAuth token:nil realm:@”yahooapis.com” signatureProvider:[[OAHMAC_SHA1SignatureProvider alloc] init]];
[request setHTTPMethod:@”GET”];

// — Parametro località — //
NSString *nameCity = @”Parma+Emilia Romagna+Italia”;

// — Parametri request — //
OARequestParameter *locationParam = [[OARequestParameter alloc] initWithName:@”location” value:nameCity];
NSArray *params = [NSArray arrayWithObjects:locationParam, nil];
[request setParameters:params];

// — Fetching response — //
OADataFetcher *fetcher = [[OADataFetcher alloc] init];
[fetcher fetchDataWithRequest:request delegate:self didFinishSelector:@selector(yahooServiceDidFinishWithTicket:andData:) didFailSelector:@selector(yahooServiceFail)];
}

/*
* Request Finish
*/
– (void)yahooServiceDidFinishWithTicket:(OAServiceTicket *)ticket andData:(NSData *)data
{
//Response success
if (ticket.didSucceed) {
//Ottengo stringa risponsta
NSString *stringResponse = [[NSString alloc] initWithBytes:data.bytes length:data.length encoding:NSUTF8StringEncoding];
NSLog(@”String response: %@”, stringResponse);
}
}

/*
* Request Fail
*/
– (void)yahooServiceFail
{
NSLog(@”OAuth Yahoo service fail”);
}[/sourcecode]

Utilizziamo quindi l’oggetto OAConsumer per wrappare le credenziali di autenticazione e lanciare una request HTTP al nostro end-point Yahoo! Boss Placefinder. Essendo questo un servizio che prende dei parametri tramite metodo GET integriamo tali parametri uttilizzando sempre la nostra libreria che si incaricherà di concatenare le sequenze chiavi+valore nel nostro URL. Infine tramite OADataFetcher deleghiamo la nostra classe a gestire tramite 2 callback le risposte del servizio.

Come avrete notato dalla documentazione del servizio, è possibile definire tramite un parametro flag l’oggetto di risposta che più ci aggrada, nel nostro caso abbiamo optato tra le varie scelte il JSON. Vi invito a guardare la struttura del XML/JSON per decidere come parsare tale risultato. Example Placefinder response. Ecco riportato un esempio:

[sourcecode lang=”xml”]
{
“bossresponse”: {
“responsecode”: “200”,
“placefinder”: {
“start”: “0”,
“count”: “1”,
“request”: “flags=J&location=San%20Francisco%2C%20CA”,
“results”: [{
“quality”: “40”,
“latitude”: “37.777119”,
“longitude”: “-122.41964”,
“offsetlat”: “37.777119”,
“offsetlon”: “-122.41964”,
“radius”: “8800”,
“name”: “”,
“line1”: “”,
“line2”: “San Francisco, CA”,
“line3”: “”,
“line4”: “United States”,
“house”: “”,
“street”: “”,
“xstreet”: “”,
“unittype”: “”,
“unit”: “”,
“postal”: “”,
“neighborhood”: “”,
“city”: “San Francisco”,
“county”: “San Francisco County”,
“state”: “California”,
“country”: “United States”,
“countrycode”: “US”,
“statecode”: “CA”,
“countycode”: “”,
“uzip”: “94102”,
“hash”: “”,
“woeid”: “2487956”,
“woetype”: “7”
}]
}
}
}
[/sourcecode]

La nostra esperienza ci ha portato ad avere una certa sensibilità per questo genere di servizi che spesso possono variare in breve tempo, quindi vi invito a tenere sotto controllo la documentazione in maniera da non incappare in spiacevoli sorprese!

Grazie e buona lavoro!