Giter Club home page Giter Club logo

android-maps-utils's Introduction

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 SDK for Android.

  • Marker animation - animates a marker from one position to another
  • Marker clustering — handles the display of a large number of points
  • Marker icons — display text on your Markers
  • Heatmaps — display a large number of points as a heat map
  • Import KML — displays KML data on the map
  • Import GeoJSON — displays and styles GeoJSON data on the map
  • Polyline encoding and decoding — compact encoding for paths, interoperability with Maps API web services
  • Spherical geometry — for example: computeDistance, computeHeading, computeArea
  • Street View metadata — checks if a Street View panorama exists at a given location

You can also find Kotlin extensions for this library in Maps Android KTX.

Requirements

  • Android API level 21+

Installation

dependencies {
    // Utilities for Maps SDK for Android (requires Google Play Services)
    // You do not need to add a separate dependency for the Maps SDK for Android
    // since this library builds in the compatible version of the Maps SDK.
    implementation 'com.google.maps.android:android-maps-utils:3.8.2'

    // Optionally add the Kotlin Extensions (KTX) for full Kotlin language support
    // See latest version at https://github.com/googlemaps/android-maps-ktx
    // implementation 'com.google.maps.android:maps-utils-ktx:<latest-version>'
}

Demo App

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

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

  1. Get a Maps API key
  2. Add a file local.properties in the root project (this file should NOT be under version control to protect your API key)
  3. Add a single line to local.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 debug variant for the Maps SDK for Android version

Documentation

See the reference documentation for a full list of classes and their methods.

Usage

Full guides for using the utilities are published in Google Maps Platform documentation.

Marker utilities

Marker utilities

Data visualization utilities

Data visualization utilities

Polyline and spherical geometry utilities

Additional utilities

Street View metadata utility

Street View metadata utility

The StreetViewUtil class provides functionality to check whether a location is supported in StreetView. You can avoid errors when adding a Street View panorama to an Android app by calling this metadata utility and only adding a Street View panorama if the response is OK.

StreetViewUtils.fetchStreetViewData(LatLng(8.1425918, 11.5386121), BuildConfig.MAPS_API_KEY,Source.DEFAULT)

fetchStreetViewData will return NOT_FOUND, OK, ZERO_RESULTS or REQUEST_DENIED, depending on the response.

By default, the Source is set to Source.DEFAULT, but you can also specify Source.OUTDOOR to request outdoor Street View panoramas.

Migration Guide from v0.x to 1.0

Migrating from v0.x to 1.0

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));
        }
        ...
    }

Contributing

Contributions are welcome and encouraged! See the contributing guide for more info.

Support

This library is offered via an open source license. It is not governed by the Google Maps Platform Technical Support Services Guidelines, the SLA, or the Deprecation Policy (however, any Google Maps Platform services used by the library remain subject to the Google Maps Platform Terms of Service).

This library adheres to semantic versioning to indicate when backwards-incompatible changes are introduced.

If you find a bug, or have a feature request, please file an issue on GitHub.

If you would like to get answers to technical questions from other Google Maps Platform developers, ask through one of our developer community channels including the Google Maps Platform Discord server.

android-maps-utils's People

Contributors

amuramoto avatar arriolac avatar arturdryomov avatar barbeau avatar broady avatar choefele avatar dependabot-preview[bot] avatar dependabot[bot] avatar dkhawk avatar friederbluemle avatar googlemaps-bot avatar hannesa2 avatar hypest avatar irisu avatar jeffdgr8 avatar johnjohndoe avatar jpoehnelt avatar kikoso avatar libby713 avatar markmcd avatar mg6maciej avatar michaelevans avatar minicat avatar noberasco avatar pauminku avatar semantic-release-bot avatar stephenmcd avatar suvercha avatar wangela avatar zamesilyasa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-maps-utils's Issues

How can I add marker dynamically?

Are there ways to add markers dynamically depending on the area of the map which is shown?
I found that Android Map Extensions [https://code.google.com/p/android-maps-extensions/] has this functionality.
Can we be also achieve like that with this library?

I don't want to switch library since this library is very convenient. 😸

Thanks,
SH

java.lang.NoClassDefFoundError: Eclipse

java.lang.NoClassDefFoundError:
com.google.maps.android.heatmaps.HeatmapTileProvider$Builder

the same error appearing with all Objects of utility library.

Eclipse

Unusable performance with >35k items in ClusterManager

If I add over 35k items to the ClusterManager, the actual (drawn) markers are updated after very long delays. For example, I can have one cluster with "1000+" text on it, and when I zoom in, it stays for about 1-2 minutes, and only after that it splits to smaller clusters and markers.

How to get a marker knowing its ClusterItem and vice versa?

First at all, congratulations!!! Great job (we users ask for something but not thanks given). I started to use this library for few days ago (clustering) and I need to show markers in map, and when user click on them, it must to show the info window showing some information about the marker. Inside this information there is a photo profile from url (http...). As you know, the photo has to be taken in a background task, so when onClusterItemClick listener go out, it downloads the photo, and when it ends, callback has to show info window, so in onClusterItemClick listener interface I return true ( I have managed the event and this way info window is not showing) but when callback from image download has to show info window but it can not call showInfoWindow method from a marker object because I have no reference to it. Also, I need to consult some information from cluster in InfoWindowAdapter, and in this case, I know the marker but not the clusterItem information.

As solution, I have tried to give two method to DefaultClusterRenderer class:

    protected Marker getMarker(T item) {
    return mMarkerCache.get(item);
}

protected T getCluster(Marker marker) {
    return mMarkerCache.get(marker);
}

This way I resolve my problem and every was fine until I recived this crash report:

01-30 17:42:50.685: E/ACRA(15290): ACRA caught a ConcurrentModificationException exception for info.si2.android.unidogs.app. Building report.
01-30 17:42:53.513: E/AndroidRuntime(15290): FATAL EXCEPTION: Thread-8895
01-30 17:42:53.513: E/AndroidRuntime(15290): java.util.ConcurrentModificationException
01-30 17:42:53.513: E/AndroidRuntime(15290): at java.util.HashMap$HashIterator.nextEntry(HashMap.java:792)
01-30 17:42:53.513: E/AndroidRuntime(15290): at java.util.HashMap$KeyIterator.next(HashMap.java:819)
01-30 17:42:53.513: E/AndroidRuntime(15290): at java.util.AbstractSet.removeAll(AbstractSet.java:110)
01-30 17:42:53.513: E/AndroidRuntime(15290): at com.google.maps.android.clustering.view.DefaultClusterRenderer$RenderTask.run(DefaultClusterRenderer.java:383)
01-30 17:42:53.513: E/AndroidRuntime(15290): at java.lang.Thread.run(Thread.java:856)

Are this and my methods relationated or is this a independient issue?
Can you confirm me this methods are a good idea in the library?

Thank you, I hope to hear soon about you.

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)

Import in Android Studio fails when ANDROID_HOME environment variable is not set.

Import in Android Studio fails when ANDROID_HOME environment variable is not set. (System.env.ANDROID_HOME in gradle file returns null)

Ambiguous method overloading for method java.io.File#.
Cannot resolve which method to invoke for [null, class org.codehaus.groovy.runtime.GStringImpl] due to overlapping prototypes between:
    [class java.lang.String, class java.lang.String]
    [class java.io.File, class java.lang.String]

Build file '/Users/davydewaele/AndroidStudioProjects/android-maps-utils/demo/build.gradle' line: 35

Consult IDE log for more details (Help | Show Log)

No Cluster for multiple marker having exact same LatitudeLongitude pairs

Hey there,
I'm facing this issue, that if there are multiple markers having exactly same Latitude-Longitude pairs, then cluster is not formed for them,they are shown as a single marker on map,and you can click only the marker which was drawn at last.
The cluster is formed only when a high(means really too much) zoom out is being done..

Some solution will be highly appreciated ..

Thanks a lot :)

Problem building and running demo

I created a new map api key in the api console and added
[my debug SHA1 fingerprint];com.google.maps.android.utils.demo

Update to my map api key in /demo/AndroidManifest.xml

gradlew assemble
...
Execution failed for task ':library:signArchives'.
Cannot perform signing task ':library:signArchives' because it has no configured signatory

Fail 1, cant sign the library.

Ok guess I dont need to use the signing plugin, it it will be signed with the debug key any way. And I dont need to upload the release to central repo so I remove plugins and tasks for signing and maven
//apply plugin: 'maven'
//apply plugin: 'signing'
/signing {
uploadArchives {
def modifyPom(pom) {
..
}
/

gradlew assemble
BUILD SUCCESSFUL

gradlew instrumentTest
BUILD SUCCESSFUL

gradlew startDemo
BUILD SUCCESSFUL

Click on Clustering demo

Fail 2

01-08 23:01:35.606 11111-12026/com.google.maps.android.utils.demo E/Google Maps Android API﹕ Authorization failure. Please see https://developers.google.com/maps/documentation/android/start for how to correctly set up the map.
01-08 23:01:35.606 11111-12026/com.google.maps.android.utils.demo E/Google Maps Android API﹕ Ensure that the following correspond to what is in the API Console: Package Name: com.google.maps.android.utils.demo, API Key: [my new api key], Certificate Fingerprint: [my debug SHA1 fingerprint]
01-08 23:01:35.616 11111-12026/com.google.maps.android.utils.demo I/Google Maps Android API﹕ Failed to contact Google servers. Another attempt will be made when connectivity is established.
01-08 23:01:50.646 11111-12034/com.google.maps.android.utils.demo E/Google Maps Android API﹕ Failed to load map. Error contacting Google servers. This is probably an authentication issue (but could be due to network errors).

Any Ideas?

Cannot add as a library project in eclipse

I have a project already using google play services. I want to use this as a library to my existing project.

Here is what I tried. I added google play services to the 'library' project and added the support library. I also set it as a library project. Eclipse builds the library just fine.

  1. I tried to grab the jar that eclipse built for the library project and add it to the libs folder of my project. When I do that I get complaints about 'Multiple dex flies define com.google.android.gms'. I am guessing because the library project and my project both depend on google play services so its getting linked twice.
  2. I tried adding the library project as an Android library to my project. 'Build Path' -> 'Configure Build Path' -> 'Android' -> Add 'library' as a library to my project. This seems to cause dups with the support library.

Is there a proper way to depend on this project in eclipse if I am not using maven or gradle?

Wrong count

Hi,
first of all thanks for the lib, it's awesome!
I run into a little issue, when I add markers dynamically the Sum of the markers goes nuts. For example, I have 5 markers, I have a button that adds a new marker, when I do it and zoom out the "5" now says "10" and when I zoom in it shows the 6 markers on the map, is this an issue or am I missing some objet.redraw() method call?

support for business version maps

For our app we are moving to the business version of Google maps. This version appears to have another package name then the free version. The package com.google.android.gms.maps is in the business version com.google.android.m4b.maps. Except for the package name, the complete API seems to be identical. Is it possible to add support for this?
See for more info: https://developers.google.com/maps/documentation/business/mobile/android/#using_the_google_maps_mobile_sdk_for_business_with_google_play_services

IconGenerator.setBackground cannot take null

The comments say that we should pass null to remove the background.
However the code calls background.getPadding() without checking if background is null

/**
 * Set the background to a given Drawable, or remove the background.
 *
 * @param background the Drawable to use as the background, or null to remove the background.
 */
@SuppressWarnings("deprecation")
// View#setBackgroundDrawable is compatible with pre-API level 16 (Jelly Bean).
public void setBackground(Drawable background) {
    getContainer().setBackgroundDrawable(background);

    // Force setting of padding.
    // setBackgroundDrawable does not call setPadding if the background has 0 padding.
    Rect rect = new Rect();
    background.getPadding(rect);
    getContainer().setPadding(rect.left, rect.top, rect.right, rect.bottom);
}

ConcurrentModificationException when using GridBasedAlgorithm

Similar to #31, I have a crash when using GridBasedAlgorithm. I've seen that you fixed this problem for NonHierarchicalDistanceBasedAlgorithm in 1845be4. Maybe GridBasedAlgorithm requires a similar fix.

Thanks

01-09 23:09:54.628: E/AndroidRuntime(22407): FATAL EXCEPTION: Thread-806
01-09 23:09:54.628: E/AndroidRuntime(22407): java.util.ConcurrentModificationException
01-09 23:09:54.628: E/AndroidRuntime(22407):    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:792)
01-09 23:09:54.628: E/AndroidRuntime(22407):    at java.util.HashMap$KeyIterator.next(HashMap.java:819)
01-09 23:09:54.628: E/AndroidRuntime(22407):    at com.google.maps.android.clustering.algo.GridBasedAlgorithm.getClusters(GridBasedAlgorithm.java:50)
01-09 23:09:54.628: E/AndroidRuntime(22407):    at com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator.getClustersInternal(PreCachingAlgorithmDecorator.java:83)
01-09 23:09:54.628: E/AndroidRuntime(22407):    at com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator.access$0(PreCachingAlgorithmDecorator.java:73)
01-09 23:09:54.628: E/AndroidRuntime(22407):    at com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator$PrecacheRunnable.run(PreCachingAlgorithmDecorator.java:106)
01-09 23:09:54.628: E/AndroidRuntime(22407):    at java.lang.Thread.run(Thread.java:856)

Cluster / Marker showing inconsitent behaviour

Hey there,
I'm using ClusterManager to add markers/clusters on my map and i'm fetching my LatLong data through server via AsyncTask, and i'm getting inconsistent behaviour,
Sometimes the marker and cluster are rendering perfectly all-right but some times they don't appear unless I zoom in or zoom out the map ..

Help would be much appreciated as i've already wasted my alot of time in searching .

Markers Disappear After Clustering

Initially the map appears fine. After zooming in and watching the cluster animate into individual pins if you then zoom back out and back in the pins no longer appear. Only the cluster names.

InfoWindow for cluster

Hi guys,

Great work on this lib, it's so good. I have a problem though. I have ried for hours and tried every conceivable combination I think of to get a cluster items info window to show.

My scenario is I have a cluster item which has it's info window displayed, when I zoom out it get's clustered and I lose the marker and the infowindow. Ideally I would like my 'selected' marker to not cluster but if I could populate the cluster's infowindow with the info that was on the item marker that would be fine too but as I said I just can't get it to display at all. I've tried the simplest of edits in the custom cluster demo but no joy.

Can anyone get a clusters infowindow to display?

Thanks,

Aaron

Markers disappears after zoom in,out and in again

I created my own map project and added the head version of 'library' in my root folder, added it to my settings.gradle, added the dependency to compile project('library')

Only mod is to remove plugins and tasks for signing and maven from ./library/build.gradle
//apply plugin: 'maven'
//apply plugin: 'signing'
/signing {
uploadArchives {
def modifyPom(pom) {
..
}
/

  1. I start a map and adds my places and the clusters appears great.
  2. I zoom in to one cluster so I can see all markers going to there places, works great
  3. I zoom out and sees all markers going in its clusters again
  4. When zooming in on the first cluster the cluster counts down as its getting smaller and disappears but I don't see the markers this time.

When running on low memory devices: java.lang.OutOfMemoryError: bitmap size exceeds VM budget

Hey,
I'm trying to make clustering work on a low memory device. On Android 2.3.5 it seems that only 25mb are allocated for one App. When some of this is already occupied by other resources (~9mb are occupied before clustering & cluster icon generation), I quickly get a OutOfMemoryError (see error message below) when multiple clusters are to be shown. IMHO this happens during the icon generation.
To prevent this my idea is to use one single bitmap for all clusters, and just changing the textview ontop of them to indicate their size. Because this might be wanted by others aswell I'm posting this here.
Can you recommend a way on how to minimize the memory usage of the cluster icon generator?

Thank you!
Jonas

attached error message:
12-27 16:15:10.590: D/dalvikvm(1020): GC_CONCURRENT freed 2948K, 68% free 8316K/25735K, external 853K/1033K, paused 7ms+11ms
12-27 16:15:10.880: D/dalvikvm(1020): GC_EXTERNAL_ALLOC freed 11K, 68% free 8320K/25735K, external 887K/1033K, paused 169ms
12-27 16:15:10.930: E/dalvikvm-heap(1020): 14400-byte external allocation too large for this process.
12-27 16:15:11.090: D/dalvikvm(1020): GC_FOR_MALLOC freed <1K, 68% free 8319K/25735K, external 759K/1033K, paused 148ms
12-27 16:15:11.090: E/GraphicsJNI(1020): VM won't let us allocate 14400 bytes
12-27 16:15:11.100: D/AndroidRuntime(1020): Shutting down VM
12-27 16:15:11.100: W/dalvikvm(1020): threadid=1: thread exiting with uncaught exception (group=0x40020560)
12-27 16:15:11.100: E/AndroidRuntime(1020): FATAL EXCEPTION: main
12-27 16:15:11.100: E/AndroidRuntime(1020): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
12-27 16:15:11.100: E/AndroidRuntime(1020): at android.graphics.Bitmap.nativeCreateFromParcel(Native Method)
12-27 16:15:11.100: E/AndroidRuntime(1020): at android.graphics.Bitmap.access$000(Bitmap.java:29)
12-27 16:15:11.100: E/AndroidRuntime(1020): at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:906)
12-27 16:15:11.100: E/AndroidRuntime(1020): at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:898)
12-27 16:15:11.100: E/AndroidRuntime(1020): at cov.onTransact(SourceFile:101)
12-27 16:15:11.100: E/AndroidRuntime(1020): at android.os.Binder.transact(Binder.java:279)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.google.android.gms.maps.model.internal.a$a$a.a(Unknown Source)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(Unknown Source)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.google.maps.android.clustering.view.DefaultClusterRenderer.onBeforeClusterRendered(DefaultClusterRenderer.java:668)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.google.maps.android.clustering.view.DefaultClusterRenderer$CreateMarkerTask.perform(DefaultClusterRenderer.java:739)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.google.maps.android.clustering.view.DefaultClusterRenderer$CreateMarkerTask.access$0(DefaultClusterRenderer.java:707)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.google.maps.android.clustering.view.DefaultClusterRenderer$MarkerModifier.performNextTask(DefaultClusterRenderer.java:574)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.google.maps.android.clustering.view.DefaultClusterRenderer$MarkerModifier.handleMessage(DefaultClusterRenderer.java:544)
12-27 16:15:11.100: E/AndroidRuntime(1020): at android.os.Handler.dispatchMessage(Handler.java:99)
12-27 16:15:11.100: E/AndroidRuntime(1020): at android.os.Looper.loop(Looper.java:130)
12-27 16:15:11.100: E/AndroidRuntime(1020): at android.app.ActivityThread.main(ActivityThread.java:3695)
12-27 16:15:11.100: E/AndroidRuntime(1020): at java.lang.reflect.Method.invokeNative(Native Method)
12-27 16:15:11.100: E/AndroidRuntime(1020): at java.lang.reflect.Method.invoke(Method.java:507)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
12-27 16:15:11.100: E/AndroidRuntime(1020): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
12-27 16:15:11.100: E/AndroidRuntime(1020): at dalvik.system.NativeStart.main(Native Method)
12-27 16:15:12.600: D/dalvikvm(1020): GC_CONCURRENT freed 518K, 62% free 9848K/25735K, external 759K/1033K, paused 6ms+54ms
12-27 16:15:13.090: I/Process(1020): Sending signal. PID: 1020 SIG: 9

Downloadable jar file required

I can't make gradle to build the project because of this error:

:tasks FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':tasks'. > Could not determine the dependencies of task ':library:compileReleaseJava'

So I really need an actual jar file to test this project. Can someone attach a built jar file?

Coupling between DefaultClusterRenderer and NonHierarchicalDistanceBasedAlgorithm ?

In the DefaultClusterRenderer the constant NonHierarchicalDistanceBasedAlgorithm.MAX_DISTANCE_AT_ZOOM is used.

Is this a problem?

For me this is a problem, since I would like to make the MAX_DISTANCE_AT_ZOOM configurable. So I can control the "granularity of clusters".

Furthermore I am wondering how this works when using the GridBasedAlgorithm? I guess it is just working because GridBasedAlgorithm.GRID_SIZE has the same value as NonHierarchicalDistanceBasedAlgorithm.MAX_DISTANCE_AT_ZOOM... or am I overlooking something here?

Would it be an approach to introduce a method getMaxDistanceAtZoom on Algorithm and then inject an Algorithm into the DefaultClusterRenderer?
I could do that and issue a Pull-Request ...

ConcurrentModificationException in DefaultClusteringRender

I am getting a ConcurrentModificationException in the DefaultClusteringRender. This happens on line 383 (call to markersToRemove.removeAll):

        // Wait for all markers to be added.
        markerModifier.waitUntilFree();

        // Don't remove any markers that were just added. This is basically anything that had
        // a hit in the MarkerCache.
        markersToRemove.removeAll(newMarkers);

Not 100% sure what the root of this problem is. I.E. should that set be a 'ConcurrentSet' or am I doing something wrong. My guess as to what is happening is that I am performing add and deletes that could be happening on different threads. In which case I would think this is an issue with the Set in DefaultClusteringRender.

Thoughts?

Heat map drawing problems

I try to draw heat map with following coordinates list:

list.add(new LatLng(-37.1886, 145.708));
list.add(new LatLng(-37.8361, 144.845));
list.add(new LatLng(-38.4034, 144.192));
list.add(new LatLng(-38.7597, 143.67));
list.add(new LatLng(-36.9672, 141.083));
list.add(new LatLng(-37.2843, 142.927));

But heat map contains only 4 points on Google Map. And if I comment one of these lines, then heat map will contains 3 points. Why this situation happens?

Gradle minSdkVersion conflict with Google Play Services 4.2.42

Using Google Play Services 4.2.42 and Android Gradle Plugin 0.8.x, I get the following failure when trying to build my app.

:processDebugManifest
[/code/android/MyProject/build/exploded-bundles/ComGoogleMapsAndroidAndroidMapsUtils03.aar/AndroidManifest.xml:2, /code/android/MyProject/build/exploded-bundles/ComGoogleAndroidGmsPlayServices4242.aar/AndroidManifest.xml:3] Main manifest has <uses-sdk android:minSdkVersion='8'> but library uses minSdkVersion='9'
[/code/android/MyProject/build/exploded-bundles/ComGoogleMapsAndroidAndroidMapsUtils03.aar/AndroidManifest.xml:2, /code/android/MyProject/build/exploded-bundles/ComGoogleAndroidGmsPlayServices4242.aar/AndroidManifest.xml:3] Main manifest has <uses-sdk android:targetSdkVersion='8'> but library uses targetSdkVersion='9'
Note: main manifest lacks a <uses-sdk android:targetSdkVersion> declaration, which defaults to value minSdkVersion or 1.
:processDebugManifest FAILED

My project's minSdkVersion is 9. Although this may be an issue with Android developer tools, I'm not quite sure because I just upgraded from version 3.2 to 4.2 of Play Services.

My hacky workaround is to replace the minSdkVersion in the exploded bundle, so I can still pull the library from the central Maven repository.

android.applicationVariants.all{ variant ->
    variant.processManifest.doFirst {
        File manifestFile = file("${buildDir}/exploded-bundles/ComGoogleMapsAndroidAndroidMapsUtils03.aar/AndroidManifest.xml")
        if (manifestFile.exists()) {
            println("Replacing minSdkVersion in Android Maps Utils")
            String content = manifestFile.getText('UTF-8')
            content = content.replaceAll(/minSdkVersion="8"/, 'minSdkVersion=\"9\"')
            manifestFile.write(content, 'UTF-8')
            println(content)
        }
    }
}

Sometimes a "ConcurrentModificationException" occurs when adding markers from multiple threads

When I add markers from multiple threads I sometimes get following exception:
E/AndroidRuntime(19091): at com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm.getClusters(NonHierarchicalDistanceBasedAlgorithm.java:90)
E/AndroidRuntime(19091): at com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator.getClustersInternal(PreCachingAlgorithmDecorator.java:83)
E/AndroidRuntime(19091): at com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator.access$0(PreCachingAlgorithmDecorator.java:73)
E/AndroidRuntime(19091): at com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator$PrecacheRunnable.run(PreCachingAlgorithmDecorator.java:106)

Seems like mItems should be thread safe or what is the best solution for this?

Greetings,
Jonas

Failed resolving Lcom/google/maps/android/utils/demo/CustomMarkerClusteringDemoActivity

I have tried to integrate and deploy android-map-utility within ADT(Eclipse)
I can build apart from a a few warnings I have tried to get rid off.
When trying to run it as an Android application the application crashes.

LogCat:

02-22 13:55:42.318: I/dalvikvm(4270): Failed resolving Lcom/google/maps/android/utils/demo/CustomMarkerClusteringDemoActivity; interface 2305 'Lcom/google/maps/android/clustering/ClusterManager$OnClusterClickListener;'
02-22 13:55:42.318: W/dalvikvm(4270): Link of class 'Lcom/google/maps/android/utils/demo/CustomMarkerClusteringDemoActivity;' failed
02-22 13:55:42.318: E/dalvikvm(4270): Could not find class 'com.google.maps.android.utils.demo.CustomMarkerClusteringDemoActivity', referenced from method com.google.maps.android.utils.demo.MainActivity.onCreate
02-22 13:55:42.318: W/dalvikvm(4270): VFY: unable to resolve const-class 2324 (Lcom/google/maps/android/utils/demo/CustomMarkerClusteringDemoActivity;) in Lcom/google/maps/android/utils/demo/MainActivity;
02-22 13:55:42.318: D/dalvikvm(4270): VFY: replacing opcode 0x1c at 0x001d
02-22 13:55:42.408: D/AndroidRuntime(4270): Shutting down VM
02-22 13:55:42.408: W/dalvikvm(4270): threadid=1: thread exiting with uncaught exception (group=0x41926898)
02-22 13:55:42.408: E/AndroidRuntime(4270): FATAL EXCEPTION: main
02-22 13:55:42.408: E/AndroidRuntime(4270): java.lang.NoClassDefFoundError: com.google.maps.android.utils.demo.CustomMarkerClusteringDemoActivity

Regards OFK

Making two instance of clustermanager in same class.

When i use two instance of cluster manager, for displaying two cluster set
Map is getting clear

private ClusterManager<MyItem> mClusterManager;
private ClusterManager<MyItem> mClusterManager1;

please help.

MarkerOptions

How do you create a ClusterItem using MarkerOptions so that the resulting map marker contains custom configuration options instead of the defaults? If all map adds/removes are suppose to go through ClusterManager/MarkerManager, there is no way to create unique Markers.

Issue refreshing markers

I am trying to change the icon for a selected marker. Neither calling ClusterManager.cluster, nor MapView.invalidate will cause the ClusterRenderer to render new pins.

protected void onBeforeClusterItemRendered(FacilityClusterItem item, MarkerOptions markerOptions) {
        Facility facility = item.getFacility();

        int pinId = 0;

        if (TextUtils.equals(facility.getId(), mSelectedFacilityId)) {
            mIconGenerator.setBackground(mContext.getResources().getDrawable(R.drawable.map_pin_white));
            pinId = facility.getFacilityType().getSelectedMapPinId();
        } else {
            mIconGenerator.setBackground(mContext.getResources().getDrawable(R.drawable.map_pin_purple));
            pinId = facility.getFacilityType().getMapPinId();
        }

        icon = BitmapDescriptorFactory.fromResource(pinId);
        markerOptions.icon(icon);
    }

Cannot use TextIconGenerator from gradle

Our eclipse project has this dependency
import com.google.maps.android.ui.TextIconGenerator;
But I am unable to reference this from gradle through studio project

My gradle file has this (I also tried just compile)

debugCompile 'com.google.android.gms:play-services:4.0.30'
debugCompile 'com.google.maps.android:android-maps-utils:0.1+'
debugCompile 'com.android.support:support-v4:19.0.+'

I also tried changing to IconGenertor but I seeing 'cannot resolve symbol ui'

9-patch graphics for bubble do not scale correctly on XXHDPI devices

When using the IconGenerator to create a marker, the marker looks correct on XHDPI devices. However, on a XXHDPI device such as the Nexus 5, the 9-patch does not seem to be stretched correctly.

Here is an example
marker

In this example, the anchor of the marker should be on the black dot in the red circle. Secondly, the anchor of the bubble is not rendered in the middle of the bubble.

I've fixed this issue locally by copying the bubbles I need into the drawable-nodpi folder instead of drawable-hdpi. However, I think the same or similar fix should be performed at the library level.

Gradle error when building as library project

When I try to build android-map-utils as a library project dependency, I receive the following gradle error:

Gradle: Execution failed for task ':Submodules:android-map-utils:library:prepareComGoogleAndroidGmsPlayServices3159Library'.
> Could not call PrepareLibraryTask.prepare() on task ':Submodules:android-map-utils:library:prepareComGoogleAndroidGmsPlayServices3159Library'

Stacktrace:

Caused by: org.gradle.api.GradleException: Could not call PrepareLibraryTask.prepare() on task ':Submodules:android-map-utils:library:prepareComGoogleAndroidGmsPlayServices3159Library'
at org.gradle.util.JavaMethod.invoke(JavaMethod.java:69)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:219)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:212)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:201)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:527)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:510)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
... 49 more
Caused by: java.lang.IllegalAccessError: tried to access class com.android.build.gradle.internal.tasks.PrepareLibraryTask$_prepare_closure1 from class com.android.build.gradle.internal.tasks.PrepareLibraryTask

Problem with distance formula

As i was reading your code, I noticed that you use the distance formula for a 2d plane ( (x2-x1)^2 + (y2-y1)^2
shouldn't you use the haversine function with the radius of earth instead to compute the distance on a spherical object (globe), this is what I did for a project I worked on a while ago. I can give you the code I used if you want to

onClusterClick method gets passed with a null Cluster (collection)

I am encountering instances where the onClusterClick method, gets passed with a null parameter. Similar to the demo app, the cluster parameter below is null, causing the application to crash, when a user clicks the "cluster marker". Another symptom when this issue is happening, is that there are way more "cluster markers" as there should be, i.e. when totally zoomed out (picture below), they are still there, instead of just one marker. I find that this happens, when I am "slowly" zooming in and out a few times. I am pointing to version 0.2.1 (gradle).

My work around right now, is to add a try-catch, at least the App doesn't crash. Any ideas?

@Override
public boolean onClusterClick(Cluster<Person> cluster) {
    // Show a toast with some info when the cluster is clicked.
    String firstName = cluster.getItems().iterator().next().name;
    Toast.makeText(this, cluster.getSize() + " (including " + firstName + ")", Toast.LENGTH_SHORT).show();
    return true;
}

zoomed_out

Demo: Failed to load map !

I cannot open the map, error:

08-11 21:52:07.831: E/Google Maps Android API(12036): Failed to load map. Error contacting Google servers. This is probably an authentication issue (but could be due to network errors).

I have a valid maps v2 api key !

Fix warnings in library

When using android-maps-utils as a library in ADT (v22.3.0-887826/Android SDK 4.4.2), I get 15 warnings (see below list). I'd be happy to fix these warnings – are you interested in a pull request?

-Claus

Description Resource    Path    Location    Type
This Handler class should be static or leaks might occur (com.google.maps.android.clustering.view.DefaultClusterRenderer.ViewModifier)  DefaultClusterRenderer.java /android-maps-utils/src/com/google/maps/android/clustering/view line 228    Android Lint Problem
The constructor Point(double, double) is deprecated SphericalMercatorProjection.java    /android-maps-utils/src/com/google/maps/android/projection  line 33 Java Problem
This Handler class should be static or leaks might occur (com.google.maps.android.clustering.view.DefaultClusterRenderer.MarkerModifier)    DefaultClusterRenderer.java /android-maps-utils/src/com/google/maps/android/clustering/view line 501    Android Lint Problem
The type Point is deprecated    SphericalMercatorProjection.java    /android-maps-utils/src/com/google/maps/android/projection  line 28 Java Problem
The type Point is deprecated    SphericalMercatorProjection.java    /android-maps-utils/src/com/google/maps/android/projection  line 33 Java Problem
The import android.util.Log is never used   GridBasedAlgorithm.java /android-maps-utils/src/com/google/maps/android/clustering/algo line 4  Java Problem
The import com.google.android.gms.maps.Projection is never used Algorithm.java  /android-maps-utils/src/com/google/maps/android/clustering/algo line 3  Java Problem
The value of the field GridBasedAlgorithm<T>.TAG is not used    GridBasedAlgorithm.java /android-maps-utils/src/com/google/maps/android/clustering/algo line 20 Java Problem
The value of the local variable pointIndex is not used  PolyUtil.java   /android-maps-utils/src/com/google/maps/android line 299    Java Problem
The value of the field PreCachingAlgorithmDecorator<T>.TAG is not used  PreCachingAlgorithmDecorator.java   /android-maps-utils/src/com/google/maps/android/clustering/algo line 17 Java Problem
The value of the field ClusterManager<T>.TAG is not used    ClusterManager.java /android-maps-utils/src/com/google/maps/android/clustering  line 28 Java Problem
The import java.util.LinkedHashSet is never used    NonHierarchicalDistanceBasedAlgorithm.java  /android-maps-utils/src/com/google/maps/android/clustering/algo line 16 Java Problem
The import com.google.android.gms.maps.model.MarkerOptions is never used    ClusterItem.java    /android-maps-utils/src/com/google/maps/android/clustering  line 4  Java Problem
Type safety: The expression of type PointQuadTree[] needs unchecked conversion to conform to PointQuadTree<T>[] PointQuadTree.java  /android-maps-utils/src/com/google/maps/android/quadtree    line 126    Java Problem
The import android.util.Log is never used   SquareTextView.java /android-maps-utils/src/com/google/maps/android/ui  line 6  Java Problem

`OutOfMemoryError` in `makeIcon()` of IconGenerator

I'm using the library for its cluster manager. I wanted to customize the cluster appearance so I followed the demo code and used the IconGenerator class to help me generate the cluster icon.

I initialize the cluster icon generator with a custom content view:

private final IconGenerator mClusterIconGenerator = new IconGenerator(getActivity());
mClusterIconGenerator.setContentView(inflater.inflate(R.layout.cluster_marker, null));

My custom view holds a background and a TextView:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="60dp"
    android:layout_height="54dp"
    android:background="@drawable/map_cluster_background" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|left"
        android:layout_marginLeft="12dp"
        android:layout_marginTop="17dp"
        android:textColor="#FFFFFF"
        android:textSize="14sp"/>

</FrameLayout>

Later a custom renderer uses this IconGenerator on the onBeforeClusterRendered method:

final Bitmap icon = mClusterIconGenerator.makeIcon(cluster.getItems().toString());

This throws the OutOfMemoryError exception. I found out that at least in my device "Samsung S2" the view is not measured correctly and therefore the makeIcon method is attempting to create a huge bitmap. (I modified the IconGenerator code log the calculated measurements in the makeIcon method)

Log.d(IconGenerator.class.getName(), "## WIDTH: " + measuredWidth + ", HEIGHT: " + measuredHeight + " ##");
Bitmap r = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);

The log outputs:

 ## WIDTH: 70233, HEIGHT: 104 ##

May be there is something wrong with my view, or measuring doesn't work correctly on my device.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.