Mapbox: el SDK de mapas abierto

Mapbox: el SDK de mapas abierto
Sin comentarios Facebook Twitter Flipboard E-mail

A la hora de integrar mapas en una aplicación móvil tenemos varias alternativas a nuestro alcance. Actualmente, las opciones más usadas, sobretodo en el desarrollo móvil, son la API de Google Maps, el SDK de Mapbox y el framework MapKit de Apple. Así que, si estás pensando en incluir mapas en tu aplicación, conviene hacer la mejor elección desde un principio.

Tras trabajar con todas estas opciones durante un tiempo, sin duda, considero que la mejor alternativa es tirar por la solución que nos ofrece Mapbox, por su simplicidad y flexibilidad. En este artículo vamos a explicar por qué Mapbox, además de ver cómo implementar algunas de las funcionalidades más potentes analizando un par de sencillos ejemplos.

¿Qué tiene Mapbox que no tienen los demás?

  • Todo es 100% personalizable. Desde cualquier color hasta mostrar/ocultar capas en el mapa. Hay una serie de estilos disponibles por defecto (Dark, Light, etc.) pero también tienes la posibilidad de diseñar/crear tus propios estilos por completo a través de la herramienta Mapbox Studio. Recientemente se lanzó Cartogram, que te genera un estilo automáticamente a partir de una imagen. Los estilos se integran en las aplicaciones añadiendo una sola línea de código. Como puedes imaginar, todo ello te permite generar mapas acordes con el branding de tu app y así ofrecer una mejor experiencia a tus usuarios.

  • Open source. Todo el código está abierto y basado en estándares abiertos. Mapbox dispone de más de 500 repositorios en Github. Esto te permite ver las funcionalidades que están en desarrollo, reportar cualquier tipo de problema que puedas tener o incluso contribuir mandando PRs. Mapbox es una plataforma hecha por desarrolladores para desarrolladores.

  • No importa para qué plataforma desarrolles porque hay SDKs disponibles para prácticamente todas. Entre las cuales están Android, iOS, Web, Qt, Unity y MacOS. Además, todas las funcionalidades están accesibles desde cada uno de ellos, ya que comparten una misma base.

  • In-app. Todo ocurre en tu app. No hay necesidad de tener que saltar a otra aplicación para nada (Mapbox no tiene apps para usuarios así que no tiene interés en competir con sus desarrolladores). Esto es especialmente útil si estás desarrollando una app de navegación, ya que, a diferencia de otros SDKs, puedes proveer una experiencia de navegación completa, sin perder a tus usuarios en ningún momento. Otro ejemplo es la posibilidad de guardar mapas offline sin salir de tu app.

  • El core está basado en mapas vectoriales implementados en C++, de forma que únicamente se mandan los datos necesarios al dispositivo y se interpretan en tiempo real, lo que se traduce en mapas muy rápidos y en visualizaciones mucho más ligeras.

  • Tanto el SDK de Android como el de iOS tienen una API similar a la de Google Maps y MapKit respectivamente. Por lo que todo el conocimiento que ya tuvieras te seguirá siendo útil y además migrar a Mapbox no te costará nada. Para hacer el cambio basta con hacer un Reemplazar todos a través del IDE y listo.

Talk is cheap. Show me the code

Para empezar a usar los servicios de Mapbox en tus aplicaciones tan sólo necesitas el típico token de acceso, que se consigue fácilmente tras darse de alta (usar Mapbox es gratis para tus primeros 50,000 usuarios activos). Hay guías rápidas de instalación, tanto para Android como para iOS. Tras completar la guía de la plataforma para la que estés desarrollando, ya estarás listo para empezar a programar.

A continuación, mostraremos cómo trabajar con dos de las funcionalidades más potentes del SDK, Data Driven Styling, Offline y 3D Extrusions. Los ejemplos están escritos en Java para Android. Aún así, como ya se ha mencionado antes, se pueden implementar en cualquiera de las otras plataformas disponibles (y Kotlin, claro).

En primer lugar, tenemos que configurar el token de acceso:


@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  // Mapbox access token is configured here. This needs to be called either in your application object or in the same activity which contains the mapview.
  // Line must go before the layout XML files loaded
  Mapbox.getInstance(this, getString(R.string.access_token));

  setContentView(R.layout.activity_style_zoom_dependent_fill_color);
  // ...
}


A continuación, ya podemos incluir un mapa de la siguiente forma:


private MapView mapView;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  Mapbox.getInstance(this, getString(R.string.access_token));
  // This contains the MapView in XML and needs to be called after the access token is configured.
  setContentView(R.layout.activity_style_zoom_dependent_fill_color);  
  
  mapView = (MapView) findViewById(R.id.mapView);
  mapView.onCreate(savedInstanceState);
  // ...
}

// Add required Lifecycle methods

activity_style_zoom_dependent_fill_color.xml:


Para garantizar un correcto manejo entre el ciclo de vida de OpenGL y el de Android, MapView define su propio ciclo de vida. Es por ello, que tenemos que sobreescribir los métodos del ciclo de vida de la Activity de la siguiente forma:


@Override
protected void onStart() {
  super.onStart();
  mapView.onStart();
}

Los métodos que tenemos que sobre escribir para que todo funcione correctamente son los siguientes (Mapbox provee implementación para todos ellos):



onCreate();
onStart();
onResume();
onPause();
onStop();
onSaveInstanceState();
onLowMemory();
onDestroy();


Por último, una vez declarado y asignado el MapView, hay que llamar a MapView#getMapAsync para crear un objeto MapboxMap, necesario para interactuar con el mapa (como ves, muy parecido a Google Maps API en Android):



@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  Mapbox.getInstance(this, getString(R.string.access_token));
  setContentView(R.layout.activity_style_zoom_dependent_fill_color);  
  
  mapView = (MapView) findViewById(R.id.mapView);
  mapView.onCreate(savedInstanceState);
 
  mapView.getMapAsync(new OnMapReadyCallback() {
  @Override
  public void onMapReady(MapboxMap mapboxMap) {
      // Interact with the map using mapboxMap here
      // Customize map with markers, polylines, etc.
  }
});

Data Driven Styling

  • Cambiar el color del agua en función del zoom:


mapView.getMapAsync(new OnMapReadyCallback() {
      @Override
      public void onMapReady(final MapboxMap mapboxMap) {
        FillLayer layer = mapboxMap.getLayerAs("water");
        if (layer == null) {
          return;
        }

        // Set a zoom function to update the color of the water
        layer.setProperties(fillColor(Function.zoom(exponential(
                Stop.stop(1f, fillColor(Color.GREEN)),
                Stop.stop(8.5f, fillColor(Color.BLUE)),
                Stop.stop(10f, fillColor(Color.RED)),
                Stop.stop(18f, fillColor(Color.YELLOW))
        ))));

        mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40.73581, -73.99155), 12), 12000);
      }
});


Offline

  • Descargar un mapa offline:

mapView.getMapAsync(new OnMapReadyCallback() {
      @Override
      public void onMapReady(final MapboxMap mapboxMap) {
        String minZoom = map.getStyleUrl();
        double minZoom = map.getCameraPosition().zoom;
        double maxZoom = map.getMaxZoom();
        float pixelRatio = this.getResources().getDisplayMetrics().density;
        
        OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(styleURL, bounds, minZoom, maxZoom, pixelRatio);
        
        byte[] metadata = name.getBytes(CHARSET);
        
        offlineManager.createOfflineRegion(definition, metadata, new OfflineManager.CreateOfflineRegionCallback() {
          @Override
          public void onCreate(OfflineRegion offlineRegion) {
            offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);
          }

          @Override
          public void onError(String error) {
          }
        });
      }
});

3D Extrusions (Building plugin)

  • Usando mapbox-android-plugin-building, mostrar edificios en 3D es tan sencillo como:

mapView.getMapAsync(new OnMapReadyCallback() {
      @Override
      public void onMapReady(@NonNull final MapboxMap map) {
        BuildingPlugin buildingPlugin = new BuildingPlugin(mapView, mapboxMap);
        buildingPlugin.setVisibility(true);
      }
});

Conclusión

Como has podido ver, Mapbox trae muchas funcionalidades que no nos ofrecen otros frameworks. Y esto tan solo es una pequeña muestra de lo que podemos hacer, ya que aparte del SDK de mapas, tenemos disponibles el Mapbox Services SDK (APIs de Geocoding, Map Matching, Directions, etc.), el Navigation SDK o los Mapbox Plugins.

Y tú, ¿conocías Mapbox? ¿Cúales son tus casos de uso al trabajar con mapas? Te animo a que le eches un vistazo a la última versión (Android/iOS) y nos digas qué te parece. En próximos artículos, hablaremos de cómo implementar otras funcionalides y trabajar con el resto de SDKs. Mientras tanto, si tienes cualquier duda, la sección de comentarios es tuya.

Documentación Mapbox Android SDK, Mapbox iOS SDK, Github

Comentarios cerrados
Inicio