我有一个使用android-maps-utils和glide 标记图标的应用程序。
我收到了使用 Firebase 崩溃报告的错误报告,因为它是私有的,所以我无法在源代码中跟踪它gms.maps.model.Marker.setIcon
,所以我正在寻求解决这个问题的一些帮助。
问题的以下部分分为:
- 用户在做什么
- 什么firebase崩溃报告给我
- 一些项目配置
- 我尝试/发现试图理解/修复它
用户在做什么
他正在放大和缩小地图(Fragment
使用com.google.android.gms.maps.SupportMapFragment
)
什么firebase崩溃报告给我
异常 java.lang.IllegalArgumentException:非托管描述符
com.google.maps.api.android.lib6.common.kb (:com.google.android.gms.DynamiteModulesB:162)
com.google.maps.api.android.lib6。 impl.oc (: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)
和:
一些项目配置
- 我正在使用自定义渲染 (
SucursalRender extends DefaultClusterRenderer<Sucursal>
) - 我正在用 Glide 下载 Marker 图标,就像我之前说的:
Glide.with(context).load(id).fitCenter().placeholder(R.drawable.ic_no_image).into(simpleTarget);
这simpleTarget
是我处理为 Glide 下载/缓存的图像的地方。我发布所有代码是simpleTarget
因为崩溃从那里开始:
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));
}
}
}
崩溃是在最后一行代码中引发的:markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(icon));
我尝试/发现试图理解/修复它
- 尝试在 4 个真实设备中重现该错误,但均未成功。
- 在网上搜索类似的错误或
gms.maps.model.Marker.setIcon
代码com.google.maps.api.android.lib6
- 试图理解 Android Studio 中给出的混淆代码
Marker.setIcon
我想我可以将代码包装在try-catch block
IllegalArgumentException: Unmanaged descriptor 中,以避免应用程序因为崩溃而关闭,但这只是一种解决方法。
更新 2
的代码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);
}
}
这ImageLoaderManager
只是 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);
}