You are on page 1of 19

Curso de Iniciacin a Android: Unidad 8

- Android prctico -

Uso de mapas v2 en aplicaciones de Android


La mayora de los dispositivos Android permiten determinar su ubicacin
geogrfica actual a travs de un mdulo GPS (del ingls Global Positioning
System, que se traduce como Sistema de Posicionamiento Global). Android
dispone del paquete android.location, que proporciona la API para determinar
la posicin actual geogrfica.
En la teora del curso se explica el uso de la API Google Maps v1. Como esta
versin dejar de estar activa a lo largo de 2013, el objeto de este documento
es describir el uso de la nueva API v2.
Por lo tanto, en este documento vamos utilizar mapas en aplicaciones de
Android haciendo uso de la API Android de Google Maps versin 2.0.
Esta nueva versin presenta muchas novedades interesantes, entre las que
cabe destacar:

Integracin con los Servicios de Google Play (Google Play Services) y la


Consola web de APIs.
Para utilizar los mapas debemos usar una nueva clase Java especfica
del tipo Fragment (MapFragment).
Uso de mapas vectoriales, aumentando la velocidad de carga y una
mayor eficiencia en cuanto al ancho de banda necesario.
Mejoras en el sistema de cach reduciendo en gran medida las
desgraciadamente famosas reas en blanco que tardan en cargar.
Disponibilidad de mapas en 3D, lo que permite mover el punto de vista
del usuario en perspectiva.

Preparacin del Entorno de programacin


Antes de empezar a utilizar el servicio de mapas de Google es necesario
comprobar que tenemos instalado el paquete correspondiente a las APIs de
Google. Este paquete se llama normalmente Google APIs by Google, Android
API x, revisin y.
Al instalar el SDK de Android en Eclipse deberas haber aadido ya este
paquete. Para comprobar que est correctamente instalado, haz clic en el
botn "Opens the Android SDK Manager" de Eclipse:

Debe aparecer el siguiente paquete como instalado ("Installed"):

-1-

Curso de Iniciacin a Android: Unidad 8


- Android prctico -

Nota: el nmero de revisin puede ser mayor que 2.


Muy importante: en la versin 2 de la API de Google Maps es necesario instalar
tambin los paquetes Google Play services y Android Support Library (ver
captura de pantalla anterior).
Nota: a la fecha de escritura de este texto, Google no permite probar las
aplicaciones que usan la API Maps v2 en el emulador de Eclipse. Por lo tanto,
debemos utilizar un dispositivo real e instalar y probar la aplicacin en l.
Obtencin de clave de uso de API Maps v2
Para poder utilizar la API de Google Maps v2 es necesario obtener previamente
una clave de uso (API Key) que estar asociada al certificado con el que
firmamos digitalmente las aplicaciones. En el apartado "Permisos y Seguridad"
de la Unidad 5 ya hemos hablado de estos certificados, necesarios para firmar
aplicaciones de Android.
Si cambiamos el certificado con el que firmamos nuestra aplicacin, algo que
normalmente se hace como paso previo a la publicacin de la aplicacin en el
Android Market, tendremos que modificar tambin la clave de uso de la API.
Cuando compilamos una aplicacin en Eclipse y la probamos, se aplica
automticamente un certificado de depuracin creado por defecto. Por lo tanto,
para poder depurar en un dispositivo Android aplicaciones que hagan uso de

-2-

Curso de Iniciacin a Android: Unidad 8


- Android prctico Google Maps v2, hay que solicitar una clave asociada a este certificado de
depuracin. Veamos cmo se pide.
Lo primero que debemos hacer es acceder con el navegador a esta pgina web
(es la Consola web de gestin de APIs de Google):
https://code.google.com/apis/console/
Es necesario disponer de un usuario de Google como, por ejemplo, del servicio
gMail. En esta ventana introduciremos los campos Email y Password y
hacemos clic en el botn Sign in.

A continuacin, aparece esta pgina:

Debemos pulsar en el botn Create project, despus, aparecer esta


pgina:

-3-

Curso de Iniciacin a Android: Unidad 8


- Android prctico -

Despus, debemos pulsar en la opcin Google Maps Android API v2. A


continuacin, aceptamos la licencia de uso de esta API:

Veremos que ya aparece activo el uso de esta API:

Finalmente, para obtener la clave de uso de esta API debemos hacer clic en la
opcin API Access que aparece en el men de la izquierda:

-4-

Curso de Iniciacin a Android: Unidad 8


- Android prctico -

Despus, pulsamos el botn de abajo Create new Android key y aparecer


la siguiente ventana superpuesta:

Para obtener la clave SHA1 que solicita la pgina, en primer lugar, hay que
localizar el fichero donde se almacena el certificado de depuracin
"debug.keystore". Podemos conocer la ruta de este fichero accediendo a las
preferencias de Eclipse, seccin "Android", apartado "Build":

-5-

Curso de Iniciacin a Android: Unidad 8


- Android prctico -

En esta ventana copiamos en el portapapeles la ruta que aparece en el campo


Default Debug Keystore. Observa que hemos borrado intencionalmente la
parte de la ruta que ser distinta en tu ordenador.
Una vez conocemos la ruta del fichero debug.keystore, vamos a acceder a l
con la herramienta keytool.exe de Java para obtener el hash SHA1 del
certificado. Esto lo hacemos desde una ventana de lnea de comandos en el
directorio C:\Program Files (x86)\Java\jre6\bin (o donde est instalado
Java) mediante la orden:
C:\Program
Files
(x86)\Java\jre6\bin>keytool
-list
-alias
androiddebugkey
-keystore
"ruta_del_certificado\debug.keystore"
storepass android -keypass android

Nota: es necesario usar la versin 6 de Java, pues en la 7 no funciona.


Si lo hacemos, veremos la siguiente ventana:

-6-

Curso de Iniciacin a Android: Unidad 8


- Android prctico -

A continuacin, copiamos en el portapapeles el dato que aparece identificado


como Huella digitales del certificado (SHA1).
Despus, accedemos de nuevo a la Consola de APIs de Google para solicitar
una clave de utilizacin de la API de Google Maps v2 para poder depurar
aplicaciones. En esta Web tendremos que escribir la Huella digital SHA1 de
nuestro certificado y el nombre del paquete (en el Ejemplo 2 de esta Unidad
del curso usamos el nombre de paquete es.mentor.unidad8.eje2.mapas.v2)
de la aplicacin para obtener la clave de uso de la API:

-7-

Curso de Iniciacin a Android: Unidad 8


- Android prctico -

En la siguiente imagen se muestra el resultado:

Nota: Observa que hemos borrado intencionalmente parte de la clave, pues,


cuando solicites sta, te darn otra diferente.
Ya hemos terminado la preparacin del entorno de programacin en Eclipse
para poder utilizar los servicios de Google Maps v2 dentro de nuestras
aplicaciones Android.

Cmo incluir mapas en las aplicaciones Android


En el Ejemplo 2b de esta Unidad vamos a desarrollar una aplicacin que
incluye un mapa sobre el que podemos hacer unas operaciones sencillas,
como cambiar a vista satlite o desplazar la posicin del mapa.
IMPORTANTE

-8-

Curso de Iniciacin a Android: Unidad 8


- Android prctico Para poder ver este proyecto en tu dispositivo Android es necesario que
obtengas la clave de uso de la API de Mapas de Google y la cambies en el
fichero de diseo AndroidManifest.xml del proyecto. Si no lo haces, arrancar
la aplicacin del ejemplo pero no se mostrar el mapa, como en la imagen
siguiente:

Para incluir un mapa de Google Maps en una aplicacin Android hay que
indicar la clave de uso de Google Maps v2 en el atributo android:value del
archivo AndroidManifest.xml del proyecto, tal y como se muestra a
continuacin:
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:allowBackup="false">
<!-- Aqu se escribe la clave de uso de Google Maps -->
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="clave_API"/>
...

Adems, en el fichero AndroidManifest, tambin debemos incluir los permisos


necesarios para poder utilizar los mapas. En primer lugar, definimos el permiso
llamado nombre_paquete.java.permission.MAPS_RECEIVE, en el ejemplo 2
quedara s:
<permission
android:name="es.mentor.unidad8.eje2.mapas.v2.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission
android:name="es.mentor.unidad8.eje2.mapas.v2.permission.MAPS_RECEIVE"
/>

-9-

Curso de Iniciacin a Android: Unidad 8


- Android prctico Despus, hay que aadir permisos adicionales que permiten a la aplicacin
acceder a los servicios web de Google, a Internet y al almacenamiento externo
del dispositivo para guardar la cach de los mapas descargados:
<uses-permission
android:name="com.google.android.providers.gsf.permission.READ_GSERVIC
ES"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Por ltimo, dado que la API v2 de Google Maps Android utiliza OpenGL ES
versin 2, debemos especificar tambin dicho requisito en el fichero
AndroidManifest aadiendo un nuevo elemento <uses-feature>:
<uses-feature android:glEsVersion="0x00020000"
android:required="true"/>

Una vez hemos configurado el archivo AndroidManifest, antes de escribir el


cdigo fuente, ha que aadir otras libreras externas a nuestro proyecto.
La primera de ellas es la librera de Google Play Services que hemos
descargamos al principio de este texto e integrarla en el proyecto Android. Para
hacerlo, desde Eclipse hacemos clic en la opcin de men principal File /
Import seleccionando la opcin Existing Android Code Into Workspace:

- 10 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico Podemos encontrar esta librera en la carpeta <carpeta-sdkandroid>/extras/google/google_play_services/libproject/google-playservices_lib:

Pulsando en el botn Aceptar podemos ver que la librera se ha cargado


globalmente en Eclipse.

A continuacin, vamos a importar esta librera en el proyecto del ejemplo del


curso. Con el botn derecho del ratn sobre la carpeta del proyecto, hacemos
clic en Properties y accedemos a la seccin Android de las preferencias. En la
ventana que aparece podemos aadir una nueva librera en la seccin inferior
- 11 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico llamada Library pulsando en el botn Add, seleccionando la librera recin
importada y aadindola a la lista de libreras disponibles en el proyecto:

En el esquema del proyecto debemos ver la librera de Google Play importada:

Finalmente, si deseamos que la aplicacin se pueda ejecutar desde versiones


anteriores de Android (concretamente en la versin de Android 2.3 del curso)
debemos asegurarnos de que el proyecto incluye la librera android-support-

- 12 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico v4.jar. Podemos encontrar esta librera en el directorio <carpeta-sdkandroid>/extras/android/support/v4/android-support-v4.jar. Debemos copiar
esta librera al directorio /lib de nuestro proyecto (puede ser necesario crear
esta carpeta dentro del proyecto).

A continuacin, hay que refrescar con la tecla F5 el proyecto para que


aparezca la librera e importarla con la opcin Build Path > Add to Build Path
del men desplegable que aparece al hacer clic con el botn derecho del ratn
sobre dicha librera:

Nota: las versiones ms recientes de ADT de Eclipse incluyen por defecto esta
librera en nuestros proyectos.

Estudio del cdigo fuente del ejemplo


En la anterior versin 1 de la API, para incluir un mapa en la aplicacin hay que
utilizar la clase Java MapView y su actividad contenedora debe ser del tipo
MapActivity. Con la nueva versin 2 de la API pasamos a tener una nica
clase especfica heredada de Fragment llamada MapFragment.
Esto nos permite, entre otras cosas, aadir uno o varios mapas a cualquier
actividad contando por supuesto con todas las ventajas del uso de la clase
Fragment.
Nota importante: como el nuevo control de mapas se basa en la clase
Fragment, para mantener la compatibilidad con versiones de Android anteriores
a la 3.0 hay que utilizar la librera de soporte android-support (ver nota
anterior).

- 13 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico Fragments es una nueva funcionalidad del SDK de Android que facilita el
desarrollo de las interfaces de las aplicaciones tanto en tabletas cmo en
telfonos.

Los Fragments son trozos de una Activity, podemos hacer una similitud con
los paneles en la programacin visual. Adems, pueden ejecutar cdigo y son
reutilizables. Es decir, podemos utilizar un Fragment en distintos sitios de una
misma aplicacin.
Son tiles en las tabletas y los telfonos porque los Fragments permiten, por
ejemplo, en el caso de que tengamos una tableta mostrar una Activity con 2
fragments (como una lista de datos y el detalle del dato seleccionado al lado).
Por otra parte, en el caso de un telfono podemos mostrar 2 Activities
separadas cada una con su propio Fragment (una pantalla tiene la lista y
haciendo clic en un registro se abre otra pantalla con el detalle). Veamos el
esquema de las interfaces de usuario a continuacin:

Esto facilita la programacin de la aplicacin al permitir definir fragmentos de


informacin que se pueden colocar en la interfaz de usuario casi si modificar
cdigo y reutilizando los distintos paneles en funcin del terminal Android.
Adems, el uso de la antigua versin 1 de la API de Google Maps era ms
complicado, la nueva versin simplifica el trabajo al programador. Por ejemplo,
la consulta de la posicin actual o la configuracin del tipo de mapa se hacan
directamente usando la clase MapView, mientras que la manipulacin de la
posicin y el zoom se hacan a travs del controlador asociado al mapa
MapController. Adems, el tratamiento de las coordenadas y unidades
utilizadas eran algo peculiares, teniendo estar continuamente convirtiendo de
grados a microgrados y stos a objetos GeoPoint.
Con la nueva API, todas estas operaciones se realizan directamente sobre la
clase base GoogleMap. Para obtener la referencia a este objeto, debemos usar
el mtodo getMap() del fragmento MapFragment que contenga nuestro mapa.
En el Ejemplo 2 la Actividad principal hereda la clase FragmentActivity, tal y
como vemos en el siguiente cdigo:
public class MapasActivity extends android.support.v4.app.FragmentActivity
// Variables donde se definen los controles de la Actividad
private GoogleMap mapa = null;
private Button sateliteBtn = null;
private Button irBtn = null;
private Button animarBtn = null;
private Button posicionBtn = null;
private CameraUpdate controlMapa = null;

- 14 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Obtenemos una referencia a las Vistas de la Actividad
// Obtenemos la referencia al mapa
// En Android 3.0 a superior podemos usar el mtodo
// getFragmentManager()en lugar de getSupportFragmentManager
// y SupportMapFragment en lugar de MapFragment.
mapa = ((SupportMapFragment)getSupportFragmentManager().
findFragmentById(R.id.mapa)).getMap();
// Botones de la aplicacin
sateliteBtn = (Button)findViewById(R.id.SateliteBtn);
irBtn = (Button)findViewById(R.id.IrBtn);
animarBtn = (Button)findViewById(R.id.AnimarBtn);
posicionBtn = (Button)findViewById(R.id.PosicionBtn);
// Definimos el Controlador del mapa: movemos el mapa a una posicin y hacemos
// zoom a 5 (puede tomar el valor de 1 a 21)
controlMapa = CameraUpdateFactory.newLatLngZoom(new LatLng(40.41, -3.69), 5F);
// Modemos el mapa
mapa.moveCamera(controlMapa);
// Definimos el evento onClick del botn Satlite
sateliteBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// Intercambiamos la capa de tipo satlite en el mapa
if(mapa.getMapType()==GoogleMap.MAP_TYPE_SATELLITE) {
mapa.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// Cambiamos el texto del botn
sateliteBtn.setText("Satlite");
// Seleccionamos la imagen que muestra el botn
sateliteBtn.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.tierra, 0, 0);
} else {
mapa.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
sateliteBtn.setText("Normal");
sateliteBtn.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.mapa, 0, 0);
}
}
});
// Definimos el evento onClick del botn Ir a...
irBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// Definimos un nuevo punto de localizacin
LatLng loc = new LatLng(40.654754, -4.690958);
// Creamos una posicin nueva de cmara
CameraPosition camPos = new CameraPosition.Builder()
.target(loc) // Centramos el mapa en la localizacin
.zoom(12)
// Establecemos el zoom en 12
.bearing(45) // Establecemos orientacin con el noreste arriba (45)
.tilt(0)
// No modificamos el punto de vista de la cmara
.build();
// Establecemos el nuevo punto de vista de la cmara
controlMapa = CameraUpdateFactory.newCameraPosition(camPos);
// Movemos la cmara a la nueva posicin en el mapa
mapa.moveCamera(controlMapa);
}
});

- 15 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico // Definimos el evento onClick del botn Animar
animarBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// Definimos un nuevo punto de localizacin
LatLng loc = new LatLng(40.93779, -4.1167040);
// Creamos una posicin nueva de cmara
CameraPosition camPos = new CameraPosition.Builder()
.target(loc)
// Centramos el mapa en la localizacin
.zoom(12)
// Establecemos el zoom en 12
.bearing(0)
// Establecemos la orientacin con el norte arriba (0)
.tilt(0)
// No modificamos el punto de vista de la cmara
.build();
// Establecemos el nuevo punto de vista de la cmara
controlMapa = CameraUpdateFactory.newCameraPosition(camPos);
// Animamos el movimiento de la cmara en el mapa
mapa.animateCamera(controlMapa);
}
});
// Definimos el evento onClick del botn Posicin Actual
posicionBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// Obtenemos la posicin actual de la cmara en el mapa
CameraPosition camPos = mapa.getCameraPosition();
// Obtenemos la latitud y longitud de la cmara en el mapa
LatLng pos = camPos.target;
// Mostramos un mensaje al usuario
Toast.makeText(MapasActivity.this,
"Posicin actual - Lat: " + pos.latitude + " - Lng: " + pos.longitude,
Toast.LENGTH_LONG).show();
}
});
} // end clase Actividad
}

A continuacin, vamos a explicar las partes importantes del cdigo anterior.


el mtodo onCreate() de
getSupportFragmentManager() para
GoogleMap.

En

la Actividad se invoca el mtodo


obtener la referencia al componente

Como todas las operaciones se realizan directamente sobre el objeto GoogleMap,


componente base de la API, debemos acceder a este componente invocando
al mtodo getMap() del fragmento MapFragment que contenga nuestro mapa.
Por defecto, cuando usamos un GoogleMap en una aplicacin, se muestra en el
modo de mapa tradicional (callejero). Sin embargo, este componente tambin
permite cambiar las capas a la vista satlite o ver fotos de la calle con
StreetView. Para ello, utilizar el mtodo setMapType() indicando como parmetro
el tipo de mapa:

MAP_TYPE_NORMAL
MAP_TYPE_HYBRID
MAP_TYPE_SATELLITE
MAP_TYPE_TERRAIN

- 16 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico En el evento onClick del botn sateliteBtn hemos usado el mtodo
setMapType() para intercambiar el modo satlite y el estndar.
Esta nueva versin de la API da ms libertad que la anterior versin a la hora
de cambiar el centro del mapa, ya que podemos mover libremente el punto de
vista (o Cmara, como lo denomina Android) por un espacio en 3 dimensiones
(3D). Por lo tanto, ya no slo debemos hablar de latitud-longitud (target) y zoom,
sino tambin de orientacin (bearing) y ngulo de visin (tilt). La manipulacin
de estos 2 ltimos parmetros permite visualizar edificios en 3D de muchas
ciudades.
El movimiento de la cmara se realiza siempre mediante la construccin de un
objeto de la clase CameraUpdate o de sus clases heredadas con los parmetros
necesarios.
Para movimientos bsicos como la actualizacin de la latitud y longitud o el
nivel de zoom podemos utilizar la clase CameraUpdateFactory y sus mtodos
estticos. Por ejemplo, usamos esta clase en el mtodo onCreate() de la
actividad para posicionar el mapa y hacer zoom a 5.
El nivel de zoom del mapa contiene un valor entero entre 1 y 21, siendo 21 el
que ofrece mayor nivel de detalle en el mapa.
Adems, esta clase dispone, entre otros, de los siguientes mtodos:

CameraUpdateFactory.zoomIn(): aumenta en 1 el nivel de zoom.


CameraUpdateFactory.zoomOut(): disminuye en 1 el nivel de zoom.
CameraUpdateFactory.zoomTo(nivel_de_zoom): establece el nivel de
CameraUpdateFactory.newLatLng(lat,
long):
establece
la

zoom.
lat-lng

expresadas en grados.

CameraUpdateFactory.newLatLngZoom(lat, long, zoom):

establece la lat-lng

y el zoom respectivamente.

CameraUpdateFactory.scrollBy(scrollHorizontal, scrollVertical):

mueve

la cmara lateralmente por el mapa (panning).


Una vez hemos creado el objeto CameraUpdateFactory con los parmetros de
posicin que deseamos establecer en el mapa hay que invocar uno de los
mtodos moveCamera() o animateCamera() del objeto GoogleMap, si queremos que
la actualizacin de la vista se muestre directamente o de forma animada
respectivamente.
Aparte de los movimientos bsicos que hemos estudiado anteriormente, es
posible modificar los dems parmetros de la cmara o varios de ellos
simultneamente
mediante
el
mtodo
general
CameraUpdateFactory.newCameraPosition() que recibe como parmetro un objeto
de tipo CameraPosition. Este objeto los construimos indicando todos los
parmetros de la posicin de la cmara a travs de su mtodo Builder().

- 17 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico En este ejemplo hemos incluido un botn irBtn que centra el mapa sobre un
punto determinado, aplica un nivel de zoom (12), establece la orientacin con el
noreste arriba (45) y no modifica el punto de vista de la cmara. Si pruebas el
ejemplo del curso, vers que el desplazamiento a la posicin y el zoom al nivel
indicados se hacen de forma instantnea sin ningn tipo de animacin
mediante el uso del mtodo moveCamera().
En el botn animarBtn hemos usado es mtodo animateCamera() para animar el
movimiento del mapa.
Finalmente, si el usuario se mueve de forma manual por el mapa, es posible
conocer la posicin actual de la cmara mediante el mtodo
getCameraPosition() del mapa que devuelve un objeto del tipo CameraPosition.
Usando sus diferentes mtodos y propiedades podemos conocer con exactitud
la posicin de la cmara, su orientacin y el nivel de zoom.
En el botn posicionBtn hemos usado es mtodo getCameraPosition() para
mostrar la posicin actual en el mapa.
Desde Eclipse puedes abrir el proyecto Ejemplo 2b (Mapas) de la Unidad 8.
Estudia el cdigo fuente y ejectalo para mostrar en el AVD el resultado del
programa anterior, en el que hemos utilizado un mapa.
Si ejecutas la aplicacin en el emulador de Android, vers que tiene el siguiente
aspecto:

- 18 -

Curso de Iniciacin a Android: Unidad 8


- Android prctico Atencin: si intentas ejecutar este ejemplo en el emulador del curso vers en la
Vista Logcat de Eclipse los siguientes errores:

A la fecha de redaccin de este documento, no es posible ejecutar aplicaciones


que requieran la utilizacin de Google Play.
Otro error que puede aparecer es el siguiente. Si al cargar el proyecto del
ejemplo 2 aparece el error CameraPosition cannot be resolved to a type:

Debemos importar de nuevo la librera de Google Play en Eclipse y en el


proyecto.

- 19 -

You might also like