I found a solution to add pulsating animation to the marker. Here is a part of the map. Here the variable "map" denotes your map.
private Circle lastUserCircle; private long pulseDuration = 1000; private ValueAnimator lastPulseAnimator; private void addPulsatingEffect(Latlng userLatlng){ if(lastPulseAnimator != null){ lastPulseAnimator.cancel(); Log.d("onLocationUpdated: ","cancelled" ); } if(lastUserCircle != null) lastUserCircle.setCenter(userLatlng); lastPulseAnimator = valueAnimate(userLocation.getAccuracy(), pulseDuration, new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { if(lastUserCircle != null) lastUserCircle.setRadius((Float) animation.getAnimatedValue()); else { lastUserCircle = map.addCircle(new CircleOptions() .center(userLatlng) .radius((Float) animation.getAnimatedValue()) .strokeColor(Color.RED) .fillColor(Color.BLUE)); } } }); } protected ValueAnimator valueAnimate(float accuracy,long duration, ValueAnimator.AnimatorUpdateListener updateListener){ Log.d( "valueAnimate: ", "called"); ValueAnimator va = ValueAnimator.ofFloat(0,accuracy); va.setDuration(duration); va.addUpdateListener(updateListener); va.setRepeatCount(ValueAnimator.INFINITE); va.setRepeatMode(ValueAnimator.RESTART); va.start(); return va; }
You should call this on location updates by adding a PositionChangedListener. You can easily find this in google maps docs. After that, for each update call, the above method is used.
Fixing the radius of the pulse to a certain equal value, so that it is not too large and not too small
Write this method
protected float getDisplayPulseRadius(float radius) { float diff = (map.getMaxZoomLevel() - map.getCameraPosition().zoom); if (diff < 3) return radius; if (diff < 3.7) return radius * (diff / 2); if (diff < 4.5) return (radius * diff); if (diff < 5.5) return (radius * diff) * 1.5f; if (diff < 7) return (radius * diff) * 2f; if (diff < 7.8) return (radius * diff) * 3.5f; if (diff < 8.5) return (float) (radius * diff) * 5; if (diff < 10) return (radius * diff) * 10f; if (diff < 12) return (radius * diff) * 18f; if (diff < 13) return (radius * diff) * 28f; if (diff < 16) return (radius * diff) * 40f; if (diff < 18) return (radius * diff) * 60; return (radius * diff) * 80; }
And change this line
userLocation.getAccuracy()
to
getDisplayPulseRadius(userLocation.getAccuracy()
As well as
.radius((Float) animation.getAnimatedValue())
to
.radius(getDisplayPulseRadius((Float) animation.getAnimatedValue()))
If you want a color-like effect to become transparent when it gets big, you can only use it in the next line, where you set the radius inside the animator
circle.setFillColor(adjustAlpha(pulseAroundMeFillColor, 1 - animation.getAnimatedFraction())); private int adjustAlpha(int color, float factor) { int alpha = Math.round(Color.alpha(color) * factor); int red = Color.red(color); int green = Color.green(color); int blue = Color.blue(color); return Color.argb(alpha, red, green, blue); }