DevCorner: Location API e Gradle

Roberto Orgiu
Roberto Orgiu
DevCorner: Location API e Gradle

Cosa c'entrano i due argomenti del titolo l'un con l'altro? Tutto e niente. Niente perché sono semanticamente diversi, tutto perché senza Gradle non saremo più in grado di compilare i nostri progetti, molto probabilmente, soprattutto visto che Google sta migrando verso questa tecnologia tutti i processi riguardanti le proprie API. Vediamo quindi subito cosa ci serve per utilizzare una minima parte delle Location API.

Divideremo questo tutorial in sottoparagrafi per meglio dividere la mole di lavoro necessaria, assumendo di aver creato un'app il cui package sia it.androidworld.devcorner.maps e di aver installato correttamente sia Android Studio sia i componenti Google Play Services e Google Repository dal Software Development Kit di Android.

Creiamo gli hash dei KeyStore

Apriamo la console delle API di Google e creiamo un nuovo progetto tramite il pulsante rosso Create Project, inserendo un nome che ci ricordi quello che stiamo facendo come, ad esempio, Tutorial Maps DevCorner.

A questo punto, spostiamoci su APIs & auth e selezioniamo Google Maps Android API v2, ce dovremo abilitare premendo sul bottone con scritto OFF, che cambierà colore in verde ed etichetta in ON. Ora, sempre nel menu a sinistra, clicchiamo su Registered Apps e poi sul bottone Register App. Noteremo che ci viene chiesto il nome dell'applicazione e il suo tipo. Inseriamo quindi un nome che più ci piace e selezioniamo la tipologia Android: noteremo che sono apparsi altri due campi nella parte inferiore, che ci chiedono il package e lo SHA-1. Abbiamo già visto il pacchetto completo del nostro software, ma dobbiamo estrarre l'hash dei nostri KeyStore, ovvero sia quello default di debug, sia quello che Google ci ha rilasciato e che serve per inserire sul Play Store le nostre app.

Apriamo quindi la cartella contenente gli utenti del nostro sistema (C:\Users su Windows 7) e apriamo quella relativa al nostro user: all'interno troveremo una directory chiamata .android (data la nomenclatura, su sistemi Unix, questa cartella potrebbe essere nascosta) e, dentro quest'ultima, troveremo il file debug.keystore, che è il nostro bersaglio.

Apriamo quindi un prompt dei comandi, una shell o qualsivoglia interfaccia a caratteri che ci permetta di interagire con ADB e digitiamo il comando (tutto in una sola riga) per estrarre i dati dal KeyStore:

keytool -list -v -alias androiddebugkey -keystore debug.keystore 
-storepass android -keypass android >> android_debug_hash.txt

Nel file android_debug_hash.txt appena creato nella directory, troveremo un hash SHA1 nel paragrafo relativo alle Impronte digitali del certificato: copiamo tutto quello che sta oltre i due punti e lo andiamo ad incollare nel campo di testo della console che si è rivelato poche righe sopra. A questo punto possiamo proseguire con la procedura e ci ritroveremo ad una nuova pagina contenente i paragrafi OAuth 2.0 Client ID ed Android Key: espandiamo il secondo (come mostrato nello screenshot qui in basso) e clicchiamo sul pulsante + posto di fianco alla riga successiva alla dicitura Android Apps.

Ora, ci verrà richiesto di inserire un nuovo valore della forma hash;package e useremo questo campo per inserire l'hash relativo al nostro KeyStore di produzione: portiamoci quindi nella directory dove abbiamo il nostro KeyStore, che supponiamo chiamato MioKeystore.keystore e apriamo la nostra console preferita in questa cartella, digitando su una sola riga il comando

keytool -list -v -alias $aliasAndroid  -keystore MioKeystore.keystore
-storepass $passwordDelKeyStore -keypass $passwordDellAlias
>> android_production_hash.txt

Dove alle variabili precedute dal segno $ andremo a sostituire i valori che esse rappresentano.

Come prima, prendiamo l'hash SHA1 e lo incolliamo nel campo di testo della pagina web, accodandogli un ; e il nome del package, it.androidworld.devcorner.maps.

Perché inserire entrambi i fingerprint? Perché in questo modo il sistema riconoscerà la nostra app sia mentre sviluppiamo, sia dopo la pubblicazione, evitando errori di autenticazione.

Importiamo la libreria di Maps

Senza chiudere la pagina web, apriamo Android Studio e creiamo il nostro progetto come di consueto, andando ad aprire il file build.gradle più interno (freccia verde nello screenshot qui sotto) per inserire tra le parentesi graffe della sezione dependencies al fondo del file la riga

compile 'com.google.android.gms:play-services:4.0.30'

per avere, a grandi linee, una sezione così popolata

dependencies {
compile 'com.android.support:appcompat-v7:+'
compile 'com.google.android.gms:play-services:4.0.30'
}

Salviamo il file e attuiamo la sincronizzazione tra Gradle e il progetto mediante il tasto evidenziato dalla freccia rossa.

Grazie a questo procedimento, siamo riusciti ad integrare la libreria che ci serviva senza dover cercarne il file jar e includerlo nel progetto, si occuperà di tutto il nostro Gradle.

Localizziamo il nostro utente

Per iniziare, dovremo inserire nel nostro file Manifest tutta una serie di informazioni, a cominciare dai permessi

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

e abilitando l'utilizzo dell'OpenGL.

<uses-feature android:glEsVersion="0x00020000" android:required="true"/>

Ora, tornando nella pagina che avevamo lasciato aperta, noteremo una lunga voce alfanumerica sotto la scritta Api Key della sezione Android Key: copiamola ed incolliamola nella relativa parte del meta-tag XML (la sostituiamo alla variabile MIA_CHIAVE) che andremo ad inserire nel nostro file Manifest insieme al valore della versione della libreria di Play Service che stiamo utilizzando.

<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="MIA_CHIAVE"/>

Una piccola nota a margine: il valore @integer/google_play_services_version verrà calcolato ed inserito tra le nostre risorse direttamente da Gradle e, se dovesse esserci un errore dovuto al mancato riconoscimento, basterà effettuare un clean del progetto mentre, se la console vi restituisse un errore inerente il valore di minSdkVersion, potreste provare a dare un'occhiata alla sezione android del file build.gradle di prima, l'errore è spesso dato dalle impostazioni presenti nella sottosezione defaultConfig.

Passiamo ora al layout della nostra Activity, che conterrà semplicemente il Fragment relativo alla mappa e sarà costituito solo ed esclusivamente dalle seguenti righe

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.google.android.gms.maps.MapFragment"/>

Ora, manca solamente il codice Java e il nostro software è pronto per la compilazione: facciamo quindi implementare alla nostra Activity i listener che ci servono ed implementiamone i metodi:

  1. GooglePlayServicesClient.ConnectionCallbacks
  2. GooglePlayServicesClient.OnConnectionFailedListener

Nel metodo onCreate inizializziamo le nostre variabili

GoogleMap map = ((MapFragment) getFragmentManager()
.findFragmentById(R.id.map)).getMap();
LocationClient mLocationClient = new LocationClient(this, this, this);

Mentre, nei metodi onStart e onStop gestiamo la connessione e disconnessione del client per il rilevamento della posizione

public void onStop() {
mLocationClient.disconnect();
super.onStop();}
public void onStart() {
super.onStart();
mLocationClient.connect();}

A questo punto, una volta che il nostro dispositivo si è connesso, verrà lanciato un evento che il nostro metodo onConnected si occuperà di gestire: richiediamo quindi l'ultima posizione nota

Location mCurrentLocation = mLocationClient.getLastLocation();

creiamo un marker da inserire sulla mappe a partire dalla latitudine e longitudine ricavati dall'oggetto appena creato.

LatLng userMark = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());

Indichiamo quindi alla nostra GoogleMap di abilitare la nostra localizzazione e spostare il centro della mappa sul marker contenente le nostre coordinate

map.setMyLocationEnabled(true);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(userMark, 13));

Possiamo quindi posizionare il marker sulla mappa, specificando il titolo e il testo della descrizione che appariranno al tap sul marker stesso

map.addMarker(new MarkerOptions().title("Tu")
.snippet("Tu sei qui... forse.").position(userMark));

Conclusioni

Eccoci giunti alla fine di questo lungo DevCorner, le cui risorse sono, come di consueto, sul thread ufficiale. Questo, ovviamente, è solo un piccolo assaggio di quello che ci aspetta: restate sintonizzati, le novità non mancheranno!