amirpiri / android-maps-extensions

Automatically exported from code.google.com/p/android-maps-extensions
0 stars 0 forks source link

IllegalArgumentException when try to execute marker.setIcon in the onMarkerClick callback #43

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem? Please provide sscce (short, self
contained, correct example) when possible.

1. initialize(add to map) a marker with custom bitmap icon
2. when marker A is clicked, it's icon need to be changed to another bitmap
3. So, I put marker.setIcon(some_new_bitmapDescripter) in the marker's 
onMarkerCLick callback
4. it seems work fine first
5. but after create and click some markers repeatedly, app crashes with 
exception

What is the expected output? What do you see instead?

I want to see markers changing their icon when clicked. but, exception comes 
like below...

--------------------------------------------
    java.lang.IllegalArgumentException: Released unknown bitmap reference
            at maps.aq.o.a(Unknown Source)
            at maps.af.n.b(Unknown Source)
            at maps.af.bk.a(Unknown Source)
            at cpe.onTransact(SourceFile:204)
            at android.os.Binder.transact(Binder.java:326)
            at com.google.android.gms.maps.model.internal.d$a$a.i(Unknown Source)
            at com.google.android.gms.maps.model.Marker.setIcon(Unknown Source)
            at com.androidmapsextensions.lazy.LazyMarker.setIcon(LazyMarker.java:185)
            at com.androidmapsextensions.impl.DelegatingMarker.setIcon(DelegatingMarker.java:188)
            at com.livecity.s.activity.MainActivity.focusOnMarker(MainActivity.java:365)

Original issue reported on code.google.com by wildr...@gmail.com on 15 Jan 2014 at 8:49

GoogleCodeExporter commented 8 years ago
Can you make sure bitmap you pass to BitmapDescriptorFactory.fromBitmap(...) is 
not null and correct otherwise (e.g. not recycled)?

Similar issue found here:
http://stackoverflow.com/questions/18097090/released-unknown-bitmap-reference

Original comment by maciek.g...@gmail.com on 15 Jan 2014 at 9:01

GoogleCodeExporter commented 8 years ago
  I have exactly the same issue with setIcon of marker. In my case the passed BitmapDescriptor is not null and is not recycled.
  The exception is thrown after the marker icon is updated, so try catch block around the setIcon method suppress the error and the result from the operation is right.

Original comment by miro.sok...@gmail.com on 3 Feb 2014 at 10:38

GoogleCodeExporter commented 8 years ago
Hey Miro,

The try-catch around setIcon doesn't seem like a good idea. Can you provide a 
simple example code so we can find the root cause of this issue?

Is the marker visible when you change the icon or hidden in a cluster?

Original comment by maciek.g...@gmail.com on 3 Feb 2014 at 10:47

GoogleCodeExporter commented 8 years ago
Hey,

Well the try-catch isn't elegant, but keeps the things right.

The problem is that the issue doesn't reproduce every time. I will try to make 
sample android project that demonstrates the problem anyway.

The marker is visible when the exception occurs.

Original comment by miro.sok...@gmail.com on 3 Feb 2014 at 11:17

GoogleCodeExporter commented 8 years ago
Does the icon change despite exception being thrown?

Original comment by maciek.g...@gmail.com on 3 Feb 2014 at 11:21

GoogleCodeExporter commented 8 years ago
My previous observations are that it changes, but I couldn't reproduce it in 
the past several minutes to confirm. I will add another comment when I am 
certain about that.

Original comment by miro.sok...@gmail.com on 3 Feb 2014 at 11:38

GoogleCodeExporter commented 8 years ago
I confirm that the icon change despite the exception and the marker is fully 
functional.

I didn't managed to create example that can rapidly reproduce the problem.

Original comment by miro.sok...@gmail.com on 7 Feb 2014 at 3:50

GoogleCodeExporter commented 8 years ago
Found another StackOverflow question about this issue: 
http://stackoverflow.com/questions/21523202/released-unknown-bitmap-reference-se
tting-marker-in-android
Not that it helps, but if someone later answers it, might be easier for anyone 
hitting this page for an answer.

Anyway this is really weird that it "works correctly" if you catch the 
exception. Can you share a bit of your code that might be relevant here?

I have tried to reproduce it with a simple code like this, but it never crashed:

            @Override
            public boolean onMarkerClick(Marker marker) {
                Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);
                canvas.drawColor(0xFF00FFFF);
                marker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));

Original comment by maciek.g...@gmail.com on 16 Feb 2014 at 3:42

GoogleCodeExporter commented 8 years ago
I had a similar problem, when I tried to reload a Marker executing 
"myMarker.setIcon()" then after some refreshes the app ran into a 
"java.lang.IllegalArgumentException: Released unknown bitmap reference".

I discovered that calling "myMap.clear()" for cleaning all markers was the 
problem, In fact in the function docs you can read that "Removes all markers, 
polylines, polygons, overlays, etc from the map.".

Well, that "etc" seems to do more as I expected...

For solving that I used a custom function to iterate through all my markers 
saved in a HashMap and removing one by one, and that's all, no more exceptions 
like that in my code.

You can iterate through all markers to remove them as follows:

/**
 * Alternative to myMap.clear() to avoid undesired exceptions
 */
private void clearAllMapMarkers() {
    // Clearing the current map markers being shown
    // Note that we do not use myMap.clear() because that incur in the exception
    // "java.lang.IllegalArgumentException: Released unknown bitmap reference"
    try {
        for (Map.Entry<String, Marker> markerEntry : mMarkerList.entrySet()) {
            markerEntry.getValue().remove();
        }
    } catch (IllegalArgumentException e) {
        // Manage here the exception (never raised but who knows...)
    }
}

I answered an StackOverflow question here: 
http://stackoverflow.com/questions/18097090/released-unknown-bitmap-reference/21
887173#21887173

Original comment by nes...@ideaknow.com on 19 Feb 2014 at 4:59

GoogleCodeExporter commented 8 years ago
Thank you for giving the solution that worked for you.

Can you also share affected code you were having this issue with? Where you 
were using both clear and setIcon? I think it might be good to post it on the 
official gmaps-api-issues if you can provide example of code that breaks.

Miro, wildroco: did you also use clear in your code? I actually never used it 
in real app, because it does more than I want.

Original comment by maciek.g...@gmail.com on 19 Feb 2014 at 10:25

GoogleCodeExporter commented 8 years ago
I don't use clear. On update I remove the markers that are out of the map and 
add the new markers on the map.

The code that manages the main part of the map functionality is:

Add object:

    private Marker addMapObject(IMapObject mapObject) {
        final BitmapDescriptor iconBitmap = mapObject.getMarkerIcon();
        final LatLng position = new LatLng(mapObject.getLatitude(), mapObject.getLongitude());
        return mMap.addMarker(new MarkerOptions().position(position).icon(iconBitmap));
    }

Create marker icon:

    public BitmapDescriptor getSelectedMarkerIcon() {
        return BitmapDescriptorFactory.fromBitmap(getSelectedIcon());
    }

    public Bitmap getSelectedIcon() {
        return Icons.getSelectedHotelIcon(mStars);
    }

    static Bitmap getSelectedIcon(int stars) {
        final Resources resources = Globals.context.getResources();
        Bitmap marker = BitmapFactory.decodeResource(resources, R.drawable.pin_grey);
        if( stars != 0 ) {
            marker = Paints.signIcon(Const.FILTER_LOW, stars, marker);
        }
        return marker;
    }

    public static Bitmap signIcon(byte priceRange, int stars, Bitmap icon) {
        final Bitmap layout = Bitmap.createBitmap(icon.getWidth(), icon.getHeight(), Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(layout);
        canvas.drawBitmap(icon, 0, 0, null);
        final String starsAsString = String.valueOf(stars);
        final float offsetLeft = icon.getWidth() * 0.50f;
        final float offsetTop = icon.getHeight() * 0.75f;
        final int color = getPaintColor(priceRange);
        final Paint paint = getPaint(color, R.dimen.font_size);
        canvas.drawText(starsAsString, offsetLeft, offsetTop, paint);
        return layout;
    }

Update marker icon:

    /**Wrapper method related with https://code.google.com/p/android-maps-extensions/issues/detail?id=43*/
    private void setMarkerIcon(Marker marker, BitmapDescriptor newIcon) {
        try {
            marker.setIcon(newIcon);
        } catch(Throwable ex) {
            MelonLog.i(getClass().getSimpleName(), "Marker.setIcon failed: " + ex.getMessage());
        }
    }

Manage map objects:

    private class MapObjectUpdater<T extends IMapObject> {

        final HashMap<Marker, T> mapObjects = new HashMap<Marker, T>();

        void update(List<T> updatedMapObjects) {
            removeUnpresentedObjects(updatedMapObjects);
            addNewObjects(updatedMapObjects);
        }

        private void removeUnpresentedObjects(List<T> updatedMapObjects) {
            for(final Iterator<Entry<Marker, T>> it = mapObjects.entrySet().iterator(); it.hasNext(); ) {
                final Entry<Marker, T> entry = it.next();
                final T mapObject = entry.getValue();
                if( ! updatedMapObjects.contains(mapObject)) {
                    final Marker marker = entry.getKey();
                    marker.remove();
                    it.remove();
                }
            }
        }

        private void addNewObjects(List<T> updatedMapObjects) {
            final Collection<T> currentValues = mapObjects.values();
            for(final T object : updatedMapObjects) {
                if( ! currentValues.contains(object)) {
                    final Marker marker = addMapObject(object);
                    mapObjects.put(marker, object);
                }
            }
        }
    }

Original comment by miro.sok...@gmail.com on 20 Feb 2014 at 3:41

GoogleCodeExporter commented 8 years ago
I experienced "IllegalArgumentExcepion: Released unknown bitmap reference" when 
way trying to modify Marker instance which is not on the map anymore. Test code 
to reproduce:

final Marker marker = googleMap.addMarker(..);
googleMap.clear();
marker.setIcon(..);

http://stackoverflow.com/questions/21523202/released-unknown-bitmap-reference-se
tting-marker-in-android/22200809#22200809

Original comment by grigori....@gmail.com on 5 Mar 2014 at 2:39