Maps SDK for Android Utility Library

Overview

Build Status Maven Central GitHub contributors Discord Apache-2.0

Maps SDK for Android Utility Library

Description

This open-source library contains utilities that are useful for a wide range of applications using the Google Maps Android API.

  • Marker clustering — handles the display of a large number of points
  • Heat maps — display a large number of points as a heat map
  • IconGenerator — display text on your Markers
  • Poly decoding and encoding — compact encoding for paths, interoperability with Maps API web services
  • Spherical geometry — for example: computeDistance, computeHeading, computeArea
  • KML — displays KML data
  • GeoJSON — displays and styles GeoJSON data

You can also find Kotlin extensions for this library here.

Developer Documentation

You can view the generated reference docs for a full list of classes and their methods.

Requirements

  • Android API level 15+
  • Maps SDK via Google Play Services OR Maps SDK v3 BETA library

Installation

dependencies {
    // Utilities for Maps SDK for Android (requires Google Play Services) 
    implementation 'com.google.maps.android:android-maps-utils:2.2.2'

    // Alternately - Utilities for Maps SDK v3 BETA for Android (does not require Google Play Services)
    implementation 'com.google.maps.android:android-maps-utils-v3:2.2.2'
}

Demo App

This repository includes a demo app that illustrates the use of this library.

The version that depends on the Maps SDK for Android can be found under the gms Gradle product flavor, while version that depends on the Maps SDK V3 BETA can be found under the v3 Gradle product flavor. The active product flavor can be modified through Android Studio’s “Build Variants” toolbar options.

To run the demo app, you'll have to:

  1. Get a Maps API key
  2. Create a file in the demo directory called secure.properties (this file should NOT be under version control to protect your API key)
  3. Add a single line to demo/secure.properties that looks like MAPS_API_KEY=YOUR_API_KEY, where YOUR_API_KEY is the API key you obtained in the first step
  4. Build and run the gmsDebug variant for the Maps SDK for Android version, or v3Debug for the Maps SDK v3 BETA version

Migration Guide

Improvements made in version 1.0.0 of the library to support multiple layers on the map caused breaking changes to versions prior to it. These changes also modify behaviors that are documented in the Maps SDK for Android Maps documentation site. This section outlines all those changes and how you can migrate to use this library since version 1.0.0.

Adding Click Events

Click events originate in the layer-specific object that added the marker/ground overlay/polyline/polygon. In each layer, the click handlers are passed to the marker, ground overlay, polyline, or polygon Collection object.

// Clustering
ClusterManager<ClusterItem> clusterManager = // Initialize ClusterManager - if you're using multiple maps features, use the constructor that passes in Manager objects (see next section)
clusterManager.setOnClusterItemClickListener(item -> {
    // Listen for clicks on a cluster item here
    return false;
});
clusterManager.setOnClusterClickListener(item -> {
    // Listen for clicks on a cluster here
    return false;
});

// GeoJson
GeoJsonLayer geoJsonLayer = // Initialize GeoJsonLayer - if you're using multiple maps features, use the constructor that passes in Manager objects (see next section)
geoJsonLayer.setOnFeatureClickListener(feature -> {
    // Listen for clicks on GeoJson features here
});

// KML
KmlLayer kmlLayer = // Initialize KmlLayer - if you're using multiple maps features, use the constructor that passes in Manager objects (see next section)
kmlLayer.setOnFeatureClickListener(feature -> {
    // Listen for clicks on KML features here
});

Using Manager Objects

If you use one of Manager objects in the package com.google.maps.android (e.g. GroundOverlayManager, MarkerManager, etc.), say from adding a KML layer, GeoJson layer, or Clustering, you will have to rely on the Collection specific to add an object to the map rather than adding that object directly to GoogleMap. This is because each Manager sets itself as a click listener so that it can manage click events coming from multiple layers.

For example, if you have additional GroundOverlay objects:

New

GroundOverlayManager groundOverlayManager = // Initialize 

// Create a new collection first
GroundOverlayManager.Collection groundOverlayCollection = groundOverlayManager.newCollection();

// Add a new ground overlay
GroundOverlayOptions options = // ...
groundOverlayCollection.addGroundOverlay(options);

Old

GroundOverlayOptions options = // ...
googleMap.addGroundOverlay(options);

This same pattern applies for Marker, Circle, Polyline, and Polygon.

Adding a Custom Info Window

If you use MarkerManager, adding an InfoWindowAdapter and/or an OnInfoWindowClickListener should be done on the MarkerManager.Collection object.

New

CustomInfoWindowAdapter adapter = // ...
OnInfoWindowClickListener listener = // ...

// Create a new Collection from a MarkerManager
MarkerManager markerManager = // ...
MarkerManager.Collection collection = markerManager.newCollection();

// Set InfoWindowAdapter and OnInfoWindowClickListener
collection.setInfoWindowAdapter(adapter);
collection.setOnInfoWindowClickListener(listener);

// Alternatively, if you are using clustering
ClusterManager<ClusterItem> clusterManager = // ...
MarkerManager.Collection markerCollection = clusterManager.getMarkerCollection();
markerCollection.setInfoWindowAdapter(adapter);
markerCollection.setOnInfoWindowClickListener(listener);

Old

CustomInfoWindowAdapter adapter = // ...
OnInfoWindowClickListener listener = // ...
googleMap.setInfoWindowAdapter(adapter);
googleMap.setOnInfoWindowClickListener(listener);

Adding a Marker Drag Listener

If you use MarkerManager, adding an OnMarkerDragListener should be done on the MarkerManager.Collection object.

New

// Create a new Collection from a MarkerManager
MarkerManager markerManager = // ...
MarkerManager.Collection collection = markerManager.newCollection();

// Add markers to collection
MarkerOptions markerOptions = // ...
collection.addMarker(markerOptions);
// ...

// Set OnMarkerDragListener
GoogleMap.OnMarkerDragListener listener = // ...
collection.setOnMarkerDragListener(listener);

// Alternatively, if you are using clustering
ClusterManager<ClusterItem> clusterManager = // ...
MarkerManager.Collection markerCollection = clusterManager.getMarkerCollection();
markerCollection.setOnMarkerDragListener(listener);

Old

// Add markers
MarkerOptions markerOptions = // ...
googleMap.addMarker(makerOptions);

// Add listener
GoogleMap.OnMarkerDragListener listener = // ...
googleMap.setOnMarkerDragListener(listener);

Clustering

A bug was fixed in v1 to properly clear and re-add markers via the ClusterManager.

For example, this didn't work pre-v1, but works for v1 and later:

clusterManager.clearItems();
clusterManager.addItems(items);
clusterManager.cluster();

If you're using custom clustering (i.e, if you're extending DefaultClusterRenderer), you must override two additional methods in v1:

  • onClusterItemUpdated() - should be the same* as your onBeforeClusterItemRendered() method
  • onClusterUpdated() - should be the same* as your onBeforeClusterRendered() method

*Note that these methods can't be identical, as you need to use a Marker instead of MarkerOptions

See the CustomMarkerClusteringDemoActivity in the demo app for a complete example.

New

    private class PersonRenderer extends DefaultClusterRenderer<Person> {
        ...     
        @Override
        protected void onBeforeClusterItemRendered(Person person, MarkerOptions markerOptions) {
            // Draw a single person - show their profile photo and set the info window to show their name
            markerOptions
                    .icon(getItemIcon(person))
                    .title(person.name);
        }
        
        /**
         * New in v1 
         */
        @Override
        protected void onClusterItemUpdated(Person person, Marker marker) {
            // Same implementation as onBeforeClusterItemRendered() (to update cached markers)
            marker.setIcon(getItemIcon(person));
            marker.setTitle(person.name);
        }
        
        @Override
        protected void onBeforeClusterRendered(Cluster<Person> cluster, MarkerOptions markerOptions) {
            // Draw multiple people.
            // Note: this method runs on the UI thread. Don't spend too much time in here (like in this example).
            markerOptions.icon(getClusterIcon(cluster));
        }
       
        /**
         * New in v1 
         */
        @Override
        protected void onClusterUpdated(Cluster<Person> cluster, Marker marker) {
            // Same implementation as onBeforeClusterRendered() (to update cached markers)
            marker.setIcon(getClusterIcon(cluster));
        }
        ...
    }

Old

    private class PersonRenderer extends DefaultClusterRenderer<Person> {
        ...       
        @Override
        protected void onBeforeClusterItemRendered(Person person, MarkerOptions markerOptions) {
            // Draw a single person - show their profile photo and set the info window to show their name
            markerOptions
                    .icon(getItemIcon(person))
                    .title(person.name);
        }
        
        @Override
        protected void onBeforeClusterRendered(Cluster<Person> cluster, MarkerOptions markerOptions) {
            // Draw multiple people.
            // Note: this method runs on the UI thread. Don't spend too much time in here (like in this example).
            markerOptions.icon(getClusterIcon(cluster));
        }
        ...
    }

Support

Encounter an issue while using this library?

If you find a bug or have a feature request, please file an issue. Or, if you'd like to contribute, send us a pull request and refer to our code of conduct.

You can also reach us on our Discord channel.

For more information, check out the detailed guide on the Google Developers site.

Comments
  • Map dragging is slow when using more than 15 000 markers in a high zoom level

    Map dragging is slow when using more than 15 000 markers in a high zoom level

    Hey, I have (sometimes) much more than 15 000 markers. When i drag the map in a high zoom level e.g. above an area that has only like 200 (clustered) markers it is very slow although I have a Galaxy S3. Someone knows how to make dragging fast in high zoom levels?

    stale 
    opened by JonasDaWi 42
  •  java.util.ConcurrentModificationException

    java.util.ConcurrentModificationException

    I am intermittently getting this error. Here's my scenario: 1.) Not that it matters, - my marker locations are trickling in (coming from a network call) 2.) Every 15 markers that arrive, I "encourage" to do cluster by calling

    mClusterManager.cluster()
    

    3.) I have overrode the method shouldRenderAsCluster such that for certain situations, it returns false. Anyway, to over-exagerrate the scenario, let's say I'll always return false. When I zoom-in/out very fast, this error happens , particularly when I am zoomed out... By aggressively hitting the "-" zoom button, and then purposely miss it (hit any area of the map).

    java.util.ConcurrentModificationException
            at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
            at java.util.HashMap$KeyIterator.next(HashMap.java:833)
            at java.util.AbstractSet.removeAll(AbstractSet.java:110)
            at com.google.maps.android.clustering.view.DefaultClusterRenderer$RenderTask.run(DefaultClusterRenderer.java:362)
            at java.lang.Thread.run(Thread.java:841)
    
    opened by ericpanorel 35
  • White squares - issue with latest Play Services 9.0.83

    White squares - issue with latest Play Services 9.0.83

    Hello, today has started appearing this issue (after few of zoom in/out most of group icons are replaced by white squares): gmaps_white_squares_issue

    We had no problems before but latest Play services has broken something (9.0.83, updated 11. may). We have test our application with Play Services 8.7.03 and there is absolutely no problem. Our application uses Play services SDK 8.4.0.

    opened by yuraj11 32
  • Render only visible items on the map

    Render only visible items on the map

    Implemented rendering only visible items on the map(issue #82 ) Added VisibleClusteringDemoActivity activity which demonstrates clustering of 20k items.

    Review on Reviewable

    opened by zamesilyasa 29
  • App freezes when loading KML layer

    App freezes when loading KML layer

    I am trying to add KML layer on to the maps. It was working okay with just a ms of freeze when i try to load the small size KML file. But some files are large with size more than 1Mb - 10Mb.. in these all cases app is getting frozen for some time while the layer is adding to the map.

    Below is the Asynctask class i am using to read the kml file from local storage path and adding it to maps.

    I tried this in many ways using handlers, threads, asynctasks... as i cannot update the UI in background thread... this is causing my app to freeze for some time.

    Eventhough it freezes I wouldn't mind but in some device while the app is frozen if the user interacts with the app then app is getting crashed. In some devices it is displaying "wait" dialog.

    Please help me out.

    ` private static class AddKMLLayerToMaps extends AsyncTask<String, String, KmlLayer> {

        //added weakreference to avoid memory leaks
        private WeakReference<CoverageFragment> weakReferencedFragment;
    
        AddKMLLayerToMaps(CoverageFragment reference) {
    
            this.weakReferencedFragment = new WeakReference<>(reference);
    
            weakReferencedFragment.get().showLoading();
        }
    
        @Override
        protected KmlLayer doInBackground(String... strings) {
    
            try {
    
                TraceUtils.logE("Coverage kml Path", strings[0]);
    
                FileInputStream fileInputStream = new FileInputStream(strings[0]);
    
                CoverageFragment fragment = weakReferencedFragment.get();
                if (fragment == null || fragment.getActivity() == null || fragment.getActivity().isFinishing()) {
                    return null;
                }
    
                KmlLayer kmlLayer = new KmlLayer(fragment.mMap, fileInputStream, getApplicationContext());
    
                fileInputStream.close();
    
                File file = new File(strings[0]);
                if (file.exists()) file.delete();
    
                return kmlLayer;
    
            } catch (Exception e) {
    
                weakReferencedFragment.get().hideLoading();
    
                TraceUtils.logException(e);
    
            }
    
            return null;
        }
    
        @Override
        protected void onPostExecute(KmlLayer kmlLayer) {
    
            super.onPostExecute(kmlLayer);
    
            if (kmlLayer != null) {
    
                //add the KML layer to map using the UI thread
                weakReferencedFragment.get().mActivity.runOnUiThread(() -> {
                    try {
    
                        kmlLayer.addLayerToMap();
    
                    } catch (Exception e) {
    
                        weakReferencedFragment.get().hideLoading();
    
                        TraceUtils.logException(e);
    
                    }
                });
    
                //zoom to the center of KML layer containers
                new MoveMapToKMLLayer(weakReferencedFragment.get()).execute(kmlLayer);
            }
        }
    
    }`
    
    status: blocked stale 
    opened by sharkboy777 27
  • Fatal Exception: android.content.res.Resources$NotFoundException: Resource ID

    Fatal Exception: android.content.res.Resources$NotFoundException: Resource ID

    Summary:

    The map randomly crashes while setting up the cluster manager and rendering the clusters.

    Steps to reproduce: This is happening intermittently so it is hard to reproduce. See logs for more details.

    Crashlytics Logs

    Fatal Exception: android.content.res.Resources$NotFoundException: Resource ID #0x7f08005e at android.content.res.ResourcesImpl.getValueForDensity + 240(ResourcesImpl.java:240) at android.content.res.Resources.getDrawableForDensity + 885(Resources.java:885) at android.content.res.Resources.getDrawable + 828(Resources.java:828) at android.content.res.Resources.getDrawable + 803(Resources.java:803) at com.google.maps.android.ui.BubbleDrawable.(BubbleDrawable.java:3) at com.google.maps.android.ui.IconGenerator.(IconGenerator.java:3) at com.google.maps.android.clustering.view.DefaultClusterRenderer.(DefaultClusterRenderer.java:12) at com.google.maps.android.clustering.ClusterManager.(ClusterManager.java:9) at com.google.maps.android.clustering.ClusterManager.(ClusterManager.java:9) at com.ojoelectric.ojo.ui.map.ScooterMapFragment.onMapReady + 179(ScooterMapFragment.java:179) at com.google.android.gms.maps.zzak.zza(zzak.java:1) at com.google.android.gms.maps.internal.zzaq.dispatchTransaction(zzaq.java:1) at com.google.android.gms.internal.maps.zzb.onTransact + 22(zzb.java:22) at android.os.Binder.transact + 656(Binder.java:656) at hq.b + 14(hq.java:14) at com.google.android.gms.maps.internal.be.a + 4(be.java:4) at com.google.maps.api.android.lib6.impl.bj.run + 4(bj.java:4) at android.os.Handler.handleCallback + 790(Handler.java:790) at android.os.Handler.dispatchMessage + 99(Handler.java:99) at android.os.Looper.loop + 175(Looper.java:175) at android.app.ActivityThread.main + 6724(ActivityThread.java:6724) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run + 438(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main + 810(ZygoteInit.java:810)

    Device and Android version:

    • LG Premiere Pro and LG Stylo 4 (8.1.0)

    • Galaxy J7 Crown (8.0) and Galaxy S8+ (7.1.2) and Galaxy Tab E 8.0 (7.1.1)

    • ZTE ZFive C LTE (7.1.1) and Z999 (7.1.2)

    • OnePlus 5T and OnePlus 6 (9.0)

    • Pixel XL (9.0)

    • AlcatelOneTouch (7.0)

    • XiaoMi 5 (8.0)

    • Coolpad Legacy (9.0)

    I am using the following google map dependencies:

    ext.googlePlayServicesVersion = "16.0.0"
    
    implementation "com.google.android.gms:play-services-location:$googlePlayServicesVersion"
    implementation "com.google.android.gms:play-services-maps:$googlePlayServicesVersion"
    kapt "com.google.android.gms:play-services-maps:$googlePlayServicesVersion"
    implementation 'com.google.maps.android:android-maps-utils:0.5'
    
    type: bug priority: p1 released released on @chris/fix/858 
    opened by Greeeeyyyss 24
  • Custom Info Window stopped working in this new version. README does not explain anything

    Custom Info Window stopped working in this new version. README does not explain anything

    Before I start, I would like to say that I went through the other issues regarding this and how there is a new README with mitigation process.

    But the new README only explains if you use Marker Manager.

    How about the if you don't use marker manager at all?

    this is how I add markers (I am using Glide)

    mUserMarker = mMap.addMarker(new MarkerOptions()
            .icon(BitmapDescriptorFactory.fromBitmap(bitmap))
             .position(loc)
             .title(getResources().getString(R.string.not_online))
    

    and my custom info window

    mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
                    @Override
                    public View getInfoWindow(Marker marker) {
                        View myView;
                        myView = LayoutInflater.from(getActivity())
                                .inflate(R.layout.custom_user_info_window2,null, false);
                        return myView;
                    }
                    @Override
                    public View getInfoContents(Marker marker) {
                        return null;
                    }
                });
    

    How to fix this in the new version where it stopped working.

    Please help, thanks in advance

    type: question triage me released 
    opened by Testator 19
  • Updating items clusterItems : Clear items and re-adding doesn't always work

    Updating items clusterItems : Clear items and re-adding doesn't always work

    I am having an issue with this library. Whenever I clear the items from the cluster manager and add a new set, some single pins are not redrawn. Here's what I am doing:

    private void displayMarkers(List markersToShowOnMap) { gMap.clear(); clusterManager.clearItems(); clusterManager.cluster(); //if I disable this it doesn't work either mClusterManager.addItems(markersToShowOnMap); mClusterManager.cluster(); }

    If I call this method with the same set of markers, while zoomed in such that some clusters are displayed and some single markers are displayed, the single markers disappear! I am using the DefaultClusterRenderer. I have logged the renderer and onBeforeClusterItemRendered is not being called a second time after clearing and re-adding items. If i zoom out and back in, the missing markers re-appear.

    needs more info type: bug 
    opened by juamor86 19
  • Feature request: simple polygon test (geodesic)

    Feature request: simple polygon test (geodesic)

    Summary:

    I need to determine whether a user-defined geodesic polygon is a simple (non-intersecting) polygon. Only simple polygons are usable by my app. Non-simple polygons would cause problems. My app lets users draw polygons to define areas on top of Google Maps.

    Expected behavior:

    Add a utility method such as:

    boolean isSimplePolygon(java.util.List<LatLng> polygon, boolean geodesic)

    Alternatively, a way to determine if two geodesic "straight" line segments intersect would get me there.

    Or if someone can point me to a ready-made algorithm, great. I don't know the math to pull this off.

    type: feature request help wanted priority: p4 stale 
    opened by bubenheimer 19
  • Add Douglas-Peucker poly simplification algorithm as PolyUtil.simplify()

    Add Douglas-Peucker poly simplification algorithm as PolyUtil.simplify()

    • Douglas-Peucker implementation ported from the Google MyTracks project (https://code.google.com/p/mytracks/source/browse/MyTracks/src/com/google/android/apps/mytracks/util/LocationUtils.java#81), (c) Google 2008, licensed under Apache v2.0.
    • Add demo activity for PolyUtil.simplify() - shows the original line in black, as well as simplified versions of the line with multiple tolerances in different colors
    • Add unit tests for PolyUtil.simplify() and PolyUtil.distanceToLine() in PolyUtilTest

    As discussed with @broady in https://github.com/googlemaps/android-maps-utils/pull/144#issuecomment-140505017.

    @broady A few unrelated white space changes snuck into this commit via Android Studio - seems this happens on save, and I haven't found a way to disable it. Let me know if this is an issue - I'm using the official Android code template.

    opened by barbeau 19
  • "Released unknown imageData reference"

    I am doing the clustering dynamically to get an acceptable performance:

     private class DynamicallyAddMarkerTask extends AsyncTask {
            @Override
            protected void onPostExecute(Object o) {
                super.onPostExecute(o);
                clusterManager.cluster();
            }
    
            @Override
            protected Object doInBackground(Object[] objects) {
                LatLngBounds bounds = (LatLngBounds) objects[0];
                clusterManager.clearItems();
    
                for (LoyaltyOutlet currentMarker : sortedAndFilteredOutlets) {
                    if (bounds.contains(currentMarker.getPosition())) {
                        clusterManager.addItem(currentMarker);
                    }
                }
    
                return null;
            }
        }
    

    This is triggered in a OnCameraChangeListener but unfortunately this makes the lib crash my app now and then. Do you think it will possible to fix this issue in the lib by for example just ignoring the exception?

    Crash stack trace:

     java.lang.IllegalArgumentException: Released unknown imageData reference
                at com.google.common.base.j.a(Unknown Source)
                at com.google.maps.api.android.lib6.impl.f.c(Unknown Source)
                at com.google.maps.api.android.lib6.impl.ap.a(Unknown Source)
                at com.google.maps.api.android.lib6.impl.ap.remove(Unknown Source)
                at com.google.android.gms.maps.model.internal.IMarkerDelegate$Stub.onTransact(IMarkerDelegate.java:51)
                at android.os.Binder.transact(Binder.java:347)
                at com.google.android.gms.maps.model.internal.zzi$zza$zza.remove(Unknown Source)
                at com.google.android.gms.maps.model.Marker.remove(Unknown Source)
                at com.google.maps.android.MarkerManager$Collection.remove(MarkerManager.java:163)
                at com.google.maps.android.MarkerManager.remove(MarkerManager.java:140)
                at com.google.maps.android.clustering.view.DefaultClusterRenderer$MarkerModifier.removeMarker(DefaultClusterRenderer.java:637)
                at com.google.maps.android.clustering.view.DefaultClusterRenderer$MarkerModifier.performNextTask(DefaultClusterRenderer.java:628)
                at com.google.maps.android.clustering.view.DefaultClusterRenderer$MarkerModifier.handleMessage(DefaultClusterRenderer.java:596)
                at android.os.Handler.dispatchMessage(Handler.java:99)
                at android.os.Looper.loop(Looper.java:176)
                at android.app.ActivityThread.main(ActivityThread.java:5419)
                at java.lang.reflect.Method.invokeNative(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:525)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
                at dalvik.system.NativeStart.main(Native Method)
    
    stale 
    opened by cjetrifork 18
  • Google maps does not render KML polygons with inner boundaries correctly (one or more polygons never get rendered)

    Google maps does not render KML polygons with inner boundaries correctly (one or more polygons never get rendered)

    Background

    While creating bathymetric maps as KML I like to make the map earier to read by adding different colored polygons to each 1m level. If using completely filled polygons, the KML is rendered differently each time I do a addLayerToMap (leading me to believe Google Maps have no way to control the order the polygons are added like Google Earth has).

    Problem

    To solve this I altered the KML to also include inner boundaries to "cut out" the inner and eliminate the need for the rendering of the polygons to come in a particular order. Using Google Earth I can verify that the filled polygons never overlap. Google Earth also renders this KML perfectly. But Google Maps can no longer render them all. No clear pattern. On one water every other, on another water perhaps one or two of them are missing.

    Expected behavior

    Using Google Earth: Sample water with all colored polygons selected. Each meter level rendered: image

    Also using Google Earth, I deselected the all levels but 2-3 meters to illustrate that its inner is "cut out". All other polygons but the deepest one have their inner "cut out": image

    I have built my KMLs in two ways: The "hard way" by writing strings with tabs and tags "manually" and by using Python and "simpleKml". I first thought the problem (see below) was caused by simpleKml adding multiple (when applicable, often needed for a water) "LinerarRing" within a single "innerBoundaryIs". So I dropped simpleKml and coded manually to get multiple "innerBoundaryIs" with a single "LinearRing" inside each. But for Google Maps that did not matter, behaviour is identical.

    Sample from the KML-file for the illustrated 2 meter polygon (coordinates are abbreviated - this polygon has one outer boundary (always) and 1+ inner boundaries, this one has 3): <Placemark> <name>2</name> <styleUrl>#2</styleUrl> <Polygon> <tessellate>true</tessellate> <altitudeMode>clampToGround</altitudeMode> <outerBoundaryIs> <LinearRing> <coordinates>10.592408209489095,59.64232214633835,0 ... 10.592408209489095,59.64232214633835,0</coordinates> </LinearRing> </outerBoundaryIs> <innerBoundaryIs> <LinearRing> <coordinates>10.592191189077477,59.642402279689236,0 ... 10.592191189077477,59.642402279689236,0</coordinates> </LinearRing> </innerBoundaryIs> <innerBoundaryIs> <LinearRing> <coordinates>10.590486028700466,59.643027621876,0 ... 10.590486028700466,59.643027621876,0</coordinates> </LinearRing> </innerBoundaryIs> <innerBoundaryIs> <LinearRing> <coordinates>10.589741958717772,59.64305730583021,0 ... 10.589741958717772,59.64305730583021,0</coordinates> </LinearRing> </innerBoundaryIs> </Polygon> </Placemark>

    The KML code is not easy to read in the code editor, here's a picture to easier see the typical structure: image

    Observed behavior

    As stated and visualized above, while Google Earth renders each polygon and also the entire "depth map" perfectly, Google Maps using Android does not. For this particular depth map only one colored polygon is missing. On another water depth map every second is invisible. Here's a screen shot: image

    Environment details

    Multiple devices used, all experience the same behaviour. My development device is a Samsung Galaxy Tab S6 lite (SM-P610), running Android 12 and One UI 4.1.1. Environment for the app is:

    • com.google.android.gms:play-services-maps:18.0.2
    • com.google.maps.android:android-maps-utils:2.4.0

    Steps to reproduce

    The behaviour in Google Maps is fairly consistent, at least it never displays all polygons properly. But the amount of polygons gone missing is not consistent.

    Using a second water map, first in Google Earth: image

    Then using Google Maps: image

    I have also attached the KML for this latter sample (file type altered to "txt", change back to "kml" to use): sample.txt

    type: bug triage me 
    opened by OlavAa 2
  • feat: exposing getColor function in the ClusterRenderer

    feat: exposing getColor function in the ClusterRenderer

    The following PRs exposes the method getColor() in the ClusterRenderer. Thus, developers can override this method and provide their own color schema for clusters.


    • [X] Make sure to open a GitHub issue as a bug/feature request before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea
    • [X] Ensure the tests and linter pass
    • [X] Code coverage does not decrease (if any source code was changed)
    • [X] Appropriate docs were updated (if necessary)
    • [X] Will this cause breaking changes to existing Java or Kotlin integrations? If so, ensure the commit has a BREAKING CHANGE footer so when this change is integrated a major version update is triggered. See: https://www.conventionalcommits.org/en/v1.0.0/

    Fixes #1121

    type: feature request 
    opened by kikoso 0
  • chore(deps): bump lint-api from 30.1.0 to 30.3.1

    chore(deps): bump lint-api from 30.1.0 to 30.3.1

    Bumps lint-api from 30.1.0 to 30.3.1.

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies java 
    opened by dependabot[bot] 0
  • chore(deps): bump lint-checks from 30.1.1 to 30.3.1

    chore(deps): bump lint-checks from 30.1.1 to 30.3.1

    Bumps lint-checks from 30.1.1 to 30.3.1.

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies java 
    opened by dependabot[bot] 0
  • chore(deps): bump lint from 30.0.4 to 30.3.1

    chore(deps): bump lint from 30.0.4 to 30.3.1

    Bumps lint from 30.0.4 to 30.3.1.

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies java 
    opened by dependabot[bot] 0
Releases(v2.4.0)
Maps SDK for Android Utility Library

Maps SDK for Android Utility Library Description This open-source library contains utilities that are useful for a wide range of applications using th

Google Maps 3.4k Dec 30, 2022
Android Maps Extensions is a library extending capabilities of Google Maps Android API v2.

Android Maps Extensions Library extending capabilities of Google Maps Android API v2. While Google Maps Android API v2 is a huge leap forward comapare

Maciej Górski 408 Dec 15, 2022
Scale bar for Android Maps (Google Maps, OSM, MapBox, Yandex)

Map Scale View Scale view for any Android Maps SDK (not only Google Maps) Contributing I encourage you to participate in this project. Feel free to op

Stas Parshin 109 Nov 18, 2022
🍃 Organic Maps is an Android & iOS offline maps app for travelers, tourists, hikers, and cyclists based on top of crowd-sourced OpenStreetMap data and curated with love by MapsWithMe founders.

?? Organic Maps is an Android & iOS offline maps app for travelers, tourists, hikers, and cyclists based on top of crowd-sourced OpenStreetMap data and curated with love by MapsWithMe founders. No ads, no tracking, no data collection, no crapware.

Organic Maps 4.3k Dec 31, 2022
An android app that uses Google Maps API and SDK to track a user's location and calculate the total distance travelled

Bike Rush is an android app that uses Google Maps API and SDK to track a user's location and calculate the total distance travelled by him or her along with time and average speed.

Ishant Chauhan 21 Nov 14, 2022
Curve-Fit is an Android library for drawing curves on Google Maps

Curve-Fit Android library for drawing curves on Google Maps. This library uses Bezier cubic equation in order to compute all intermediate points of a

Sarweshkumar C R 63 Mar 7, 2021
malik dawar 87 Sep 18, 2022
Interactive, thoroughly customizable maps in native Android powered by vector tiles and OpenGL.

Interactive, thoroughly customizable maps in native Android powered by vector tiles and OpenGL.

Mapbox 247 Dec 27, 2022
Demo de uso de google maps en Android, charla para el GDG Chimbote

mapasbasico Demo de uso de google maps en Android, charla para el GDG Chimbote Puedes usar este proyecto como base para trabajar con mapas en Android.

Whiston Kendrick Borja Reyna 4 Sep 17, 2021
Google Maps Api test using marker rotation and routes.

Google Maps Api test using marker rotation and routes. Features ✔️ Kotlin ✔️ DI: Hilt ✔️ Retrofit ✔️ Gson ✔️ View binding ✔️ Coroutines ✔️ AndroidX ✔️

Carlos Adan 39 Jul 15, 2022
EasyRoutes allows you to easily draw routes through the google maps address api.

EasyRoutes EasyRoutes allows you to easily draw routes through the google maps address api. Note: You need to generate an API key from the google cons

Antonio Huerta Reyes 7 Jul 26, 2022
Membuat Custom Tooltip Marker Google Maps

Custom-Tooltip-Marker Membuat Custom Tooltip Marker Google Maps Tutorial Build with Android Studio https://youtu.be/E8ND0YThNiU Tutorial Build with St

Azhar Rivaldi 5 Feb 17, 2022
TileOverlay component for react-native-maps

TileOverlay component for react-native-maps

Joe Julik 1 Apr 10, 2022
App usage tracker which maps your app usage to geo location.

Guilt Guilt is an inspiration from Meta (pun intended), it tracks the apps usage and maps it with geo location data where the app was last used. The a

null 6 Dec 28, 2022
An app to search nearby businesses on Google Maps & Add Grocery Items to List!

GoStore: Internship Program Project A mobile app is built where the user can search for his nearby locations based on his requirement. Whenever the us

null 7 Nov 28, 2022
Android library project that lets you manage the location updates to be as painless as possible

Smart Location Library Android library project that intends to simplify the usage of location providers and activity recognition with a nice fluid API

Nacho Lopez 1.6k Dec 29, 2022
Android library that allows you to determine your location in a few of lines

locsimple Android library that allows you to determine your location in some lines! Benefits: automatic processing of permissions processing of enabli

Dmitry 7 Aug 31, 2022
A library for reverse geocoding coordinates in Android

?? AndroidReverseGeocoder A library for reverse geocoding coordinates in Android. The library is built on top of android's Geocoder library. AndroidRe

ShimShim27 1 Jun 24, 2022
Positional is a location information app for Android with Compass, Clock, Level, Sun and Moon and many other features.

Positional is a location based app that utilizes the device's GPS and fetches various details of the current latitude and longitude data like Altitude, Speed, Address and similar other information and show it in easily understandable format to the user. Alongside this main functionality of being a location app, Positional also provides a separate panel for Compass and Clock, and they serve their own purpose as their name suggests.

Hamza Rizwan 85 Dec 28, 2022