Google Maps Android Utility Library

repository·main·Indexed 25 days ago

https://github.com/googlemaps/android-maps-utils

An open-source utility library for the Google Maps SDK for Android. It provides advanced features including marker clustering (with NonHierarchicalViewBasedAlgorithm for large sets), heatmaps, spherical geometry calculations, and a data module for parsing and rendering geospatial formats such as KML, KMZ, GeoJSON, and GPX using MapViewRenderer.

Tokens
6.6K
Snippets
12
Records
50
Agent score
86%

What's inside android-maps-utils

  1. Overview of the Data Module architecture

    main

    The data module uses a Clean Architecture approach to separate parsing, modeling, and rendering:

    1. Parsers (com.google.maps.android.data.parser): Converts raw files (KML, GeoJSON, GPX) into intermediate objects using KmlParser, GeoJsonParser, or GpxParser.
    2. Mappers (com.google.maps.android.data.renderer.mapper): Transforms parsed objects into a unified internal model using KmlMapper, GeoJsonMapper, or GpxMapper.
    3. Internal Model (com.google.maps.android.data.renderer.model): A platform-agnostic representation consisting of:
      • DataScene: Top-level container.
      • DataLayer: A collection of features.
      • Feature: Contains Geometry, Style, and Properties.
      • Geometry: Supports Point, LineString, Polygon, MultiGeometry, and GroundOverlay.
      • Style: Supports PointStyle, LineStyle, PolygonStyle, and GroundOverlayStyle.
    4. Renderer (com.google.maps.android.data.renderer.mapview): Uses MapViewRenderer to draw the model onto a GoogleMap.
  2. Use the Renderer to draw data on Google Maps

    main

    To display complex data (like KML or GeoJSON) on a GoogleMap, follow this workflow:

    1. Initialize the Renderer: Create a Renderer instance and associate it with your GoogleMap object.
    2. Parse Data: Use a DataParser (e.g., KmlParser or GeoJsonParser) to parse your data source (such as an InputStream) into a structured in-memory representation.
    3. Map to Layers: Pass the parsed data to a Mapper (e.g., KmlMapper or GeoJsonMapper). This converts the format-specific data into a Layer containing generic MapObjects.
    4. Add to Renderer: Add the resulting Layer to the Renderer using addLayer(layer).

    The Renderer will then automatically handle drawing the MapObjects (such as MarkerObject, PolylineObject, PolygonObject, or CircleObject) onto the map.

  3. Implement Marker Clustering

    main

    Use ClusterManager to manage multiple markers at different zoom levels.

    1. Create a class that implements ClusterItem.
    2. Initialize a ClusterManager within the onMapReady callback.
    3. Link the map's listeners to the manager: map.setOnCameraIdleListener(clusterManager) and map.setOnMarkerClickListener(clusterManager).
    4. Add items to the cluster using clusterManager.addItem(item).
  4. Decode Polylines and calculate Spherical distance

    main

    Use PolyUtil and SphericalUtil for coordinate manipulation and geometry calculations.

    • Decoding: Use PolyUtil.decode(encodedPathString) to convert an encoded string into a list of LatLng points.
    • Distance: Use SphericalUtil.computeDistanceBetween(latLng1, latLng2) to calculate the distance between two points.
  5. Import GeoJSON and KML data

    main

    Import geographic data from raw resource files using GeoJsonLayer or KmlLayer.

    • GeoJSON: val layer = GeoJsonLayer(map, R.raw.geojson_file, context); layer.addLayerToMap()
    • KML: val layer = KmlLayer(map, R.raw.kml_file, context); layer.addLayerToMap()
    // GeoJSON
    val layer = GeoJsonLayer(map, R.raw.geojson_file, context)
    layer.addLayerToMap()
    
    // KML
    val layer = KmlLayer(map, R.raw.kml_file, context)
    layer.addLayerToMap()
  6. Migrate ClusterItem implementation to v5.x

    main

    In v5.x, the ClusterItem interface is written in idiomatic Kotlin. When creating custom cluster item classes (like data classes), you should now use the override keyword directly in the constructor for the properties position, title, snippet, and zIndex. This replaces the need for manual getter method overrides used in v4.x.

    // After (v5.x Idiomatic Kotlin)
    data class MyItem(
        override val position: LatLng,
        override val title: String?,
        override val snippet: String?,
        override val zIndex: Float?
    ) : ClusterItem
  7. Parse and map geospatial data (KML, GeoJSON, GPX)

    main

    The data module provides parsers to convert raw file formats into intermediate objects, which can then be mapped into a unified DataLayer using specific mappers. This allows you to treat different geospatial formats identically once they are in the internal model.

    // Load KML
    val kml = KmlParser().parse(inputStream)
    val kmlLayer = KmlMapper.toLayer(kml)
    
    // Load GeoJSON
    val geoJson = GeoJsonParser().parse(inputStream)
    val geoJsonLayer = GeoJsonMapper.toLayer(geoJson)
    
    // Load GPX
    val gpx = GpxParser().parse(inputStream)
    val gpxLayer = GpxMapper.toLayer(gpx)
  8. Install the Maps SDK for Android Utility Library

    main

    You can install the entire library using the aggregator artifact, or include only the specific submodules your application requires to reduce binary size.

    Requirements:

    • Android API level 23+
    • A Google Maps Platform project with the Maps SDK for Android enabled.
    • An API key associated with that project.
    // Install all utilities via the aggregator artifact
    dependencies {
        implementation("com.google.maps.android:android-maps-utils:5.0.0")
    }
    
    // OR install only specific submodules
    dependencies {
        // Base utilities: PolyUtil, SphericalUtil, collection managers, Street View metadata
        implementation("com.google.maps.android:android-maps-utils-core:5.0.0")
        // Marker clustering
        implementation("com.google.maps.android:android-maps-utils-clustering:5.0.0")
        // KML and GeoJSON import
        implementation("com.google.maps.android:android-maps-utils-data:5.0.0")
        // Heatmaps
        implementation("com.google.maps.android:android-maps-utils-heatmaps:5.0.0")
        // Marker icons and animation
        implementation("com.google.maps.android:android-maps-utils-ui:5.0.0")
    }
  9. Render geospatial layers using MapViewRenderer

    main

    Use MapViewRenderer to render a DataLayer onto a GoogleMap. The renderer handles the lifecycle of adding and removing map elements like Markers, Polylines, Polygons, and GroundOverlays. You can provide an IconProvider (such as UrlIconProvider) to handle asynchronous icon loading via Coroutines.

    // Initialize Renderer
    val renderer = MapViewRenderer(googleMap, UrlIconProvider(lifecycleScope))
    
    // Add Layer
    renderer.addLayer(kmlLayer)
    
    // Remove Layer
    renderer.removeLayer(kmlLayer)
    
    // Enable Advanced Markers
    renderer.useAdvancedMarkers = true
  10. Import Google Maps Android Utility Library v5.x

    main

    Starting with v5.x, the library uses a multi-module architecture. You can either import the aggregator artifact to get all utilities or import specific submodules to reduce build size.

    Available Submodules:

    • android-maps-utils-core (:library): Base utilities like PolyUtil, SphericalUtil, MathUtil, and managers (MarkerManager, PolygonManager, etc.).
    • android-maps-utils-data (:data): KML and GeoJSON parsing/rendering.
    • android-maps-utils-clustering (:clustering): Marker clustering.
    • android-maps-utils-heatmaps (:heatmaps): Heatmap overlay tile providers.
    • android-maps-utils-ui (:ui): Custom markers and UI components.

    To import all utilities using a Version Catalog (libs.versions.toml), use the following configuration:

    [versions]
    androidMapsUtils = "5.0.0"
    
    [libraries]
    android-maps-utils = { group = "com.google.maps.android", name = "android-maps-utils", version.ref = "androidMapsUtils" }