Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

11
Mapas offline en Android con OpenStreetMap y la librería MapsForge Posted on 11 agosto, 2014 En este artículo vamos a ver cómo integrar mapas offline en nuestra aplicación gracias a OpenStreetMap y la librería MapsForge. Los mapas offline nos permiten mostrar al usuario de nuestra aplicación un mapa con toda la información necesaria pero sin requerir conexión a internet, los mapas se almacenan en el teléfono. La librería MapsForge es una librería libre y gratuita que integra los mapas de OpenStreetMap en Android, sus características principales son: Formato de archivo ligero para renderizado rápido de datosOpenStreetMap en el dispositivo De fácil uso, similar a la librería de Google Maps (v1) API de capas potente y flexible Estilos de mapas personalizables mediante ficheros de configuración XML Librería de sólo 400KB de tamaño 100% libre y gratuita Eso es lo que nos ofrece MapsForge, además hace nada han

description

Explicacion de como crear un aplicacion movile utilizando cartografia offline de OpenStreetMaps,

Transcript of Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

Page 1: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

Mapas offline en Android conOpenStreetMap y la libreríaMapsForgePosted on 11 agosto, 2014

En este artículo vamos a ver cómo integrar mapas offline en nuestraaplicación gracias a OpenStreetMap y la librería MapsForge.

Los mapas offline nos permiten mostrar al usuario de nuestraaplicación un mapa con toda la información necesaria pero sinrequerir conexión a internet, los mapas se almacenan en el teléfono.

La librería MapsForge es una librería libre y gratuita que integra losmapas de OpenStreetMap en Android, sus característicasprincipales son:

Formato de archivo ligero para renderizado rápido dedatosOpenStreetMap en el dispositivoDe fácil uso, similar a la librería de Google Maps (v1)API de capas potente y flexibleEstilos de mapas personalizables mediante ficheros deconfiguración XMLLibrería de sólo 400KB de tamaño100% libre y gratuita

 

Eso es lo que nos ofrece MapsForge, además hace nada han

Page 2: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

publicado una actualización que facilita mucho las cosas, elproblema es que cambia mucho respecto a la versión anterior, y, adía de hoy la documentación está sin actualizar, por lo que hay quemirar los ejemplos que publicaron para poder entender algo, sobretodo si es la primera vez que la utilizas. Ese es uno de losprincipales motivos que me han llevado a escribir este artículo, yaque me ha costado un mundo implementar la librería en miaplicación.

Dicho esto, vamos a  ello.

Los pasos necesarios, en resumen, son:

Generar un fichero con el mapa de nuestra zona y convertirloal formato utilizado por MapsForgeIntegrar la librería en nuestro proyectoCopiar los datos a la tarjeta SD del dispositivo, ya sea a manoo mediante código, aquí para reducir el tamaño del artículo loharemos a manoImplementar la lógica de la aplicación

De extra veremos cómo ejecutar una tarea al hacer click en unMarker

1.­ Generar fichero con el mapa de nuestra zona

Lo primero que hay que hacer es generar el fichero ".map" con elmapa de la zona que incluiremos en nuestra aplicación, para ellovamos a esta página web: OpenStreetMap Data Extracts yseleccionamos el continente y país de la zona que incluiremos ennuestra aplicación. Para este ejemplo yo he entrado en "Europe­>Spain" y he descargado el fichero con nombre "spain­latest.osm.pbf".

Una vez tenemos el fichero con extensión "pbf" necesitamos otraherramienta más llamada Osmosis que podemos descargarpinchando aquí.

Una vez descargado lo descomprimimos y accedemos a la carpetadesde una terminal en Linux o desde la consola de comandos enWindows. Para generar nuestro mapa tendríamos que ejecutar elsiguiente comando:

osmosis ‐‐read‐pbf file=spain‐latest.osm.pbf ‐‐bounding‐box 

Page 3: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

–read­pbf file: Requiere la ruta a nuestro fichero "pbf" descargadoantes.

–write­xml: Nombre del fichero generado (respetar la extensión".osm")

Dónde se nos piden 4 valores que no conocemos, que son lascoordenadas que limitan nuestra zona, por tanto tendremos queconseguirlas. Para ello entramos aquí, navegamos por el mapahasta la zona que incluiremos en nuestra aplicación y pinchamos enla opción de la izquierda que dice "Seleccionar manualmente unárea diferente" lo que nos permitirá seleccionar la zona mostrandolas coordenadas. Así que la seleccionamos y lo dejamos comoestá.

Ahora tenemos que pasar esas coordenadas a Osmosis. Segúnpodemos ver en la imagen anterior las coordenadas están situadaspor punto cardinal, por tanto la COORDENADA_OESTE está en laizquierda, la COORDENADA_NORTE está arriba y así. Por lo que elcomando quedaría así:

osmosis ‐‐read‐pbf file=spain‐latest.osm.pbf ‐‐bounding‐box 

El nombre del fichero resultante es "coruna.osm", podemos llamarlocomo queramos pero respetando la extensión ".osm" para no tenerproblemas a posteriori.

Ya tenemos el mapa de nuestra zona generado en formatoOpenStreetMap, pero como vimos en las características principalesMapsForge usa un formato de archivo diferente que reduce eltamaño considerablemente, por lo que nos falta convertir el fichero".osm" generado al formato ".map" de MapsForge para ellonecesitamos un plugin que pondremos a Osmosis.

El plugin en cuestión se llama "Map Writer" y lo podéis descargar

Page 4: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

desde la página de MapsForge concretamente desde su seccióndeDescargas dónde dice "Writer Plugin" dentro de "Release 0.4.0Downloads" (última versión). El fichero descargado lo tenemos que copiar en la carpeta"lib/default" de nuestro Osmosis (la ruta en la que lo hayamosdescomprimido). Después tendremos que crear un fichero dentro dela carpeta "config" de Osmosis con nombre "osmosis­plugins.conf"que contenga la línea:

org.mapsforge.map.writer.osmosis.MapFileWriterPluginLoader

Con esto ya estamos preparados para convertir el mapa, así queejecutamos:

osmosis ‐‐read‐xml coruna.osm ‐‐mapfile‐writer file=coruna.map

–read­xml: Solicita el nombre del fichero a convertir (generadoantes)

–mapfile­writer file: Nombre del fichero destino (respetar extensión".map")

Tras esto, ya tendremos preparado el fichero que contiene losmapas de la zona que mostraremos en el mapa de nuestraaplicación.

2.­ Integrar la librería en nuestro proyecto (Eclipse)

Tras crear nuestro proyecto procederemos primero de todo a integrarla librería en él para poder utilizarla en nuestra aplicación. Para ellocreamos un carpeta llamada "libs" en el proyecto si es que aun noexiste y en él copiamos/importamos los siguientes ficheros quedescargamos de aquí (versión 0.4.3):

mapsforge­core­0.4.3.jarmapsforge­map­0.4.3.jarmapsforge­map­android­0.4.3.jarmapsforge­map­reader­0.4.3.jarsvg­android­0.4.3.jar

Después los seleccionamos todos y pulsando con el botón derechoabrimos el sub menú "Build Path" y presionamos "Add to BuildPath". Ahora ya podemos empezar a desarrollar nuestra app, peroantes de ello vamos a copiar el mapa a su lugar correspondientepara tenerlo disponible en la aplicación.

Page 5: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

3.­ Copiar los datos a la SD del dispositivo

Como dijimos al principio, copiaremos el mapa a mano aldispositivo, para reducir el tamaño del artículo pero lo ideal seríaque la aplicación se encargase de copiarlo si no existe para no tenerproblemas si el usuario lo elimina o algo así.

Así que en la SD del dispositivo que vayas a utilizar la aplicaciónhay que crear una carpeta llamada "maps" y dentro copiamos elfichero "coruna.map" generado en el primer punto.

Vayamos con el código de nuestra aplicación

4.­ Implementar la lógica de la aplicación

Lo primero que necesitamos es un contenedor para nuestro mapa,así que en nuestro "xml" escribimos lo siguiente:

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context="com.example.offlinemapsforgesample.MainActivity"

 

    <org.mapsforge.map.android.view.MapView

        android:id="@+id/mapView"

        android:layout_width="match_parent"

        android:layout_height="match_parent" />

 

</RelativeLayout>

Page 6: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

 

Algo tan sencillo como añadir un "MapView" que es la vista quemostrará el mapa.

La actividad resultante es la siguiente:

 

package com.example.offlinemapsforgesample;

 

import java.io.File;

 

import org.mapsforge.core.model.LatLong;

import org.mapsforge.map.android.graphics.AndroidGraphicFactory

import org.mapsforge.map.android.util.AndroidUtil;

import org.mapsforge.map.android.view.MapView;

import org.mapsforge.map.layer.cache.TileCache;

import org.mapsforge.map.layer.renderer.TileRendererLayer;

import org.mapsforge.map.rendertheme.InternalRenderTheme;

 

import android.graphics.BitmapFactory;

import android.os.Bundle;

import android.os.Environment;

import android.support.v7.app.ActionBarActivity;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.Toast;

 

public class MainActivity extends ActionBarActivity {

 

  private MapView mapView;

  private TileCache tileCache;

  private TileRendererLayer tileRendererLayer;

 

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    AndroidGraphicFactory.createInstance(getApplication

    setContentView(R.layout.activity_main);

 

    mapView = (MapView)findViewById(R.id.mapView

    mapView.setLayerType(View.LAYER_TYPE_SOFTWARE

 

    mapView.setClickable(true);

 

    // create a tile cache of suitable size

Page 7: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

    tileCache = AndroidUtil.createTileCache(this

        mapView.getModel().displayModel

        mapView.getModel().frameBufferModel

 

    mapView.getModel().mapViewPosition.setZoomLevel

    mapView.getMapZoomControls().setZoomLevelMin

    mapView.getMapZoomControls().setZoomLevelMax

 

    String filepath = Environment.getExternalStorageDirectory

    // tile renderer layer using internal render theme

    tileRendererLayer = new TileRendererLayer(tileCache,

        mapView.getModel().mapViewPosition

    tileRendererLayer.setMapFile(new File(filepath

    tileRendererLayer.setXmlRenderTheme(InternalRenderTheme.

 

    // only once a layer is associated with a mapView the rendering starts

    mapView.getLayerManager().getLayers().add(tileRendererLayer

 

    //mapView.setClickable(true);

    mapView.setBuiltInZoomControls(true);

    mapView.getMapScaleBar().setVisible(false);

 

    mapView.getModel().mapViewPosition.setCenter

 

    MyMarker marker = new MyMarker(this, new LatLong

    mapView.getLayerManager().getLayers().add(marker

  }

 

  @Override

  public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.

    getMenuInflater().inflate(R.menu.main, menu)

    return true;

  }

 

  @Override

  public boolean onOptionsItemSelected(MenuItem item) 

    // Handle action bar item clicks here. The action bar will

    // automatically handle clicks on the Home/Up button, so long

    // as you specify a parent activity in AndroidManifest.xml.

    int id = item.getItemId();

    if (id == R.id.action_settings) {

      return true;

    }

    return super.onOptionsItemSelected(item);

  }

}

Page 8: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

En ella podemos contemplar varias cosas importantes:

AndroidGraphicFactory.createInstance(getApplication());

Se encarga de recopilar información de nuestro dispositivonecesaria para mostrar el mapa, tiene que estar antes del"setContentView" y tiene que estar siempre presente, en casocontrario la aplicación se cierra con un error.

Después se inicializa la vista del mapa para poder usarla, como eshabitual en Android y se le asigna el tipo de layer.

Le decimos que el mapa es "pulsable" para poder movernos por él yhacer zoom, sino sería un mapa estático.

mapView.setClickable(true);

Después de esto se crea un "Tile caché" que se encarga de cachearlos "tiles" (porciones de mapa) que se van mostrando para no tenerque andar cargándolas siempre desde cero y se indica el zoom pordefecto y los niveles mínimo y máximo de oom. Luego se crea un"Tile renderer layer" encargado de dibujar los "tiles" al que se leindica el "Tile Caché" que utilizará y la ruta al mapa además del tipode "renderer".

mapView.getLayerManager().getLayers().add(tileRendererLayer

Esto añade la "capa" creada al mapa y por último se le indica quemuestre los controles de zoom predefinidos y que oculte la barra deescala que mostraría la distancia de una proporción de mapa deforma visual, para al final centrar el mapa en una posición concreta.

Para que esto funcione tenemos que añadir a nuestro ficheroManifest el permiso:

<uses­permission

android:name="android.permission.WRITE_EXTERNAL_STORAGE"

/>

Page 9: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

Ya que en la tarjeta SD se almacena el caché del mapa, y esnecesario poder escribir en ella.

Con esto ya tenemos nuestra aplicación funcionando y el mapaperfectamente usable.

Por último veremos como implementar el click en un "Marker" paraque se puedan abrir nuevas ventanas o mostrar información relativaa un punto concreto tras pulsar en él.

EXTRA.­ Ejecutar tarea al hacer click en un Marker

Algo que no sabía como hacer con esta librería y que me parecevital es cómo ejecutar algo al hacer click en un Marker para mostrarla información de ese punto o abrir una ventana nueva, por lo quevamos a ver cómo hacerlo.

Para implementar el click, tenemos que heredar el objeto "Marker"de MapsForge y realizar nuestra tarea dentro del método "onTap",así que para ello creamos una nueva clase dentro del proyecto(llamada "MyMarker" en el ejemplo) que contenga lo siguiente:

 

package com.example.offlinemapsforgesample;

 

import org.mapsforge.core.graphics.Bitmap;

import org.mapsforge.core.model.LatLong;

import org.mapsforge.core.model.Point;

import org.mapsforge.map.layer.overlay.Marker;

 

import android.content.Context;

import android.widget.Toast;

 

public class MyMarker extends Marker{

  private Context ctx;

 

Page 10: Mapas Offline en Android Con OpenStreetMap y La Librería MapsForge _ Tecno Game

  public MyMarker(Context ctx, LatLong latLong, Bitmap bitmap, 

      int verticalOffset) {

    super(latLong, bitmap, horizontalOffset, verticalOffset

    this.ctx = ctx;

  }

 

  @Override

  public boolean onTap(LatLong tapLatLong, Point layerXY, 

    if (this.contains(layerXY, tapXY)) {

      Toast.makeText(ctx, "Marker con latitud: "

    return true;

  }

    return super.onTap(tapLatLong, layerXY, tapXY

  }

 

}

 

Y en la actividad principal añadimos estas dos líneas:

 

MyMarker marker = new MyMarker(this, new LatLong(43.385833, 

mapView.getLayerManager().getLayers().add(marker);

 

Que se encargan de crear el Marker personalizado y añadirlo almapa.

Y eso es todo por hoy, espero que con esta mini guía os sea másfácil integrar las funcionalidades de MapsForge en vuestraaplicación para poder mostrar mapas sin necesidad de conexión ainternet.

Recursos:

Mapa: coruna.mapProyecto para Eclipse: OfflineMapsforgeSample.zip

Este es el resultado final: