La API de Google
Maps v2 es parte del SDK de Google Play Services, el cual se instala como parte
del Android SDK completo.
Es necesario
tener en cuenta para el desarrollo que esta solamente permite la utilización de
emuladores configurados con Google Apis y Google Play Services, con versión mínima
4.2.2 (API 17) del SDK.
Lo mínimo necesario
Incluir en el Manifest los permisos mínimos, así como la clave de
Google Maps.
La aplicación
debe referenciar la librería Google Play Services para poder funcionar
correctamente:
<uses-permission
android:name="es.hubiqus.mapas.permission.MAPS_RECEIVE"/>
<uses-permission
android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<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-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.Light">
<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value=“...
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
|
Cabe destacar del Manifest anterior que en
los permisos de tipo MAPS_RECEIVE debe incluirse el
nombre de paquete de la app.
Esta clase debe chequear si se
encuentra habilitado el APK de Google Play Services en el dispositivo, en caso
contrario lanza una ventana de descarga del mismo, y cierra la app:
/**
* Chequear la APK Google Play Services APK
*
Si no, lanza diálogo para la descarga
*/
private boolean checkPlayServices() {
int resultCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode))
{
GooglePlayServicesUtil.getErrorDialog(resultCode,
this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
finish();
}
return false;
}
return true;
}
|
Incluir el
fragment de Google maps dentro de un layout de la app, por defecto incluye los
controles de zoom:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
|
Sobre el XML del
fragment se pueden establecer los valores de configuración del mapa, de forma
que al cargarlo ya aparecerá con las propiedades establecidas:
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment"
map:cameraBearing="92.5"
map:cameraTargetLat="36.7212"
map:cameraTargetLng="-4.4213"
map:cameraTilt="40"
map:cameraZoom="16"
map:mapType="hybrid"
map:uiCompass="false"
map:uiRotateGestures="true"
map:uiScrollGestures="true"
map:uiTiltGestures="false"
map:uiZoomControls="false"
map:uiZoomGestures="true"/>
|
Gestión del mapa
De la misma forma que a través del XML, por código se pueden
establecer algunas propiedades del mapa y/o modificarlas en tiempo de ejecución:
private GoogleMap mMap;
...
mMap = ((SupportMapFragment)
getSupportFragmentManager().
findFragmentById(R.id.map)).getMap();
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
|
A continuación se
muestra la forma de realizar acciones concretas en el mapa a través de la clase
CameraUpdate, que facilita todas las operaciones sobre el mismo.
Para centrar el mapa en un punto simplemente será necesario
trasladar la cámara hacia el mismo:
CameraUpdate camUpdate =
CameraUpdateFactory.newLatLng(new LatLng(36.719726,
-4.421611));
mMap.moveCamera(camUpdate);
|
Otra opción es animar la cámara, de forma que se produzca en el
mapa un efecto de traslado desde el punto de inicio al punto destino:
mMap.animateCamera(camUpdate);
|
Otra de las acciones habituales
será conocer la posición actual de la cámara, es decir, en qué punto se encuentra centrado el mapa:
CameraPosition camPosition = mMap.getCameraPosition();
String position = "Latitud: " + camPosition.target.latitude +
",Longitud: " + camPosition.target.longitude;
|
El objeto CameraPosition se puede emplear también para modificar
la posición actual de la cámara, permitiendo establecer un mayor número de parámetros
que los permitidos por los métodos de CameraUpdateFactory:
LatLng target = new LatLng(36.719726,
-4.421611);
CameraPosition pos = new
CameraPosition.Builder()
.target(target) //Centrar el mapa
.zoom(16) //Zoom
.bearing(45) //Orientación
.tilt(70) //Ángulo de cámara
.build();
CameraUpdate camUpdate =
CameraUpdateFactory.newCameraPosition(pos);
|
Agregar un marcador a un mapa con esta API es sencillo. El
siguiente código establece un marcador con icono personalizado, que al ser
pulsado mostrará un pequeño
diálogo sobre el mapa con título y descripción
(snippet):
mMap.addMarker(new MarkerOptions()
.position(new LatLng(36.719726, -4.421611))
.icon(BitmapDescriptorFactory.fromResource(R.drawable.blank))
.title("Málaga")
.snippet("Centro de Málaga"));
|
Para responder a eventos sobre la pulsación en el icono y poder
realizar acciones personalizadas, será necesario establecer un Listener sobre
el mapa:
mMap.setOnMarkerClickListener(new OnMarkerClickListener() {
public boolean
onMarkerClick(Marker marker) {
Toast t = Toast.makeText(MapaActivity.this,
marker.getTitle(),
Toast.LENGTH_SHORT);
t.show();
return false;
}
});
|
Además de Listeners para esta tarea, se pueden establecer para
otras acciones como el cambio de posición (OnCameraChangeListener) o también
para la pulsación de un punto cualquiera sobre el mapa:
mMap.setOnMapClickListener(new OnMapClickListener() {
public void
onMapClick(LatLng point) {
Toast t =
Toast.makeText(MapaActivity.this,
"Latitud:
" + point.latitude +
",
Longitud: " + point.longitude,
Toast.LENGTH_SHORT);
t.show();
}
});
|
Para que la ventana de información (InfoWindow) no aparezca sobre
el mapa, simplemente se pueden añadir marcadores sin título. Esto debe combinarse
con el OnMarkerClickListener para que la aplicación realice alguna acción
personalizada al pulsar sobre los marcadores:
mMap.addMarker(new MarkerOptions()
.position(new LatLng(36.719726, -4.421611))
.snippet("Centro de Málaga"));
|
También es
posible personalizar la ventana de información, creando un InfoWindowAdapter y
estableciéndolo en el mapa a través del método setInfoWindowAdapter.
App Google Maps
Para acciones
avanzadas con Google Maps siempre se puede recurrir a la aplicación propia de
Google que viene instalada en todos los dispositivos. Esta aplicación está basada
en las urls que se emplean en la propia web de Google, de forma que si se
intenta lanzar dicha url en un Intent, el dispositivo abrirá la aplicación
mostrando la información necesaria.
El siguiente código muestra una ruta entre dos puntos:
//Incluir dirflg=w para ruta a pie
String uri = "http://maps.google.com/maps?saddr=" + origen.getLatitud() + ","
+ origen.getLongitud() + "&daddr="
+
punto.getLatitud() + ","
+ punto.getLongitud();
Intent intent = new Intent( android.content.Intent.ACTION_VIEW, Uri.parse(uri));
intent.setClassName("com.google.android.apps.maps",
"com.google.android.maps.MapsActivity");
startActivity(intent);
|
Referencia