En el quinto capítulo del Curso Android seguiremos trabajando con el hardware de los teléfonos, ahora nos corresponde aprovechar el GPS y mostrar la ubicación actual en un mapa. La aplicación que realizaremos nos permitirá mostrar la ubicación y actualizarse cada vez que exista movimiento.
Es importante notar que las pruebas de este capítulo al igual que los capítulos 4 y 5 son para realizarlas en un teléfono con Android es posible utilizar el emulador con algunos arreglos. Ejemplo: obtener localización, monitorear sus cambios y mostrarla en un mapa a través de markers. Queremos que al finalizar se vea de la siguiente form:
Disposición inicial
Iniciamos descargando el código que debe ser importado hacia un nuevo proyecto y que tiene algunas características importantes.
- Permisos en el Manifest, por el acceso a internet para el mapa y la ubicación del GPS requerimos estos 2 permisos bajo el tag:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- Uso de la librería de mapas, también en el Manifest bajo el tag:
<uses-library android:name="com.google.android.maps" />
- En la clase de la actividad principal, utilizaremos herencia de
MapActivity
para facilitarnos el manejo del mapa e implementaremos la interfazLocationListener
para detectar los cambios en la localización. - Por heredar de
MapActivity
debemos implementar el método:@Override protected boolean isRouteDisplayed() { return false; }
- Por implementar LocationListener debemos realizar los siguientes métodos:
@Override public void onLocationChanged(Location location) {} @Override public void onProviderDisabled(String provider) {} @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(String provider) {}
Diseño
Utilizaremos una vista especial para el mapa es necesario un key para la utilización del servicio de Google Maps y depende directamente del certificado utilizado para firmar las aplicaciones, el valor del atributo android:apiKey
que aparece en el código es válida para mi certificado.
<com.google.android.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="0xJ4uwRGDV296srCn4Iiy46oFmd1jecLr07BsAA" />
Agregando código
La clase de la Activity
para nuestra aplicación extenderá de MapActivity
para facilitarnos el manejo de la visualización del mapa e implementará LocationListener
para el manejo de las actualizaciones de ubicación.
public class Main extends MapActivity implements LocationListener
De los métodos disponibles, utilizaremos onProviderDisabled
para forzar al usuario a tener el GPS funcionando antes de que la aplicación inicie.
@Override public void onProviderDisabled(String provider) { Intent intent = new Intent( android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(intent); }
Vamos a mostrar un marker
en las diferentes ubicaciones detectadas, para ello haremos una clase que represente este Overlay
mostrando la imagen seleccionada. Para este ejemplo se utilizará la imagen del ícono, al definirla dentro de la misma clase de la Activity
principal entonces será una clase privada.
class MyOverlay extends Overlay { }
Tendremos una variable de instancia representando el punto donde se colocará el marcador y será un parámetro recibido por el constructor:
GeoPoint point; /* El constructor recibe el punto donde se dibujará el marker */ public MyOverlay(GeoPoint point) { super(); this.point = point; }
Sobrecargaremos el método draw
para dibujar nuestro marker
:
@Override public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) { super.draw(canvas, mapView, shadow); //se traduce el punto geo localizado a un punto en la pantalla Point scrnPoint = new Point(); mapView.getProjection().toPixels(this.point, scrnPoint); //se construye un bitmap a partir de la imagen Bitmap marker = BitmapFactory.decodeResource(getResources(), R.drawable.icon); //se dibuja la imagen del marker canvas.drawBitmap(marker, scrnPoint.x - image.getWidth() / 2, scrnPoint.y - marker.getHeight() / 2, null); return true; }
El código completo de la clase para los overlays
es el siguiente:
class MyOverlay extends Overlay { GeoPoint point; //El constructor recibe el punto donde se dibujará el marker public MyOverlay(GeoPoint point) { super(); this.point = point; } @Override public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) { super.draw(canvas, mapView, shadow); //se traduce el punto geolocalizado a un punto en la pantalla */ Point scrnPoint = new Point(); mapView.getProjection().toPixels(this.point, scrnPoint); //se construye un bitmap a partir de la imagen Bitmap marker = BitmapFactory.decodeResource(getResources(), R.drawable.icon); // se dibuja la imagen del marker canvas.drawBitmap(marker, scrnPoint.x - marker.getWidth() / 2, scrnPoint.y - marker.getHeight() / 2, null); return true; } }
Para ir dibujando estos markers al principio y cada vez que haya una actualización de la ubicación, utilizaremos un método nuevo con la firma:
protected void updateLocation(Location location)
Obtenemos el MapView
y de él un MapController
:
MapView mapView = (MapView) findViewById(R.id.mapview); MapController mapController = mapView.getController();
Construimos un punto a partir de la latitud y longitud del Location
recibido:
GeoPoint point = new GeoPoint((int) (location.getLatitude() * 1E6), (int) (location.getLongitude() * 1E6));
Movemos el centro del mapa hacia esta ubicación:
mapController.animateTo(point); mapController.setZoom(15);
Posterior a esto, intentaremos hacer geolocalización del punto, obtener una dirección a partir de las coordenadas del punto. Primero instanciamos un objeto Geocoder
que responderá de acuerdo a la localidad configurada en el teléfono.
Geocoder geoCoder = new Geocoder(this, Locale.getDefault());
A través de este Geocoder
y con el punto de la ubicación intentamos obtener alguna dirección asociada y se lo hacemos saber al usuario por medio de un toast
(aviso).
try { List<Address> addresses = geoCoder.getFromLocation(point.getLatitudeE6() / 1E6, point.getLongitudeE6() / 1E6, 1); String address = ""; if (addresses.size() > 0) { for (int i = 0; i < addresses.get(0).getMaxAddressLineIndex(); i++) address += addresses.get(0).getAddressLine(i) + "\n"; } Toast.makeText(this, address, Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); }
Por último, instanciamos la clase MyOverlay
construída previamente para agregar un nuevo marker en el listado de overlays del mapa e invalidamos la vista para que vuelva a dibujarse todo.
List<Overlay> mapOverlays = mapView.getOverlays(); MyOverlay marker = new MyOverlay(point); mapOverlays.add(marker); mapView.invalidate();
En el método onCreate
vamos a instanciar un LocationManager
para mostrar el primer marker y solicitar actualizaciones:
MapView mapView = (MapView) findViewById(R.id.mapview); //habilitamos el control de zoom mapView.setBuiltInZoomControls(true); LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); updateLocation(locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)); /* se actualizará cada minuto y 50 metros de cambio en la localización mientras más pequeños sean estos valores más frecuentes serán las actualizaciones */ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000, 50, this);
Luego en el método onLocationChanged
llamamos a nuestro método updateLocation
para que dibuje un nuevo marker cada vez que se actualice la localización:
@Override public void onLocationChanged(Location location) { updateLocation(location); }
Descarga:
Puedes descargar el código de la aplicación completa y funcional en: Geolocalización y utilización de mapas de Google.
Conclusión
En este capítulo aprendimos sobre:
- Cómo manejar un mapa, la necesidad de una vista especial y solicitar un API Key.
- Cómo dibujar markers a través de overlays sobre el mapa, además personalizamos la imagen del marker.
- Cómo solicitar la ubicación actual y actualizaciones ante el cambio de ubicación.
Adrian Catalán para Maestros del Web.
Agrega tu comentario | Enlace permanente al artículo