IllegalArgumentException: Unmanaged descriptor using gms.maps.model.Marker.setIcon
Asked Answered
L

11

71

I have an app that use android-maps-utils and glide for marker icons.
I got an error report using Firebase crash reporting which I can't track in source code because gms.maps.model.Marker.setIcon is private, so I'm asking for some help with this problem.
The follow part of the question is divided into:

  • What the user was doing
  • What firebase crash reported to me
  • Some project configs
  • What I tried/found trying to understand/fix it

What the user was doing
He was zooming in and out in a map (Fragment that uses com.google.android.gms.maps.SupportMapFragment)

What firebase crash reported to me

Exception java.lang.IllegalArgumentException: Unmanaged descriptor
com.google.maps.api.android.lib6.common.k.b (:com.google.android.gms.DynamiteModulesB:162)
com.google.maps.api.android.lib6.impl.o.c (:com.google.android.gms.DynamiteModulesB:75)
com.google.maps.api.android.lib6.impl.db.a (:com.google.android.gms.DynamiteModulesB:334)
com.google.android.gms.maps.model.internal.q.onTransact (:com.google.android.gms.DynamiteModulesB:204)
android.os.Binder.transact (Binder.java:387)
com.google.android.gms.maps.model.internal.zzf$zza$zza.zzL () com.google.android.gms.maps.model.Marker.setIcon ()
co.com.spyspot.ui.content.sucursal.SucursalRender$CustomSimpleTarget.onResourceReady (SucursalRender.java:156)
co.com.spyspot.ui.content.sucursal.SucursalRender$CustomSimpleTarget.onResourceReady (SucursalRender.java:130)
com.bumptech.glide.request.GenericRequest.onResourceReady (GenericRequest.java:525)
com.bumptech.glide.request.GenericRequest.onResourceReady (GenericRequest.java:507)
com.bumptech.glide.load.engine.EngineJob.handleResultOnMainThread (EngineJob.java:158)
com.bumptech.glide.load.engine.EngineJob.access$100 (EngineJob.java:22)
com.bumptech.glide.load.engine.EngineJob$MainThreadCallback.handleMessage (EngineJob.java:202)
android.os.Handler.dispatchMessage (Handler.java:98)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:5443)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:728)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:618)

And:

enter image description here

Some project configs

  • I'm using a Custom Render (SucursalRender extends DefaultClusterRenderer<Sucursal>)
  • I'm downloading the Marker icon with Glide like I said before: Glide.with(context).load(id).fitCenter().placeholder(R.drawable.ic_no_image).into(simpleTarget);

The simpleTarget is where I handle the images downloaded/cached for Glide. I'm posting all code about simpleTarget because the crash is starting there:

private class CustomSimpleTarget extends SimpleTarget<GlideDrawable> {
    Sucursal sucursal;
    Marker markerToChange = null;

    @Override
    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
        mImageView.setImageDrawable(resource);
        //currentSelectedItem is the current element selected in the map (Sucursal type)
        //mIconGenerator is a: CustomIconGenerator extends IconGenerator
        if (currentSelectedItem != null && sucursal.idalmacen.contentEquals(currentSelectedItem.idalmacen))
            mIconGenerator.customIconBackground.useSelectionColor(true, ContextCompat.getColor(mContext, R.color.colorAccent));
        else
            mIconGenerator.customIconBackground.useSelectionColor(false, 0);

        Bitmap icon = mIconGenerator.makeIcon();

        if (markerToChange == null) {
            for (Marker marker : mClusterManager.getMarkerCollection().getMarkers()) {
                if (marker.getPosition().equals(sucursal.getPosition())) {
                    markerToChange = marker;
                }
            }
        }

        // if found - change icon
        if (markerToChange != null) {
            //GlideShortcutDrawable is a WeakReference<>(drawable)
            sucursal.setGlideShortCutDrawable(resource);
            markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(icon));
        }
    }
}

The crash is being thrown in last line of code: markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(icon));

What I tried/found trying to understand/fix it

  • Tried to reproduce the error in 4 real devices without success.
  • Searched in web for similar errors or code about gms.maps.model.Marker.setIcon or com.google.maps.api.android.lib6
  • Tried to understand the obfuscated code given in Android Studio for Marker.setIcon

I guess I can wrap the code in a try-catch block for that IllegalArgumentException: Unmanaged descriptor to avoid application get closed because the crash but it's just a work around it.

update 2
The code of DefaultClusterRenderer:

public class SucursalRender extends DefaultClusterRenderer<Sucursal> {
    /**
     * Create a customized icon for markers with two background colors. Used with {@link com.google.maps.android.clustering.ClusterItem}.
     */
    private final CustomIconGenerator mIconGenerator;
    /**
     * Marker image.
     */
    private final ImageView mImageView;
    /**
     * Create a customized icon for {@link Cluster<Sucursal>} with a single background.
     */
    private final IconGenerator mClusterIconGenerator;
    /**
     * Cluster image.
     */
    private final ImageView mClusterImageView;
    private final Context mContext;
    /**
     * Keep a reference to the current item highlighted in UI (the one with different background).
     */
    public Sucursal currentSelectedItem;
    /**
     * The {@link ClusterManager<Sucursal>} instance.
     */
    private ClusterManager<Sucursal> mClusterManager;

    public SucursalRender(Context context, GoogleMap map, ClusterManager<Sucursal> clusterManager) {
        super(context, map, clusterManager);

        mContext = context;
        mClusterManager = clusterManager;
        mIconGenerator = new CustomIconGenerator(mContext.getApplicationContext());
        mClusterIconGenerator = new IconGenerator(mContext.getApplicationContext());

        int padding = (int) mContext.getResources().getDimension(R.dimen.custom_profile_padding);
        int dimension = (int) mContext.getResources().getDimension(R.dimen.custom_profile_image);

        //R.layout.map_cluster_layout is a simple XML with the visual elements to use in markers and cluster
        View view = ((AppCompatActivity)mContext).getLayoutInflater().inflate(R.layout.map_cluster_layout, null);
        mClusterIconGenerator.setContentView(view);
        mClusterImageView = (ImageView) view.findViewById(R.id.image);
        mClusterImageView.setPadding(padding, padding, padding, padding);

        mImageView = new ImageView(mContext.getApplicationContext());
        mImageView.setLayoutParams(new ViewGroup.LayoutParams(dimension, dimension));
        mImageView.setPadding(padding, padding, padding, padding);
        mIconGenerator.setContentView(mImageView);

        CustomIconBackground customIconBackground = new CustomIconBackground(false);
        mIconGenerator.setBackground(customIconBackground);
        mIconGenerator.customIconBackground = customIconBackground;
        mClusterIconGenerator.setBackground(new CustomIconBackground(true));
    }

    ...

    @Override
    protected void onBeforeClusterItemRendered(final Sucursal sucursal, MarkerOptions markerOptions) {

        mImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_no_image));
        Bitmap icon = mIconGenerator.makeIcon();
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
    }

    @Override
    protected void onClusterItemRendered(Sucursal clusterItem, Marker marker) {
        CustomSimpleTarget simpleTarget = new CustomSimpleTarget();
        simpleTarget.sucursal = clusterItem;
        simpleTarget.markerToChange = marker;
        ImageLoaderManager.setImageFromId(simpleTarget, clusterItem.logo, mContext);
    }

    @Override
    protected void onBeforeClusterRendered(Cluster<Sucursal> cluster, MarkerOptions markerOptions) {
        mClusterImageView.setImageDrawable(ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.ic_sucursales, null));
        Bitmap icon = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
    }

    @Override
    protected boolean shouldRenderAsCluster(Cluster cluster) {
        // Always render clusters.
        return cluster.getSize() > 1;
    }

    /**
     * Just extends {@link IconGenerator} and give the ability to change background.
     * Used to know highlight the current selected item in UI.
     */
    private class CustomIconGenerator extends IconGenerator {
        private CustomIconBackground customIconBackground;
        private CustomIconGenerator(Context context) {
            super(context);
        }
    }


    /**
     * Create a custom icon to use with {@link Marker} or {@link Cluster<Sucursal>}
     */
    private class CustomIconBackground  extends Drawable {

        private final Drawable mShadow;
        private final Drawable mMask;
        private int mColor = Color.WHITE;

        private boolean useSelectionColor;
        private int mColorSelection;

        private CustomIconBackground(boolean isCluster) {
            useSelectionColor = false;

            if (isCluster) {
                mMask = ContextCompat.getDrawable(mContext, R.drawable.map_pin_negro_cluster);
                mShadow = ContextCompat.getDrawable(mContext, R.drawable.map_pin_transparente_cluster);
            }
            else {
                mMask = ContextCompat.getDrawable(mContext, R.drawable.map_pin_negro);
                mShadow = ContextCompat.getDrawable(mContext, R.drawable.map_pin_transparente);
            }
        }

        public void setColor(int color) {
            mColor = color;
        }

        private void useSelectionColor(boolean value, int color) {
            useSelectionColor = value;
            mColorSelection = color;
        }
        @Override
        public void draw(@NonNull Canvas canvas) {
            mMask.draw(canvas);
            canvas.drawColor(mColor, PorterDuff.Mode.SRC_IN);
            mShadow.draw(canvas);

            if (useSelectionColor) {
                canvas.drawColor(mColorSelection, PorterDuff.Mode.SRC_IN);
                useSelectionColor = false;
            }
        }

        @Override
        public void setAlpha(int alpha) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setColorFilter(ColorFilter cf) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }

        @Override
        public void setBounds(int left, int top, int right, int bottom) {
            mMask.setBounds(left, top, right, bottom);
            mShadow.setBounds(left, top, right, bottom);
        }

        @Override
        public void setBounds(@NonNull Rect bounds) {
            mMask.setBounds(bounds);
            mShadow.setBounds(bounds);
        }

        @Override
        public boolean getPadding(@NonNull Rect padding) {
            return mMask.getPadding(padding);
        }
    }

The ImageLoaderManager is just a Facade for Glide.

public static void setImageFromId(SimpleTarget<GlideDrawable> simpleTarget, String id, Context context) {

    if (context instanceof AppCompatActivity) {
        AppCompatActivity activity = (AppCompatActivity)context;
        if (activity.isDestroyed())
            return;
    }
    Glide.with(context)
            .load(id)
            .fitCenter()
            .placeholder(R.drawable.ic_no_image)
            .into(simpleTarget);
}
Lynching answered 27/1, 2017 at 20:27 Comment(15)
I don't think that's the problem - but the whole markerToChange thing looks bad. Why not pass the marker to the CustomSimpleTarget constructor? This way the callback have a (weak?) reference to the marker, and you don't need to travers all markers, nor guessing that this is the right marker.Insnare
Hi @YoniGross CustomSimpleTarget is an async process (when Glide is downloading the image). When the image get downloaded you don't know the state of the markers at that moment and the marker that you could pass into the constructor could be still in memory but not displayed in map (because is in process of sync with new markers in map, check out how markers got updated when you zoom in/out in android-maps-utils and you will understand what I'm talking about).Lynching
Besides I guess you would not get much having that marker, I mean, in that method, before trying to setIcon() I'm sure I have the marker... suppose is the one you are trying to get in the constructor... the problem still remains in the next line of code markerToChange.setIconLynching
Anyway if you have a better implementation of SimpleTarget<GlideDrawable>, I will be happy if you can share it with SO communityLynching
have you tried ?Glide.with(context).load(id).fitCenter().placeholder(R.drawable.ic_no_image).override(60, 60).into(simpleTarget);Awad
@MiguelHincapieC, no problem, if you'll share the code using CustomSimpleTarget and setting the marker in it I'll gladly share the way I think it can be improved.Insnare
@YoniGross ready, I added the code.Lynching
@JadavLalit nope I have not tried that. Could you explain me a little bit what I could be looking for implementing it please?Lynching
@Lynching If you using large bitmap then map may produce Out of Memory error,and error returned by it is unknown or hard to find what actual problem is. Therefore, .ov‌​erride(60, 60) function with glide load small image on map. That is good to resize image in what size you exactly using in app.Awad
@JadavLalit thanks for the advice. I'm gonna take a look at all images and talk with the designer but I'm almost sure they are smallLynching
@Lynching after some inspection of google-maps-utils and it's DefaultClusterManager, I've changed my mind. The problem might be exactly the opposite: the cluster manager constantly removing marker and adding new markers. Especially when zooming (and need to create / break clusters). Therefore, it's possible the marker you are referring to in your glide target has been removed from the map already. So actually not referencing the marker in the target should fix the issue, although not optimal, and I would have change the whole 'rendering' implementation.Insnare
@YoniGross lets see if I understood, removing if (markerToChange == null) will help me with this issue (ok, I'm going to try it). Changing the whole 'rendering' you mean: SucursalRender? I did it based on google-maps-utils demos and some well vote up answers with snippet. Like I said before, if you have one better I will be happy to use it ;). I could reference it in lot of question about it (google-maps-utils and async download content) to help people to use it.Lynching
Yes, as far as I understand it should. The ClusterRenderer role is to constantly render the markers (for single items/clusters) based on map state (e.g Zoom level). The onBeforeRender callbacks acts in a similar fashion to RecyclerView.Adapter.bindHolder.bindViewHolder(). Look at DefaultClusterRenderer.RenderTask code - it is constantly removing markers and adding new ones when animating. The difference between your code and in CustomMarkerClusteringDemoActivity is that the setIcon operation there is sync while yours is async. You should load asyncly to the model and sync in render.Insnare
@Lynching have you tried my suggestion? And assuming it fixed the issue, do you understand why it happens and how to re-write your rendering code properly?Insnare
@YoniGross yeah I got your idea about has the model in a separate layer. I did it, also used JadavLalit advice about override method but still today I got a fire crash report. I will try what user2595794 said.Lynching
S
30

When clearing the map with

    googleMap.clear();

**remove any reference to all the markers** on the map. I had the problem and figured out that the problem was with my code which I forgot to remove reference to a marker and tried to change icon of a cleared Marker

Sergius answered 1/11, 2017 at 15:7 Comment(3)
Great tip! This wasn't exactly my case but it did point out my problem. After a device reset or back button pressed event the map reloaded and all saved map markers became invalid. I was recreating all the markers nicely but I forgot 1 reference that I was maintaining separately from my array list. Once I recreated the stray marker from the old one, that fixed my error.Assentation
So for an example if you had many points and by selection you wanna update icon and revert previous point to normal icon, after resume fragment you had to know what was that last point. So i need to keep a refrence to my last Marker.Perceval
What did you mean ~"remove any reference to all the markers"? Kotiln doesn't have references like Swift.Minutely
I
22

I found this happening when accessing marker after it was removed. Interacting with marker in callback is exactly that case. As mentioned in Map's API:

After a marker has been removed, the behavior of all its methods is undefined. https://developers.google.com/android/reference/com/google/android/gms/maps/model/Marker.html#remove()

Best option would be checking is marker removed from map or not.
But we don't have such API. And I found another workaround, we can use Marker's setTag and getTag. Tag is set to null, when marker is removed:

Google Maps Android API neither reads nor writes this property, except that when a marker is removed from the map, this property is set to null. https://developers.google.com/android/reference/com/google/android/gms/maps/model/Marker.html#setTag(java.lang.Object)

When creating marker use some tag for it.
When updating marker check tag is not null.

This could help in your case.

@Override
protected void onClusterItemRendered(Sucursal clusterItem, Marker marker) {
    // we don't care about tag's type so don't reset original one
    if (marker.getTag() == null) {
        marker.setTag("anything");
    }
    CustomSimpleTarget simpleTarget = new CustomSimpleTarget();
    simpleTarget.sucursal = clusterItem;
    simpleTarget.markerToChange = marker;
    ImageLoaderManager.setImageFromId(simpleTarget, clusterItem.logo, mContext);
}

And in callback

private class CustomSimpleTarget extends SimpleTarget<GlideDrawable> {
    ...

    @Override
    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
        ...

        // if found - change icon
        if (markerToChange != null) {
            //GlideShortcutDrawable is a WeakReference<>(drawable)
            sucursal.setGlideShortCutDrawable(resource);
            if (markerToChange.getTag != null) {
                markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(icon));
            }
        }
    }
}
Induction answered 23/3, 2017 at 12:4 Comment(3)
I agree with your analysis although I found adding a wrapper around the Marker to manage this "has it been removed flag" and other data was beneficial, simply because the API says "After a marker has been removed, the behavior of all its methods is undefined." which would in theory include the 'getTag' - but obviously in implementation the 'getTag' evidently still works.Hawes
Continuing, the API docs (following your link) no longer indicates that it sets tag to null when removed but advises the client to call setTag(null) (which contradicts the "behaviour of all other methods is undefined" statement but still seems to function.Hawes
the solution in my case: adding tags to markers and checking the tag before setting the icon on markerLavona
M
16

I was too getting same exception and setting silent exception with try/catch would not have been solution as user is not able to see current location in my case:

java.lang.IllegalArgumentException: Unmanaged descriptor at com.google.maps.api.android.lib6.common.k.b(:com.google.android.gms.DynamiteModulesB:162) at com.google.maps.api.android.lib6.impl.o.c(:com.google.android.gms.DynamiteModulesB:75) at com.google.maps.api.android.lib6.impl.db.a(:com.google.android.gms.DynamiteModulesB:334) at com.google.android.gms.maps.model.internal.q.onTransact(:com.google.android.gms.DynamiteModulesB:204) at android.os.Binder.transact(Binder.java:361) at com.google.android.gms.maps.model.internal.zzf$zza$zza.zzL(Unknown Source) at com.google.android.gms.maps.model.Marker.setIcon(Unknown Source)

What I was doing :

Minimize the map fragment screen by pressing home button and then starting app from launcher.

What code was doing:

Checking is marker is not null and location is not null set location and icon.

     if (markerCurrentLocation == null && googleMap != null) {
            markerCurrentLocation = googleMap.addMarker(new MarkerOptions()
                    .position(new LatLng(0.0, 0.0))
                    .icon(null));
            markerCurrentLocation.setTag(-101);
       }

         if (markerCurrentLocation != null && location != null) {
                markerCurrentLocation.setPosition(new LatLng(location.getLatitude(), location.getLongitude()));
                if (ORDER_STARTED) {
                   markerCurrentLocation.setIcon(CURRENT_MARKER_ORANGE);
                } else {
                    markerCurrentLocation.setIcon(CURRENT_MARKER_GRAY);
                }       
         }

Exception was at : markerCurrentLocation.setIcon();

How I got rid of this exception:

I removed the following line

 if (markerCurrentLocation == null && googleMap != null) 

Which means I am initializing marker again. If you encounter this error, try not to setIcon() on old marker, instead inflate new marker and then use setIcon().

Explanation:

I ASSUME (not sure) exception reason was if code is trying to setIcon() again on marker on which it is already set , at particular instance like in my case Map is resuming or may be in your case marker goes out of visible part of map and comes in or something similar.

For sure there is no problem with descriptor we get from method BitmapDescriptorFactory.fromBitmap() or BitmapDescriptorFactory.fromResource(). As the exception hints, descriptor got unmanaged on a old marker, better use new one.

Madelenemadelin answered 10/2, 2017 at 11:51 Comment(2)
Seem it's the nearest answer to my problem. You are getting same error for a different cause, but it gave me a light about what the problem could be. The hard thing is I don't have any devices in where the error is happening (it's a fire crash report for an app on store). So what I'm going to try what you and @JadavLalit said, publish a new version and then wait if I keep getting the error report... or not.Lynching
The bounty is about to finish and like I said before, your answer is the closest one to the problem, so I will give you the bounty. But take in count your answer (at this moment) is just giving me a path or direction in where I can look for the error. To check the answer like an accepted answer, it should replicate the code, show where and how the error was happening and how to fix it.Lynching
M
5

This exception happens when your marker was reclustered by ClusterManager. ClusterManager recreates marker on clustering. So, to avoid it you must get your marker from render of ClusterManeger:

ClusterIconRender render = (ClusterIconRender) mClusterManager.getRenderer();
Marker trueMarker = render.getMarker(clusterMarker);
if (trueMarker != null) {
    trueMarker.setIcon(...);
    ... // do whatever else your want with marker
}

In code above ClusterMarker implements ClusterItem and ClusterIconRender extends DefaultClusterRenderer.

Mcmillon answered 12/5, 2017 at 12:43 Comment(3)
This was the correct solution for me. I was storing a reference to the Marker but when working with ClusterItem you should be storing a reference to the ClusterItem instead and getting the marker through it.Atalie
Thanks, this work for me. I save current selected marker to set "uselected image", when another marker is selected.Siphon
This was the answer to me too. Just don't try to track any Markers yourself, always get them from the ClusterIconRenderer based on your ClusterItem.Elude
G
3

I have the same environment (maps-utils + custom renderer + Glide) and the same error IllegalArgumentException: Unmanaged descriptor.

I solved the error by checking if the marker is "valid" before setting the icon, using the methods DefaultClusterRenderer.getCluster(Marker) and DefaultClusterRenderer.getClusterItem(Marker). If both return null, I don't do anything on the onResourceReady(...) method.

In your case I would try the following change to CustomSimpleTarget:

private class CustomSimpleTarget extends SimpleTarget<GlideDrawable> {
    Sucursal sucursal;
    Marker markerToChange = null;

    @Override
    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {

        if (getCluster(markerToChange) != null || getClusterItem(markerToChange) != null) {

            mImageView.setImageDrawable(resource);
            //currentSelectedItem is the current element selected in the map (Sucursal type)
            //mIconGenerator is a: CustomIconGenerator extends IconGenerator
            if (currentSelectedItem != null && sucursal.idalmacen.contentEquals(currentSelectedItem.idalmacen))
                mIconGenerator.customIconBackground.useSelectionColor(true, ContextCompat.getColor(mContext, R.color.colorAccent));
            else
                mIconGenerator.customIconBackground.useSelectionColor(false, 0);

            Bitmap icon = mIconGenerator.makeIcon();

            //GlideShortcutDrawable is a WeakReference<>(drawable)
            sucursal.setGlideShortCutDrawable(resource);
            markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(icon));
        }
    }
}

PS.: I can reproduce the problem easily on a slow device and clearing the app cache before testing (to force Glide to load from network). Then I open the map and perform some zoom in/out before any markers load.

Galton answered 13/2, 2017 at 14:29 Comment(0)
W
2

Had the same exception after adding cluster. I fixed it by calling:

clusterManager.clearItems()

Instead of calling method I used before, without cluster:

googleMap.clear();
Warila answered 24/10, 2020 at 11:19 Comment(1)
Thank you for the answer, it's been a while since I got stuck with this and the code has changed or been improved, the true is I have no criteria to accept one or another answer. Ty anyway for helping with this answer :).Lynching
G
1

Exact Solution

We should stop clearing googleMap. Before add marker, this code should be work. And this crash will be solved.

        clusterManager.clearItems()
        clusterManager.markerCollection.clear()
    
Gadolinite answered 28/3, 2023 at 9:59 Comment(0)
T
0

Make sure the icon that you are using for marker should not be vector,it should be .png image.

Toadstool answered 9/2, 2017 at 7:12 Comment(2)
Unfortunately they are all .pngLynching
@Toadstool you can use vector image as marker for that you need to add some codeComprehend
A
0

I fixed it by calling the following method.

clusterManager.clearItems()

After that, you can set bitmap to the markers.

Almond answered 24/5, 2019 at 7:7 Comment(0)
A
0

Marker centerPoint

when you do that: centerPoint.remove();

And then you do it again :

marker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));

It throws an error :

Unmanaged descriptor

You should centerPoint.remove(); centerPoint=null;

Amphitryon answered 29/9, 2019 at 7:45 Comment(0)
B
0

Try

mClusterManager.markerCollection.clear();
mMap.clear()
Betroth answered 28/8, 2020 at 23:50 Comment(1)
Adding a quick explanation with this code sample can help improve this answer.Disguise

© 2022 - 2024 — McMap. All rights reserved.