Mig*_*ieC 47 android google-maps android-maps-utils android-glide
我有一个使用android-maps-utils和滑动标记图标的应用程序.
我收到了使用Firebase崩溃报告的错误报告,我无法在源代码中跟踪,因为它gms.maps.model.Marker.setIcon是私有的,所以我要求帮助解决这个问题.
问题的以下部分分为:
用户正在做什么
他在地图中放大和缩小(Fragment使用com.google.android.gms.maps.SupportMapFragment)
火灾基地崩溃向我报告了什么
异常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.g lide.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.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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
该碰撞被抛出的代码最后一行:markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(icon));
我尝试/发现试图理解/修复它
gms.maps.model.Marker.setIcon或的代码com.google.maps.api.android.lib6Marker.setIcon我想我可以将代码包装在一个try-catch blockfor IllegalArgumentException:非托管描述符中,以避免应用程序因为崩溃而关闭,但它只是解决它.
更新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);
}
}
Run Code Online (Sandbox Code Playgroud)
这ImageLoaderManager只是一个滑翔门面.
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);
}
Run Code Online (Sandbox Code Playgroud)
Mor*_*goo 16
用清除地图时
googleMap.clear();
Run Code Online (Sandbox Code Playgroud)
**remove any reference to all the markers**在地图上.我有问题,并发现问题是我的代码,我忘了删除引用标记,并试图更改图标cleared Marker
Sou*_*rma 13
我也得到了相同的异常并且使用try/catch设置静默异常不会是解决方案,因为用户无法在我的情况下看到当前位置:
java.lang.IllegalArgumentException:com.google.maps.api.api.andi.lib6上com.google.maps.api.android.lib6.common.kb(:com.google.android.gms.DynamiteModulesB:162)中的非托管描述符com.google.maps.api.android.lib6.impl.db.a上的.impl.oc(:com.google.android.gms.DynamiteModulesB:75)(:com.google.android.gms.DynamiteModulesB:334) com.google.android.gms.maps.model.internal.q.onTransact(:com.google.android.gms.DynamiteModulesB:204)at com的android.os.Binder.transact(Binder.java:361). com.google.android.gms.maps.model.Marker.setIcon上的google.android.gms.maps.model.internal.zzf $ zza $ zza.zzL(未知来源)(未知来源)
我在做什么:
通过按主页按钮然后从启动器启动应用程序来最小化地图片段屏幕.
代码在做什么:
检查标记不为空,位置不是空设置位置和图标.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
例外是:markerCurrentLocation.setIcon();
我如何摆脱这个例外:
我删除了以下行
if (markerCurrentLocation == null && googleMap != null)
Run Code Online (Sandbox Code Playgroud)
这意味着我再次初始化标记.如果遇到此错误,请尝试不要在旧标记上设置Icon(),而是膨胀新标记然后使用setIcon().
说明:
我ASSUME(不确定)异常原因是,如果代码在已经设置的标记上再次尝试setIcon(),在特殊情况下就像在我的情况下Map正在恢复或者可能在你的情况下标记出来的可见部分地图和进来或类似的东西.
我们从方法BitmapDescriptorFactory.fromBitmap()或BitmapDescriptorFactory.fromResource()得到的描述符没有问题.作为异常提示,描述符在旧标记上不受管理,更好地使用新标记.
Sta*_*hin 12
我在移除标记后访问标记时发现了这种情况.在回调中与标记进行交互就是这种情况.如Map的API中所述:
删除标记后,其所有方法的行为都是未定义的. https://developers.google.com/android/reference/com/google/android/gms/maps/model/Marker.html#remove()
最好的选择是检查标记是否从地图中删除.
但是我们没有这样的API.我找到了另一种解决方法,我们可以使用Marker setTag和getTag.删除标记时,标记设置为null:
Google Maps Android API既不会读取也不会写入此属性,除非从地图中删除标记时,此属性设置为null. https://developers.google.com/android/reference/com/google/android/gms/maps/model/Marker.html#setTag(java.lang.Object)
创建标记时使用一些标记.
更新标记检查标记时不为空.
这可能对您的情况有所帮助.
@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);
}
Run Code Online (Sandbox Code Playgroud)
并在回调中
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));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
当您的标记由 重新聚集时,会发生此异常ClusterManager。ClusterManager在聚类上重新创建标记。因此,为了避免它,您必须从渲染中获取标记ClusterManeger:
ClusterIconRender render = (ClusterIconRender) mClusterManager.getRenderer();
Marker trueMarker = render.getMarker(clusterMarker);
if (trueMarker != null) {
trueMarker.setIcon(...);
... // do whatever else your want with marker
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中ClusterMarker实现ClusterItem和ClusterIconRender扩展DefaultClusterRenderer。
| 归档时间: |
|
| 查看次数: |
10773 次 |
| 最近记录: |