IllegalArgumentException:使用 gms.maps.model.Marker.setIcon 的非托管描述符 [英] IllegalArgumentException: Unmanaged descriptor using gms.maps.model.Marker.setIcon

查看:27
本文介绍了IllegalArgumentException:使用 gms.maps.model.Marker.setIcon 的非托管描述符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序使用

一些项目配置

  • 我正在使用自定义渲染器(SucursalRender extends DefaultClusterRenderer)
  • 我正在下载带有 Glide 的标记图标,就像我之前说的: Glide.with(context).load(id).fitCenter().placeholder(R.drawable.ic_no_image).into(simpleTarget);

simpleTarget 是我处理为 Glide 下载/缓存的图像的地方.我正在发布关于 simpleTarget 的所有代码,因为崩溃是从那里开始的:

private class CustomSimpleTarget extends SimpleTarget{Sucursal sucursal;标记markerToChange = null;@覆盖public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) {mImageView.setImageDrawable(资源);//currentSelectedItem 为当前在地图中选择的元素(Sucursal 类型)//mIconGenerator 是一个:CustomIconGenerator extends IconGeneratorif (currentSelectedItem != null && sucursal.idalmacen.contentEquals(currentSelectedItem.idalmacen))mIconGenerator.customIconBackground.useSelectionColor(true, ContextCompat.getColor(mContext, R.color.colorAccent));别的mIconGenerator.customIconBackground.useSelectionColor(false, 0);位图图标 = mIconGenerator.makeIcon();如果(markerToChange == null){for (Marker 标记:mClusterManager.getMarkerCollection().getMarkers()) {如果 (marker.getPosition().equals(sucursal.getPosition())) {markerToChange = 标记;}}}//如果找到 - 更改图标如果(markerToChange != null){//GlideShortcutDrawable 是一个 WeakReference<>(drawable)sucursal.setGlideShortCutDrawable(资源);markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(icon));}}}

崩溃在最后一行代码中抛出:markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(icon));

我试图理解/修复它的尝试/发现

  • 尝试在 4 台真实设备中重现该错误,但未成功.
  • 在网络上搜索关于 gms.maps.model.Marker.setIconcom.google.maps.api.android.lib6 的类似错误或代码
  • >
  • 试图理解 Android Studio 中为 Marker.setIcon
  • 提供的混淆代码

我想我可以将代码包装在一个 try-catch 块 中,用于 IllegalArgumentException: Unmanaged descriptor 以避免应用程序因为崩溃而关闭,但这只是一个解决方法.

更新 2
DefaultClusterRenderer的代码:

public class SucursalRender extends DefaultClusterRenderer{/*** 为具有两种背景颜色的标记创建自定义图标.与 {@link com.google.maps.android.clustering.ClusterItem} 一起使用.*/私人最终 CustomIconGenerator mIconGenerator;/*** 标记图像.*/私有最终 ImageView mImageView;/*** 使用单一背景为 {@link Cluster} 创建自定义图标.*/私有最终 IconGenerator mClusterIconGenerator;/*** 集群图像.*/私有最终 ImageView mClusterImageView;私有最终上下文 mContext;/*** 保留对 UI 中突出显示的当前项目的引用(具有不同背景的项目).*/公共 Sucursal currentSelectedItem;/*** {@link ClusterManager} 实例.*/private ClusterManager<Sucursal>mClusterManager;公共 SucursalRender(上下文上下文,GoogleMap 地图,ClusterManager<Sucursal> clusterManager){超级(上下文,地图,集群管理器);mContext = 上下文;mClusterManager = 集群管理器;mIconGenerator = new CustomIconGenerator(mContext.getApplicationContext());mClusterIconGenerator = new IconGenerator(mContext.getApplicationContext());int padding = (int) mContext.getResources().getDimension(R.dimen.custom_profile_padding);int 维度 = (int) mContext.getResources().getDimension(R.dimen.custom_profile_image);//R.layout.map_cluster_layout 是一个简单的 XML,带有用于标记和集群的视觉元素查看视图 = ((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));}...@覆盖受保护的无效 onBeforeClusterItemRendered(最终 Sucursal sucursal,MarkerOptions 标记选项){mImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_no_image));位图图标 = mIconGenerator.makeIcon();markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));}@覆盖protected void onClusterItemRendered(Sucursal clusterItem, Marker 标记) {CustomSimpleTarget simpleTarget = new CustomSimpleTarget();simpleTarget.sucursal = clusterItem;simpleTarget.markerToChange = 标记;ImageLoaderManager.setImageFromId(simpleTarget, clusterItem.logo, mContext);}@覆盖protected void onBeforeClusterRendered(Cluster cluster, MarkerOptions markerOptions) {mClusterImageView.setImageDrawable(ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.ic_sucursales, null));位图图标 = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));}@覆盖受保护的布尔值 shouldRenderAsCluster(集群集群){//总是渲染集群.返回 cluster.getSize() >1;}/*** 只需扩展 {@link IconGenerator} 并提供更改背景的能力.* 用于知道在 UI 中突出显示当前选定的项目.*/私有类 CustomIconGenerator 扩展了 IconGenerator {私人 CustomIconBackground customIconBackground;私有 CustomIconGenerator(上下文上下文){超级(上下文);}}/*** 创建自定义图标以与 {@link Marker} 或 {@link Cluster} 一起使用*/私有类 CustomIconBackground 扩展 Drawable {私人最终 Drawable mShadow;私人最终 Drawable mMask;private int mColor = Color.WHITE;私有布尔 useSelectionColor;私有 int mColorSelection;私人 CustomIconBackground(boolean isCluster) {useSelectionColor = false;如果(isCluster){mMask = ContextCompat.getDrawable(mContext, R.drawable.map_pin_negro_cluster);mShadow = ContextCompat.getDrawable(mContext, R.drawable.map_pin_transparente_cluster);}别的 {mMask = ContextCompat.getDrawable(mContext, R.drawable.map_pin_negro);mShadow = ContextCompat.getDrawable(mContext, R.drawable.map_pin_transparente);}}public void setColor(int color) {mColor = 颜色;}私有无效 useSelectionColor(布尔值,整数颜色){useSelectionColor = 值;mColorSelection = 颜色;}@覆盖public void draw(@NonNull Canvas canvas) {mMask.draw(画布);canvas.drawColor(mColor, PorterDuff.Mode.SRC_IN);mShadow.draw(画布);如果(使用选择颜色){canvas.drawColor(mColorSelection, PorterDuff.Mode.SRC_IN);useSelectionColor = false;}}@覆盖公共无效 setAlpha(int alpha) {抛出新的 UnsupportedOperationException();}@覆盖公共无效 setColorFilter(ColorFilter cf) {抛出新的 UnsupportedOperationException();}@覆盖公共 int getOpacity() {返回 PixelFormat.TRANSLUCENT;}@覆盖public void setBounds(int left, int top, int right, int bottom) {mMask.setBounds(左、上、右、下);mShadow.setBounds(左、上、右、下);}@覆盖public void setBounds(@NonNull Rect bounds) {mMask.setBounds(bounds);mShadow.setBounds(bounds);}@覆盖公共布尔 getPadding(@NonNull 矩形填充){返回 mMask.getPadding(padding);}}

ImageLoaderManager 只是 Glide 的 Facade.

public static void setImageFromId(SimpleTarget simpleTarget, String id, Context context) {如果(AppCompatActivity 的上下文实例){AppCompatActivity 活动 = (AppCompatActivity)context;如果(活动.isDestroyed())返回;}Glide.with(上下文).load(id).fitCenter().placeholder(R.drawable.ic_no_image).into(simpleTarget);}

解决方案

清除地图时

 googleMap.clear();

**删除对地图上所有标记的任何引用**.我遇到了问题并发现问题出在我的代码上,我忘记删除对标记的引用并尝试更改 cleared Marker

的图标

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:


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

解决方案

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

这篇关于IllegalArgumentException:使用 gms.maps.model.Marker.setIcon 的非托管描述符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆