this may be dumb question but i couldn't find any solution with previous answer regarding this question now let me post my question i need to make ripple effect around circle image in google map marker , now let me post what i have tried so far:
#Override
public void onLocationChanged(final Location location) {
mLastLocation=location;
GradientDrawable d = new GradientDrawable();
d.setShape(GradientDrawable.OVAL);
d.setSize(500,500);
d.setColor(0x555751FF);
d.setStroke(5, Color.TRANSPARENT);
Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth()
, d.getIntrinsicHeight()
, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
d.draw(canvas);
final int radius = 100;
final GroundOverlay circle = mMap.addGroundOverlay(new GroundOverlayOptions()
.position(new LatLng(location.getLatitude(),location.getLongitude()), 2 * radius).image(BitmapDescriptorFactory.fromBitmap(createMarker(TrackingActivity.this,new LatLng(location.getLatitude(),location.getLongitude())))));
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.setIntValues(0, radius);
valueAnimator.setDuration(3000);
valueAnimator.setEvaluator(new IntEvaluator());
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float animatedFraction = valueAnimator.getAnimatedFraction();
circle.setTransparency(animatedFraction);
// circle.setDimensions(animatedFraction * radius * 2);
}
});
valueAnimator.start();
// mMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(),location.getLongitude())).icon(BitmapDescriptorFactory.fromBitmap(createMarker(this,new LatLng(location.getLatitude(),location.getLongitude())))));
closeDialog();
public Bitmap createMarker(Context context, LatLng point) {
int px = context.getResources().getDimensionPixelSize(R.dimen.map_marker_diameter);
View markerView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.circle_imgview, null);
markerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
markerView.layout(0, 0, px, px);
markerView.buildDrawingCache();
CircleImageView bedNumberTextView = markerView.findViewById(R.id.circleimg);
Bitmap mDotMarkerBitmap = Bitmap.createBitmap(px, px, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mDotMarkerBitmap);
Picasso.with(this).load("https://fww").into(bedNumberTextView);
markerView.draw(canvas);
return mDotMarkerBitmap;
}
}
The above code make my entire circle image ripple , but i only want to make ripple around my circle image how can i achieve this. Even i have tried using third party ripple animation and wrap my image inside that animation but it is not working to how can i achieve this friends. Thanks in advance!!
Try this Code. it's very easy to implement.
I hope this code help for you.
MapRipple.class
public class MapRipple {
private GoogleMap mGoogleMap;
private LatLng mLatLng, mPrevLatLng;
private BitmapDescriptor mBackgroundImageDescriptor;
private float mTransparency = 0.5f;
private volatile double mDistance = 100;
private int mNumberOfRipples = 1;
private int mFillColor = Color.TRANSPARENT;
private int mStrokeColor = Color.BLACK;
private int mStrokeWidth = 5;
private long mDurationBetweenTwoRipples = 1000;
private long mRippleDuration = 2000;
private ValueAnimator mAnimators[];
private Handler mHandlers[];
private GroundOverlay mGroundOverlays[];
private GradientDrawable mBackground;
private boolean isAnimationRunning = false;
public MapRipple(GoogleMap googleMap, LatLng latLng, Context context) {
mGoogleMap = googleMap;
mLatLng = latLng;
mPrevLatLng = latLng;
mBackground = (GradientDrawable) ContextCompat.getDrawable(context, R.drawable.map_background);
mAnimators = new ValueAnimator[4];
mHandlers = new Handler[4];
mGroundOverlays = new GroundOverlay[4];
}
public MapRipple withTransparency(float transparency) {
mTransparency = transparency;
return this;
}
public MapRipple withDistance(double distance) {
mDistance = distance;
return this;
}
public MapRipple withLatLng(LatLng latLng) {
mPrevLatLng = mLatLng;
mLatLng = latLng;
return this;
}
public MapRipple withNumberOfRipples(int numberOfRipples) {
if (numberOfRipples > 4 || numberOfRipples < 1) {
numberOfRipples = 4;
}
mNumberOfRipples = numberOfRipples;
return this;
}
public MapRipple withFillColor(int fillColor) {
mFillColor = fillColor;
return this;
}
public MapRipple withStrokeColor(int strokeColor) {
mStrokeColor = strokeColor;
return this;
}
#Deprecated
public void withStrokewidth(int strokeWidth) {
mStrokeWidth = strokeWidth;
}
public MapRipple withStrokeWidth(int strokeWidth) {
mStrokeWidth = strokeWidth;
return this;
}
public MapRipple withDurationBetweenTwoRipples(long durationBetweenTwoRipples) {
mDurationBetweenTwoRipples = durationBetweenTwoRipples;
return this;
}
public boolean isAnimationRunning() {
return isAnimationRunning;
}
public MapRipple withRippleDuration(long rippleDuration) {
mRippleDuration = rippleDuration;
return this;
}
private final Runnable mCircleOneRunnable = new Runnable() {
#Override
public void run() {
mGroundOverlays[0] = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
.position(mLatLng, (int) mDistance)
.transparency(mTransparency)
.image(mBackgroundImageDescriptor));
startAnimation(0);
}
};
private final Runnable mCircleTwoRunnable = new Runnable() {
#Override
public void run() {
mGroundOverlays[1] = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
.position(mLatLng, (int) mDistance)
.transparency(mTransparency)
.image(mBackgroundImageDescriptor));
startAnimation(1);
}
};
private final Runnable mCircleThreeRunnable = new Runnable() {
#Override
public void run() {
mGroundOverlays[2] = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
.position(mLatLng, (int) mDistance)
.transparency(mTransparency)
.image(mBackgroundImageDescriptor));
startAnimation(2);
}
};
private final Runnable mCircleFourRunnable = new Runnable() {
#Override
public void run() {
mGroundOverlays[3] = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
.position(mLatLng, (int) mDistance)
.transparency(mTransparency)
.image(mBackgroundImageDescriptor));
startAnimation(3);
}
};
private void startAnimation(final int numberOfRipple) {
ValueAnimator animator = ValueAnimator.ofInt(0, (int) mDistance);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setDuration(mRippleDuration);
animator.setEvaluator(new IntEvaluator());
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int animated = (int) valueAnimator.getAnimatedValue();
mGroundOverlays[numberOfRipple].setDimensions(animated);
if (mDistance - animated <= 10) {
if (mLatLng != mPrevLatLng) {
mGroundOverlays[numberOfRipple].setPosition(mLatLng);
}
}
}
});
animator.start();
mAnimators[numberOfRipple] = animator;
}
private void setDrawableAndBitmap() {
mBackground.setColor(mFillColor);
mBackground.setStroke(UiUtil.dpToPx(mStrokeWidth), mStrokeColor);
mBackgroundImageDescriptor = UiUtil.drawableToBitmapDescriptor(mBackground);
}
public void stopRippleMapAnimation() {
if (isAnimationRunning) {
try {
for (int i = 0; i < mNumberOfRipples; i++) {
if (i == 0) {
mHandlers[i].removeCallbacks(mCircleOneRunnable);
mAnimators[i].cancel();
mGroundOverlays[i].remove();
}
if (i == 1) {
mHandlers[i].removeCallbacks(mCircleTwoRunnable);
mAnimators[i].cancel();
mGroundOverlays[i].remove();
}
if (i == 2) {
mHandlers[i].removeCallbacks(mCircleThreeRunnable);
mAnimators[i].cancel();
mGroundOverlays[i].remove();
}
if (i == 3) {
mHandlers[i].removeCallbacks(mCircleFourRunnable);
mAnimators[i].cancel();
mGroundOverlays[i].remove();
}
}
} catch (Exception e) {
//no need to handle it
}
}
isAnimationRunning = false;
}
public void startRippleMapAnimation() {
if (!isAnimationRunning) {
setDrawableAndBitmap();
for (int i = 0; i < mNumberOfRipples; i++) {
if (i == 0) {
mHandlers[i] = new Handler();
mHandlers[i].postDelayed(mCircleOneRunnable, mDurationBetweenTwoRipples * i);
}
if (i == 1) {
mHandlers[i] = new Handler();
mHandlers[i].postDelayed(mCircleTwoRunnable, mDurationBetweenTwoRipples * i);
}
if (i == 2) {
mHandlers[i] = new Handler();
mHandlers[i].postDelayed(mCircleThreeRunnable, mDurationBetweenTwoRipples * i);
}
if (i == 3) {
mHandlers[i] = new Handler();
mHandlers[i].postDelayed(mCircleFourRunnable, mDurationBetweenTwoRipples * i);
}
}
}
isAnimationRunning = true;
}
}
R.drawable.map_background
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="150dp"
android:height="150dp" />
<stroke
android:width="0.5dp"
android:color="#000000" />
</shape>
PolyUtil.class
public class PolyUtil {
private PolyUtil() {}
private static double tanLatGC(double lat1, double lat2, double lng2, double lng3) {
return (tan(lat1) * sin(lng2 - lng3) + tan(lat2) * sin(lng3)) / sin(lng2);
}
private static double mercatorLatRhumb(double lat1, double lat2, double lng2, double lng3) {
return (mercator(lat1) * (lng2 - lng3) + mercator(lat2) * lng3) / lng2;
}
private static boolean intersects(double lat1, double lat2, double lng2,
double lat3, double lng3, boolean geodesic) {
// Both ends on the same side of lng3.
if ((lng3 >= 0 && lng3 >= lng2) || (lng3 < 0 && lng3 < lng2)) {
return false;
}
// Point is South Pole.
if (lat3 <= -PI/2) {
return false;
}
// Any segment end is a pole.
if (lat1 <= -PI/2 || lat2 <= -PI/2 || lat1 >= PI/2 || lat2 >= PI/2) {
return false;
}
if (lng2 <= -PI) {
return false;
}
double linearLat = (lat1 * (lng2 - lng3) + lat2 * lng3) / lng2;
// Northern hemisphere and point under lat-lng line.
if (lat1 >= 0 && lat2 >= 0 && lat3 < linearLat) {
return false;
}
// Southern hemisphere and point above lat-lng line.
if (lat1 <= 0 && lat2 <= 0 && lat3 >= linearLat) {
return true;
}
// North Pole.
if (lat3 >= PI/2) {
return true;
}
return geodesic ?
tan(lat3) >= tanLatGC(lat1, lat2, lng2, lng3) :
mercator(lat3) >= mercatorLatRhumb(lat1, lat2, lng2, lng3);
}
public static boolean containsLocation(LatLng point, List<LatLng> polygon, boolean geodesic) {
return containsLocation(point.latitude, point.longitude, polygon, geodesic);
}
public static boolean containsLocation(double latitude, double longitude, List<LatLng> polygon, boolean geodesic) {
final int size = polygon.size();
if (size == 0) {
return false;
}
double lat3 = toRadians(latitude);
double lng3 = toRadians(longitude);
LatLng prev = polygon.get(size - 1);
double lat1 = toRadians(prev.latitude);
double lng1 = toRadians(prev.longitude);
int nIntersect = 0;
for (LatLng point2 : polygon) {
double dLng3 = wrap(lng3 - lng1, -PI, PI);
// Special case: point equal to vertex is inside.
if (lat3 == lat1 && dLng3 == 0) {
return true;
}
double lat2 = toRadians(point2.latitude);
double lng2 = toRadians(point2.longitude);
// Offset longitudes by -lng1.
if (intersects(lat1, lat2, wrap(lng2 - lng1, -PI, PI), lat3, dLng3, geodesic)) {
++nIntersect;
}
lat1 = lat2;
lng1 = lng2;
}
return (nIntersect & 1) != 0;
}
private static final double DEFAULT_TOLERANCE = 0.1; // meters.
public static boolean isLocationOnEdge(LatLng point, List<LatLng> polygon, boolean geodesic,
double tolerance) {
return isLocationOnEdgeOrPath(point, polygon, true, geodesic, tolerance);
}
public static boolean isLocationOnEdge(LatLng point, List<LatLng> polygon, boolean geodesic) {
return isLocationOnEdge(point, polygon, geodesic, DEFAULT_TOLERANCE);
}
public static boolean isLocationOnPath(LatLng point, List<LatLng> polyline,
boolean geodesic, double tolerance) {
return isLocationOnEdgeOrPath(point, polyline, false, geodesic, tolerance);
}
public static boolean isLocationOnPath(LatLng point, List<LatLng> polyline,
boolean geodesic) {
return isLocationOnPath(point, polyline, geodesic, DEFAULT_TOLERANCE);
}
private static boolean isLocationOnEdgeOrPath(LatLng point, List<LatLng> poly, boolean closed,
boolean geodesic, double toleranceEarth) {
int idx = locationIndexOnEdgeOrPath(point, poly, closed, geodesic, toleranceEarth);
return (idx >= 0);
}
public static int locationIndexOnPath(LatLng point, List<LatLng> poly,
boolean geodesic, double tolerance) {
return locationIndexOnEdgeOrPath(point, poly, false, geodesic, tolerance);
}
public static int locationIndexOnPath(LatLng point, List<LatLng> polyline,
boolean geodesic) {
return locationIndexOnPath(point, polyline, geodesic, DEFAULT_TOLERANCE);
}
private static int locationIndexOnEdgeOrPath(LatLng point, List<LatLng> poly, boolean closed,
boolean geodesic, double toleranceEarth) {
int size = poly.size();
if (size == 0) {
return -1;
}
double tolerance = toleranceEarth / EARTH_RADIUS;
double havTolerance = hav(tolerance);
double lat3 = toRadians(point.latitude);
double lng3 = toRadians(point.longitude);
LatLng prev = poly.get(closed ? size - 1 : 0);
double lat1 = toRadians(prev.latitude);
double lng1 = toRadians(prev.longitude);
int idx = 0;
if (geodesic) {
for (LatLng point2 : poly) {
double lat2 = toRadians(point2.latitude);
double lng2 = toRadians(point2.longitude);
if (isOnSegmentGC(lat1, lng1, lat2, lng2, lat3, lng3, havTolerance)) {
return Math.max(0, idx - 1);
}
lat1 = lat2;
lng1 = lng2;
idx++;
}
} else {
double minAcceptable = lat3 - tolerance;
double maxAcceptable = lat3 + tolerance;
double y1 = mercator(lat1);
double y3 = mercator(lat3);
double[] xTry = new double[3];
for (LatLng point2 : poly) {
double lat2 = toRadians(point2.latitude);
double y2 = mercator(lat2);
double lng2 = toRadians(point2.longitude);
if (max(lat1, lat2) >= minAcceptable && min(lat1, lat2) <= maxAcceptable) {
// We offset longitudes by -lng1; the implicit x1 is 0.
double x2 = wrap(lng2 - lng1, -PI, PI);
double x3Base = wrap(lng3 - lng1, -PI, PI);
xTry[0] = x3Base;
// Also explore wrapping of x3Base around the world in both directions.
xTry[1] = x3Base + 2 * PI;
xTry[2] = x3Base - 2 * PI;
for (double x3 : xTry) {
double dy = y2 - y1;
double len2 = x2 * x2 + dy * dy;
double t = len2 <= 0 ? 0 : clamp((x3 * x2 + (y3 - y1) * dy) / len2, 0, 1);
double xClosest = t * x2;
double yClosest = y1 + t * dy;
double latClosest = inverseMercator(yClosest);
double havDist = havDistance(lat3, latClosest, x3 - xClosest);
if (havDist < havTolerance) {
return Math.max(0, idx - 1);
}
}
}
lat1 = lat2;
lng1 = lng2;
y1 = y2;
idx++;
}
}
return -1;
}
private static double sinDeltaBearing(double lat1, double lng1, double lat2, double lng2,
double lat3, double lng3) {
double sinLat1 = sin(lat1);
double cosLat2 = cos(lat2);
double cosLat3 = cos(lat3);
double lat31 = lat3 - lat1;
double lng31 = lng3 - lng1;
double lat21 = lat2 - lat1;
double lng21 = lng2 - lng1;
double a = sin(lng31) * cosLat3;
double c = sin(lng21) * cosLat2;
double b = sin(lat31) + 2 * sinLat1 * cosLat3 * hav(lng31);
double d = sin(lat21) + 2 * sinLat1 * cosLat2 * hav(lng21);
double denom = (a * a + b * b) * (c * c + d * d);
return denom <= 0 ? 1 : (a * d - b * c) / sqrt(denom);
}
private static boolean isOnSegmentGC(double lat1, double lng1, double lat2, double lng2,
double lat3, double lng3, double havTolerance) {
double havDist13 = havDistance(lat1, lat3, lng1 - lng3);
if (havDist13 <= havTolerance) {
return true;
}
double havDist23 = havDistance(lat2, lat3, lng2 - lng3);
if (havDist23 <= havTolerance) {
return true;
}
double sinBearing = sinDeltaBearing(lat1, lng1, lat2, lng2, lat3, lng3);
double sinDist13 = sinFromHav(havDist13);
double havCrossTrack = havFromSin(sinDist13 * sinBearing);
if (havCrossTrack > havTolerance) {
return false;
}
double havDist12 = havDistance(lat1, lat2, lng1 - lng2);
double term = havDist12 + havCrossTrack * (1 - 2 * havDist12);
if (havDist13 > term || havDist23 > term) {
return false;
}
if (havDist12 < 0.74) {
return true;
}
double cosCrossTrack = 1 - 2 * havCrossTrack;
double havAlongTrack13 = (havDist13 - havCrossTrack) / cosCrossTrack;
double havAlongTrack23 = (havDist23 - havCrossTrack) / cosCrossTrack;
double sinSumAlongTrack = sinSumFromHav(havAlongTrack13, havAlongTrack23);
return sinSumAlongTrack > 0; // Compare with half-circle == PI using sign of sin().
}
public static List<LatLng> simplify(List<LatLng> poly, double tolerance) {
final int n = poly.size();
if (n < 1) {
throw new IllegalArgumentException("Polyline must have at least 1 point");
}
if (tolerance <= 0) {
throw new IllegalArgumentException("Tolerance must be greater than zero");
}
boolean closedPolygon = isClosedPolygon(poly);
LatLng lastPoint = null;
if (closedPolygon) {
final double OFFSET = 0.00000000001;
lastPoint = poly.get(poly.size() - 1);
poly.remove(poly.size() - 1);
poly.add(new LatLng(lastPoint.latitude + OFFSET, lastPoint.longitude + OFFSET));
}
int idx;
int maxIdx = 0;
Stack<int[]> stack = new Stack<>();
double[] dists = new double[n];
dists[0] = 1;
dists[n - 1] = 1;
double maxDist;
double dist = 0.0;
int[] current;
if (n > 2) {
int[] stackVal = new int[]{0, (n - 1)};
stack.push(stackVal);
while (stack.size() > 0) {
current = stack.pop();
maxDist = 0;
for (idx = current[0] + 1; idx < current[1]; ++idx) {
dist = distanceToLine(poly.get(idx), poly.get(current[0]),
poly.get(current[1]));
if (dist > maxDist) {
maxDist = dist;
maxIdx = idx;
}
}
if (maxDist > tolerance) {
dists[maxIdx] = maxDist;
int[] stackValCurMax = {current[0], maxIdx};
stack.push(stackValCurMax);
int[] stackValMaxCur = {maxIdx, current[1]};
stack.push(stackValMaxCur);
}
}
}
if (closedPolygon) {
poly.remove(poly.size() - 1);
poly.add(lastPoint);
}
idx = 0;
ArrayList<LatLng> simplifiedLine = new ArrayList<>();
for (LatLng l : poly) {
if (dists[idx] != 0) {
simplifiedLine.add(l);
}
idx++;
}
return simplifiedLine;
}
public static boolean isClosedPolygon(List<LatLng> poly) {
LatLng firstPoint = poly.get(0);
LatLng lastPoint = poly.get(poly.size()-1);
return firstPoint.equals(lastPoint);
}
public static double distanceToLine(final LatLng p, final LatLng start, final LatLng end) {
if (start.equals(end)) {
return computeDistanceBetween(end, p);
}
final double s0lat = toRadians(p.latitude);
final double s0lng = toRadians(p.longitude);
final double s1lat = toRadians(start.latitude);
final double s1lng = toRadians(start.longitude);
final double s2lat = toRadians(end.latitude);
final double s2lng = toRadians(end.longitude);
double s2s1lat = s2lat - s1lat;
double s2s1lng = s2lng - s1lng;
final double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng)
/ (s2s1lat * s2s1lat + s2s1lng * s2s1lng);
if (u <= 0) {
return computeDistanceBetween(p, start);
}
if (u >= 1) {
return computeDistanceBetween(p, end);
}
LatLng sa = new LatLng(p.latitude - start.latitude, p.longitude - start.longitude);
LatLng sb = new LatLng(u * (end.latitude - start.latitude), u * (end.longitude - start.longitude));
return computeDistanceBetween(sa, sb);
}
public static List<LatLng> decode(final String encodedPath) {
int len = encodedPath.length();
final List<LatLng> path = new ArrayList<LatLng>();
int index = 0;
int lat = 0;
int lng = 0;
while (index < len) {
int result = 1;
int shift = 0;
int b;
do {
b = encodedPath.charAt(index++) - 63 - 1;
result += b << shift;
shift += 5;
} while (b >= 0x1f);
lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
result = 1;
shift = 0;
do {
b = encodedPath.charAt(index++) - 63 - 1;
result += b << shift;
shift += 5;
} while (b >= 0x1f);
lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
path.add(new LatLng(lat * 1e-5, lng * 1e-5));
}
return path;
}
public static String encode(final List<LatLng> path) {
long lastLat = 0;
long lastLng = 0;
final StringBuffer result = new StringBuffer();
for (final LatLng point : path) {
long lat = Math.round(point.latitude * 1e5);
long lng = Math.round(point.longitude * 1e5);
long dLat = lat - lastLat;
long dLng = lng - lastLng;
encode(dLat, result);
encode(dLng, result);
lastLat = lat;
lastLng = lng;
}
return result.toString();
}
private static void encode(long v, StringBuffer result) {
v = v < 0 ? ~(v << 1) : v << 1;
while (v >= 0x20) {
result.append(Character.toChars((int) ((0x20 | (v & 0x1f)) + 63)));
v >>= 5;
}
result.append(Character.toChars((int) (v + 63)));
}
}
Google Map Activity
MapRipple mapRipple = new MapRipple(mGoogleMap, new LatLng(gpsTracker.getLatitude(), gpsTracker.getLongitude()), this);
mapRipple.stopRippleMapAnimation();
mapRipple.withNumberOfRipples(3);
mapRipple.withFillColor(Color.parseColor("#FFA3D2E4"));
mapRipple.withStrokeColor(Color.BLACK);
mapRipple.withStrokewidth(0);
mapRipple.withDistance(2000);
mapRipple.withRippleDuration(12000);
mapRipple.withDurationBetweenTwoRipples(1000);
mapRipple.withTransparency(0.5f);
mapRipple.startRippleMapAnimation();
Custom Marker pin
mGoogleMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromBitmap(YourMarkerPinBitmap))
.anchor(0.5f, 0.6f)
.position(new LatLng(gpsTracker.getLatitude(), gpsTracker.getLongitude())));
Location Change
if (mapRipple != null && mapRipple.isAnimationRunning())
mapRipple.withLatLng(new LatLng(lati, longi));
I am working on a project in which I am showing two random location and the path between them.I have used this tutorial to accomplish.
Now i want to show the moving image from one location to another.I have already put markers on that two locations.and also I have saved the position in an arraylist.
I had found some similar posts but couldn't solve my issue.
Here is my code for moving the drawable:
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
final Handler handler = new Handler();
int i = 0;
#Override
public boolean onMarkerClick(Marker marker) {
// System.out.println("Marker size:- " + MarkerPoints.size());
handler.post(new Runnable() {
#Override
public void run() {
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.truck_16);
while (i < MarkerPoints.size()) {
MarkerOptions markerOptions = new MarkerOptions().position(MarkerPoints.get(i))
.title("Current Location")
icon(icon);
System.out.println(MarkerPoints.get(i));
mMap.addMarker(markerOptions);
i++;
handler.postDelayed(this, 3000);
}
}
});
return true;
}
});
private double bearingBetweenLocations(LatLng latLng1, LatLng latLng2) {
final double PI = 3.14159;
final double lat1 = latLng1.latitude * PI / 180;
final double long1 = latLng1.longitude * PI / 180;
final double lat2 = latLng2.latitude * PI / 180;
final double long2 = latLng2.longitude * PI / 180;
final double dLon = (long2 - long1);
final double y = Math.sin(dLon) * Math.cos(lat2);
final double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
return brng;
}
Suppose you have current and destination co-ordinates like below.
private LatLng CURRENT_LOC = new LatLng(23.013171, 72.522300);
private LatLng DESTINATION_LOC = new LatLng(23.013481, 72.522496);
After that add marker on google map
if (googleMap != null)
{
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.truck_16);
MarkerOptions current = new MarkerOptions().position(CURRENT_LOC).title("Current Point");
current_marker = googleMap.addMarker(current);
current_marker.setIcon(icon);
current_marker.setFlat(true);
MarkerOptions destination = new MarkerOptions().position(DESTINATION_LOC).title("Destination Point");
destination_marker = googleMap.addMarker(destination);
destination_marker.setFlat(true);
}
And move marker on click
#Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.btn_move:
float rotate = (float) bearingBetweenLocations(CURRENT_LOC, DESTINATION_LOC);
rotateMarker(rotate);
break;
}
}
below all are methods that move marker from current location to destnation
private double bearingBetweenLocations(LatLng latLng1,LatLng latLng2)
{
double PI = 3.14159;
double lat1 = latLng1.latitude * PI / 180;
double long1 = latLng1.longitude * PI / 180;
double lat2 = latLng2.latitude * PI / 180;
double long2 = latLng2.longitude * PI / 180;
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
return brng;
}
public void rotateMarker(float rotate)
{
if (current_marker != null)
{
//final LatLngInterpolator latLngInterpolator = new LatLngInterpolator.LinearFixed();
ValueAnimator valueAnimator = new ValueAnimator();
//final LatLng startPosition = current_marker.getPosition();
final float startRotation = current_marker.getRotation();
final float angle = 180 - Math.abs(Math.abs(startRotation - rotate) - 180);
final float right = WhichWayToTurn(startRotation, rotate);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
#Override
public void onAnimationUpdate(ValueAnimator animation)
{
try
{
if (current_marker == null) // oops... destroying map during animation...
{
return;
}
float v = animation.getAnimatedFraction();
//newPosition = latLngInterpolator.interpolate(v, startPosition, toLatLng(location));
float rotation = startRotation + right * v * angle;
current_marker.setRotation(rotation);
//current_marker.setPosition(newPosition);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
});
valueAnimator.addListener(new AnimatorListenerAdapter()
{
#Override
public void onAnimationEnd(Animator animation)
{
//current_marker.setPosition(newPosition);
animateMarker(current_marker, DESTINATION_LOC, false);
}
});
valueAnimator.setFloatValues(0, 1);
valueAnimator.setDuration(1000);
valueAnimator.start();
}
}
public void animateMarker(final Marker marker, final LatLng toPosition, final boolean hideMarker)
{
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = googleMap.getProjection();
Point startPoint = proj.toScreenLocation(marker.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 5000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
double lng = t * toPosition.longitude + (1 - t) * startLatLng.longitude;
double lat = t * toPosition.latitude + (1 - t) * startLatLng.latitude;
marker.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
marker.setVisible(false);
} else {
marker.setVisible(true);
}
}
}
});
}
private float WhichWayToTurn(float currentDirection, float targetDirection)
{
float diff = targetDirection - currentDirection;
if (Math.abs(diff) == 0)
{
return 0;
}
if(diff > 180)
{
return -1;
}
else
{
return 1;
}
}
Hope this would help you.
Finally I found a way to accomplish this.May be this is not the best way but it solves the problem.I am posting this so in future if someone needs to do stuff like that,It can be helpful.
I have store all the points in an ArrayList called MarkerPoints that we get from the API and use it to draw the image on ever point.
Here is the code:
public class MyActivity extends FragmentActivity implements Runnable
{
private Thread thread = null;
volatile boolean isRunning;
private ArrayList<LatLng> MarkerPoints; //This arrayList contains all points that are on the route
int i = 0;
Marker marker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_on_trip_maps);
isRunning = true;
}
#Override
public void run() {
while (isRunning) {
runOnUiThread(new Runnable() {
#Override
public void run() {
update();
}
});
control();
}
}
public void update() {
if (marker != null) {
marker.remove();
}
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.truck_16);
marker = mMap.addMarker(new MarkerOptions().position(MarkerPoints.get(i))
.title("Current Location")
.icon(icon));
System.out.println(MarkerPoints.get(i));
i++;
if (i > MarkerPoints.size() - 1) {
isRunning = false;
}
}
public void control() {
try {
thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
This will give the moving effect.
I am using a plasio turbo x to test my osmdroid sample. I am also testing using a moto g. In moto g the map rotation which is according to the compass head up is working fine, but in plasio one the compass starts to spin and map also spins, they don't get stable. You can see the logcat here(it is very big, stackoverflow not letting me add it here).
Following is my class in which I have used compass:
public class MainActivity extends FragmentActivity implements LocationListener, IOrientationConsumer,MapEventsReceiver {
private CompassOverlay mCompassOverlay = null;
private MyLocationNewOverlay mLocationOverlay;
IOrientationProvider compass = null;
int deviceOrientation = 0;
MapView mMapView;
float gpsspeed;
float gpsbearing;
float lat = 0;
float lon = 0;
float alt = 0;
long timeOfFix = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
final double lat1 = Double.parseDouble(intent.getStringExtra("lat1"));
final double long1 = Double.parseDouble(intent.getStringExtra("long1"));
final double lat2 = 25.633;
final double long2 = 71.094;
//important! set your user agent to prevent getting banned from the osm servers
org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants.setUserAgentValue(BuildConfig.APPLICATION_ID);
mMapView = (MapView) findViewById(R.id.map);
mMapView.setTileSource(TileSourceFactory.MAPNIK);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
mCompassOverlay = new CompassOverlay(this, new InternalCompassOrientationProvider(this),
mMapView);
mCompassOverlay.enableCompass();
mMapView.getOverlays().add(this.mCompassOverlay);
addOverlays();
GeoPoint startPoint = new GeoPoint(lat1, long1);
IMapController mapController = mMapView.getController();
mapController.setZoom(9);
mapController.setCenter(startPoint);
Marker startMarker = new Marker(mMapView);
startMarker.setPosition(startPoint);
startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
mMapView.getOverlays().add(startMarker);
RoadManager roadManager = new OSRMRoadManager(this);
ArrayList<GeoPoint> waypoints = new ArrayList<GeoPoint>();
waypoints.add(startPoint);
GeoPoint endPoint = new GeoPoint(lat2, long2);
Marker endMarker = new Marker(mMapView);
endMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
mMapView.getOverlays().add(endMarker);
waypoints.add(endPoint);
Road road = roadManager.getRoad(waypoints);
Polyline roadOverlay = RoadManager.buildRoadOverlay(road);
mMapView.getOverlays().add(roadOverlay);
mMapView.invalidate();
}
public void addOverlays() {
mLocationOverlay = new MyLocationNewOverlay(mMapView);
mLocationOverlay.setEnableAutoStop(false);
mLocationOverlay.enableFollowLocation();
mLocationOverlay.enableMyLocation();
this.mMapView.getOverlayManager().add(mLocationOverlay);
mMapView.setBuiltInZoomControls(true);
mMapView.setMultiTouchControls(true);
mMapView.setTilesScaledToDpi(true);
}
#Override
protected void onResume() {
super.onResume();
//lock the device in current screen orientation
int orientation;
int rotation = ((WindowManager) this.getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
this.deviceOrientation = 0;
break;
case Surface.ROTATION_90:
this.deviceOrientation = 90;
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
this.deviceOrientation = 180;
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
default:
this.deviceOrientation = 270;
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
}
this.setRequestedOrientation(orientation);
LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, (LocationListener) this);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, (LocationListener) this);
} catch (Exception ex) {
}
compass = new InternalCompassOrientationProvider(this);
compass.startOrientationProvider(this);
mMapView.getController().zoomTo(14);
}
#Override
public void onLocationChanged(Location location) {
if (mMapView == null)
return;
//after the first fix, schedule the task to change the icon
//mMapView.getController().setCenter(new GeoPoint(location.getLatitude(), location.getLongitude()));
mMapView.invalidate();
gpsbearing = location.getBearing();
gpsspeed = location.getSpeed();
lat = (float) location.getLatitude();
lon = (float) location.getLongitude();
alt = (float) location.getAltitude(); //meters
timeOfFix = location.getTime();
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
#Override
protected void onPause() {
super.onPause();
compass.stopOrientationProvider();
LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
lm.removeUpdates(this);
} catch (Exception ex) {
}
//unlock the orientation
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
Float trueNorth = 0f;
#Override
public void onOrientationChanged(final float orientationToMagneticNorth, IOrientationProvider source) {
GeomagneticField gf = new GeomagneticField(lat, lon, alt, timeOfFix);
trueNorth = orientationToMagneticNorth + gf.getDeclination();
gf=null;
synchronized (trueNorth) {
if (trueNorth > 360.0f) {
trueNorth = trueNorth - 360.0f;
}
//use gps bearing instead of the compass
if (gpsspeed > 0.01f) {
float t = (360 - gpsbearing - this.deviceOrientation);
if (t < 0) {
t += 360;
}
if (t > 360) {
t -= 360;
}
mMapView.setMapOrientation(t);
} else {
//this part adjusts the desired map rotation based on device orientation and compass heading
float t = (360 - trueNorth - this.deviceOrientation);
if (t < 0) {
t += 360;
}
if (t > 360) {
t -= 360;
}
mMapView.setMapOrientation(t);
}
this.runOnUiThread(new Runnable() {
#Override
public void run() {
if (this!=null ) {
Toast.makeText(MainActivity.this, "GPS Speed: " + gpsspeed + "m/s GPS Bearing: " + gpsbearing +
"\nDevice Orientation: " + (int) deviceOrientation + " Compass heading: " + (int) orientationToMagneticNorth + "\n" +
"True north: " + trueNorth.intValue() + " Map Orientation: " + (int) mMapView.getMapOrientation() + "\n", Toast.LENGTH_SHORT).show();
}
}
});
}
}
#Override
public boolean singleTapConfirmedHelper(GeoPoint geoPoint) {
return false;
}
#Override
public boolean longPressHelper(GeoPoint geoPoint) {
return false;
}
}
I am developing an android app which will track the current location latitude and longitude and store in external database.Here i am having a list of latitudes and longitudes.I populated them by using the custom adapter . But,Here i need the distance from one base latitude and base longitude to remaining items latitude and longitude.Here the base latitude and longitude was selected by the user it self.Here the below the list explains like this i have
SELECTION LAT LONG DISTANCE
-------------------------------------------------
checkbox1 123.4546 456.48751 Text
checkbox2 123.4546 456.48751 Text
checkbox3 123.4546 456.48751 Text
checkbox4 123.4546 456.48751 Text
If user selects the check-box 1 then i have to find the distance from check-box 1 lat long to check-box 2,check-box 3,check-box-4 lat long in KILOMETERS and display in their respected position .
This is some code from adapter i had written but it was not showing any results.
public class Locations_Adapter extends BaseAdapter {
public String distance_string;
Context context;
List<Locations_modle> objects;
double distance, latitude, longitude;
String latitude_string, longitude_string;
double baseLat, baseLong, finalLat, finalLong;
Location location_pointa, location_pointb;
TextView distance_text;
float[] results;
int selectedPostion = -1;
public Locations_Adapter(Context context, int resource, List<Locations_modle> objects) {
this.context = context;
this.objects = objects;
}
/**
* Distance calculation between two lat longs
**/
private static double calculateDistance(double baseLat, double baseLong, double latitude, double longitude, String unit) {
double theta = baseLong - longitude;
double dist = Math.sin(deg2rad(baseLat)) * Math.sin(deg2rad(latitude)) + Math.cos(deg2rad(baseLat)) * Math.cos(deg2rad(longitude)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == "K") {
dist = dist * 1.609344;
} else if (unit == "N") {
dist = dist * 0.8684;
}
return (dist);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts decimal degrees to radians :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private static double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts radians to decimal degrees :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private static double rad2deg(double rad) {
return (rad * 180 / Math.PI);
}
#Override
public int getCount() {
return objects.size();
}
#Override
public Object getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
final View locations_row = LayoutInflater.from(context).inflate(R.layout.layout_adapter_list_details, null);
final Locations_modle location = (Locations_modle) objects.get(position);
TextView text_cust_name = (TextView) locations_row.findViewById(R.id.txt_cust_name_heading);
TextView latitude = (TextView) locations_row.findViewById(R.id.txt_latitude);
latitude.setText(location.getLatitude());
TextView longitude = (TextView) locations_row.findViewById(R.id.txt_longitude);
distance_text = (TextView) locations_row.findViewById(R.id.txt_distance);
longitude.setText(location.getLongitude());
text_cust_name.setText(location.getLocationName());
CheckBox check_locations = (CheckBox) locations_row.findViewById(R.id.check_locations);
final Location location_point_a = new Location("Source");
final Location location_point_b = new Location("Destination");
location_point_a.setLatitude(Double.parseDouble(location.getLatitude()));
location_point_a.setLongitude(Double.parseDouble(location.getLongitude()));
if (position == selectedPostion) {
check_locations.setChecked(true);
} else {
check_locations.setChecked(false);
}
check_locations.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// selectedPostion = position;
latitude_string = location.getLatitude();
longitude_string = location.getLongitude();
baseLat = Double.parseDouble(latitude_string);
baseLong = Double.parseDouble(longitude_string);
for (int i = 0; i < objects.size(); i++) {
finalLat = Double.parseDouble(objects.get(i).getLatitude());
finalLong = Double.parseDouble(objects.get(i).getLongitude());
calculateDistance(baseLat, baseLong, finalLat, finalLong, "k");
}
distance_text.setText(Double.toString(calculateDistance(baseLat, baseLong, finalLat, finalLong, "k")));
} /*else {
selectedPostion = -1;
}
notifyDataSetChanged();
*/
}
});
return locations_row;
}
}
Can any one tell how to achieve this
You can try this:
public static Double distanceBetween(LatLng point1, LatLng point2)
{
if (point1 == null || point2 == null) {
return null;
}
else{
return SphericalUtil.computeDistanceBetween(point1, point2);
}
}
You can try this
public float distance (float lat_a, float lng_a, float lat_b, float lng_b )
{
double earthRadius = 3958.75;
double latDiff = Math.toRadians(lat_b-lat_a);
double lngDiff = Math.toRadians(lng_b-lng_a);
double a = Math.sin(latDiff /2) * Math.sin(latDiff /2) +
Math.cos(Math.toRadians(lat_a)) * Math.cos(Math.toRadians(lat_b)) *
Math.sin(lngDiff /2) * Math.sin(lngDiff /2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double distance = earthRadius * c;
int meterConversion = 1609;
return new Float(distance * meterConversion).floatValue();
}
Use this method:
public static double haversineDistance(double lat1, double lng1, double lat2, double lng2) {
final int R = 6371; // Radious of the earth
double latDistance = toRad(lat2-lat1);
double lonDistance = toRad(lng2-lng1);
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double distance = R * c;
distance = distance * 1000 * 0.000621371; // DISTANCE IN MILES
return (distance / 0.62137); // CONVERT MILES TO KM
}
public static double toRad(double value) {
return value * Math.PI / 180;
}
You can try this:
Location loc = new Location("");
Location p = new Location("");
loc.setLatitude(locLat);
loc.setLongitude(locLon);
p.setLatitude(pLat);
p.setLongitude(pLon);
double dis = loc.distanceTo(p);
String.format("%.2f", dis * 0.001);
In loc you set your location
You can use internal Api to find distance between 2 latlng
public double getDistanceBetweenPoints(LatLng origin, LatLng dest, String unit) {
Location selected_location = new Location("Start");
selected_location.setLatitude(origin.latitude);
selected_location.setLongitude(origin.longitude);
Location near_locations = new Location("End");
near_locations.setLatitude(dest.latitude);
near_locations.setLongitude(dest.longitude);
//in meters
double dist = selected_location.distanceTo(near_locations);
if (unit.equals("K")) {
dist = dist * 1.609344;
} else if (unit.equals("N")) {
dist = dist * 0.8684;
}
return dist;
}
I've recently been working on simple speed calculations for an application I'm working on, but the code I have takes far too long to retrieve the location, and I know that questions like this have been asked before, but none of the answers seem to retrieve the results I'm looking for. So, how can I make this code have gps fixes within a matter of seconds, and is it even possible?
My LocationListener:
package me.dylan.acf;
import java.text.DecimalFormat;
import java.util.ArrayList;
import android.app.NotificationManager;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.text.format.Time;
import android.widget.TextView;
public class GPSManager implements LocationListener {
ArrayList<Double> avgspeeds = new ArrayList<Double>();
TextView debug;
NotificationManager mngr;
double avgspeed;
long lastTime = 0;
GraphView view;
Location lastloc;
int earthRadius = 6371;
long delaytime = 30;
ArrayList<Double> allspeeds = new ArrayList<Double>();
public GPSManager(TextView view) {
debug = view;
Location location = ACF.instance.lmanager
.getLastKnownLocation(ACF.instance
.getProperLocationsServices(ACF.instance
.getApplicationContext()));
if (location != null) {
double speed = location.getSpeed();
lastloc = location;
debug.setText("Average Speed: " + avgspeed + "\nCurrent speed: "
+ speed + "\nLocation updates: " + avgspeeds.size());
}
}
#Override
public void onLocationChanged(Location location) {
// DecimalFormat format = new DecimalFormat("0.00");
double speed = location.getSpeed();
if (lastloc != null) {
double latDist = Math.toRadians(location.getLatitude()
- lastloc.getLatitude());
double lonDist = Math.toRadians(location.getLongitude()
- lastloc.getLongitude());
double lat1 = Math.toRadians(location.getLatitude());
double lat2 = Math.toRadians(lastloc.getLatitude());
double a = Math.sin(latDist / 2) * Math.sin(latDist / 2)
+ Math.sin(lonDist / 2) * Math.sin(lonDist / 2)
* Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
speed = (dist * 0.621371) / Math.abs(System.currentTimeMillis() - lastTime * 60 * 60 * 60);
lastTime = System.currentTimeMillis();
}
allspeeds.add(speed);
if (allspeeds.size() > 30) {
allspeeds.remove(0);
}
avgspeed = 0;
for (double d : allspeeds) {
avgspeed += d;
}
avgspeed /= allspeeds.size();
// avgspeed = Double.parseDouble(format.format(avgspeed));
avgspeeds.add(avgspeed);
lastloc = location;
debug.setText("Average Speed: " + avgspeed + "\nCurrent speed: "
+ speed + "\nLocation updates: " + avgspeeds.size());
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
Where I call it:
public void updateWithProperService() {
lmanager.requestSingleUpdate(
getProperLocationsServices(getApplicationContext()), GPSmngr,
null);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
updateWithProperService();
}
}, 10000);
}
public String getProperLocationsServices(Context context) {
if (lmanager == null)
lmanager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
int minTime = 3000;
/*
* boolean isGPS = false; boolean isNetwork = false; try { isGPS =
* lmanager.isProviderEnabled(LocationManager.GPS_PROVIDER); } catch
* (Exception e) { e.printStackTrace(); } try { isNetwork = lmanager
* .isProviderEnabled(LocationManager.NETWORK_PROVIDER); } catch
* (Exception e) { e.printStackTrace(); }
*/
List<String> matchingProviders = lmanager.getAllProviders();
Location bestResult = null;
long bestTime = 0;
for (String provider : matchingProviders) {
Location location = lmanager.getLastKnownLocation(provider);
if (location != null) {
// float accuracy = location.getAccuracy();
long time = location.getTime();
// float bestAccuracy;
/*
* if ((time > minTime && accuracy < bestAccuracy )) {
* bestResult = location; bestTime = time; } else
*/if (time < minTime &&
/* bestAccuracy == Float.MAX_VALUE && */time < bestTime) {
bestResult = location;
bestTime = time;
}
}
}
if (bestResult != null)
return bestResult.getProvider();
else
return LocationManager.NETWORK_PROVIDER;
}
google has released a nice API on their recent Google IO 2013 event:
https://developers.google.com/events/io/sessions/324498944
you should check it out and see how you can minimize your code.
do note that it requires that the device would have the play store app for this to work.
this method has many advantages over using the normal location sensors (battery, speed , accuracy,...) .
gps needs about 15 seconds if it was disabled before and when using Assisted GPS.
you cannot improve that.
Whitout AGPS it needs 25-35 seconds, under good conditions.
The term is called "Time to First fix" (TTF).