63

I am working on a project similar to UBER, Lyft or OLA ie. Map on the home with available moving Cars. I'm looking for some kind of Library which can make Cars move and take turn smoothly just like UBER. For now I was able to move car smoothly from one lat-long to another with the below code. But tricky part is Taking turn and make sure the car face to front when moving to direction.

Smooth Moving Car Code:

    final LatLng SomePos = new LatLng(12.7796354, 77.4159606);

    try {
        if (googleMap == null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
            }
        }
        googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        googleMap.setMyLocationEnabled(true);
        googleMap.setTrafficEnabled(false);
        googleMap.setIndoorEnabled(false);
        googleMap.setBuildingsEnabled(true);
        googleMap.getUiSettings().setZoomControlsEnabled(true);
        googleMap.moveCamera(CameraUpdateFactory.newLatLng(SomePos));
        googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
                .target(googleMap.getCameraPosition().target)
                .zoom(17)
                .bearing(30)
                .tilt(45)
                .build()));

        myMarker = googleMap.addMarker(new MarkerOptions()
                .position(SomePos)
                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher))
                .title("Hello world"));


        googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker arg0) {

                final LatLng startPosition = myMarker.getPosition();
                final LatLng finalPosition = new LatLng(12.7801569, 77.4148528);
                final Handler handler = new Handler();
                final long start = SystemClock.uptimeMillis();
                final Interpolator interpolator = new AccelerateDecelerateInterpolator();
                final float durationInMs = 3000;
                final boolean hideMarker = false;

                handler.post(new Runnable() {
                    long elapsed;
                    float t;
                    float v;

                    @Override
                    public void run() {
                        // Calculate progress using interpolator
                        elapsed = SystemClock.uptimeMillis() - start;
                        t = elapsed / durationInMs;

                        LatLng currentPosition = new LatLng(
                                startPosition.latitude * (1 - t) + finalPosition.latitude * t,
                                startPosition.longitude * (1 - t) + finalPosition.longitude * t);

                        myMarker.setPosition(currentPosition);

                        // Repeat till progress is complete.
                        if (t < 1) {
                            // Post again 16ms later.
                            handler.postDelayed(this, 16);
                        } else {
                            if (hideMarker) {
                                myMarker.setVisible(false);
                            } else {
                                myMarker.setVisible(true);
                            }
                        }
                    }
                });

                return true;

            }

        });

    } catch (Exception e) {
        e.printStackTrace();
    }
VipiN Negi
  • 2,994
  • 3
  • 24
  • 47

6 Answers6

60

I recently came across the same use-case. Here is my solution on it.

First, I would like to thank @VipiN for sharing "The Smooth Moving Car Code". It works smoothly.

The second part is to place car-marker in the right direction and rotate it according to turns. To achieve this I calculated the bearing or heading angle between two successive points(i.e. location updates you receive from device/server). This link will help you understand the maths behind it.

The following code will give you bearing between two locations:

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

Finally, we need to rotate the car-marker by the angle that we get from above method.

private void rotateMarker(final Marker marker, final float toRotation) {
    if(!isMarkerRotating) {
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        final float startRotation = marker.getRotation();
        final long duration = 1000;

        final Interpolator interpolator = new LinearInterpolator();

        handler.post(new Runnable() {
            @Override
            public void run() {
                isMarkerRotating = true;

                long elapsed = SystemClock.uptimeMillis() - start;
                float t = interpolator.getInterpolation((float) elapsed / duration);

                float rot = t * toRotation + (1 - t) * startRotation;

                marker.setRotation(-rot > 180 ? rot / 2 : rot);
                if (t < 1.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                } else {
                    isMarkerRotating = false;
                }
            }
        });
    }
}

Cheers!

Prasad
  • 616
  • 7
  • 6
20

Here is my code to move marker like uber. i have shown two ways to move marker .

Important Note: To move car on proper road [like ola,uber] you need to use road api provided by google

1.By static latitude and longitude

2.By Real time Latitude and longitude

package com.gangsofcoder.googlemapdemo;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

import cz.msebera.android.httpclient.Header;

public class MoveCar extends AppCompatActivity {
    private GoogleMap googleMap;
    SupportMapFragment mapFragment;
    Marker marker;
    private boolean isMarkerRotating = false;
    ArrayList<LatLng> listOfPoints = new ArrayList<>();
    int currentPt = 0;
    LatLng finalPosition;
    Marker mMarker;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    setUpMapIfNeeded();
    //new location details
    listOfPoints.add(new LatLng(30.701623, 76.684220));
    listOfPoints.add(new LatLng(30.702486, 76.685487));
    listOfPoints.add(new LatLng(30.703135, 76.684891));
    listOfPoints.add(new LatLng(30.703256, 76.685000));
    listOfPoints.add(new LatLng(30.703883, 76.685941));
    listOfPoints.add(new LatLng(30.703413, 76.685190));
}

private void setUpMapIfNeeded() {
    if (mapFragment == null) {
        mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

        if (mapFragment != null) {
            mapFragment.getMapAsync(new OnMapReadyCallback() {
                @Override
                public void onMapReady(GoogleMap googleMap) {
                    loadMap(googleMap);
                }
            });
        }
    }
}

private void loadMap(GoogleMap map) {
    googleMap = map;

    mMarker = googleMap.addMarker(new MarkerOptions().position(new LatLng(30.701623, 76.684220)).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_car)));      


    final Handler handler = new Handler();
    //Code to move car along static latitude and longitude

  /*  handler.postDelayed(new Runnable() {
        @Override
        public void run() {

            if (currentPt < listOfPoints.size()) {
                //post again
                Log.d("tess", "inside run ");
                Location targetLocation = new Location(LocationManager.GPS_PROVIDER);
                targetLocation.setLatitude(listOfPoints.get(currentPt).latitude);
                targetLocation.setLongitude(listOfPoints.get(currentPt).longitude);
                animateMarkerNew(targetLocation, mMarker);
                handler.postDelayed(this, 3000);
                currentPt++;
            } else {
                Log.d("tess", "call back removed");
                //removed callbacks
                handler.removeCallbacks(this);
            }
        }
    }, 3000);*/

    //Here move marker along real time updates
    final RequestParams params = new RequestParams();
    params.put("source_lattitude", "lat");
    params.put("source_longitude", "long");
    params.put("date", "date");

    //new handler
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {

            LoopjHttpClient.post(getString(R.string.default_upload_website), params, new AsyncHttpResponseHandler() {
                @Override
                public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {

                    try {
                        JSONObject jsonObject = new JSONObject(new String(responseBody));
                        String status = jsonObject.getString("status");
                        String text = jsonObject.getString("text");
                        //reading json array
                        JSONArray jsonArray = jsonObject.getJSONArray("result");
                        String source = jsonArray.getJSONObject(0).getString("source");

                        String[] latLong = source.split(",");
                        Location location = new Location(LocationManager.GPS_PROVIDER);
                        location.setLatitude(Double.parseDouble(latLong[0]));
                        location.setLongitude(Double.parseDouble(latLong[1]));
                        //calling method to animate marker  
                        animateMarkerNew(location, mMarker);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                    Log.d("onFailure", "onFailure");
                }
            });

            handler.postDelayed(this, 3000);
        }
    }, 3000);

}

private void animateMarkerNew(final Location destination, final Marker marker) {

    if (marker != null) {

                final LatLng startPosition = marker.getPosition();
                final LatLng endPosition = new LatLng(destination.getLatitude(), destination.getLongitude());

                final float startRotation = marker.getRotation();
                final LatLngInterpolatorNew latLngInterpolator = new LatLngInterpolatorNew.LinearFixed();

                ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
                valueAnimator.setDuration(3000); // duration 3 second
                valueAnimator.setInterpolator(new LinearInterpolator());
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        try {
                            float v = animation.getAnimatedFraction();
                            LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, endPosition);
                            marker.setPosition(newPosition);
                            googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
                                    .target(newPosition)
                                    .zoom(15.5f)
                                    .build()));

                            marker.setRotation(getBearing(startPosition, new LatLng(destination.getLatitude(), destination.getLongitude())));
                        } catch (Exception ex) {
                            //I don't care atm..
                        }
                    }
                });
                valueAnimator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);

                        // if (mMarker != null) {
                            // mMarker.remove();
                        // }
                        // mMarker = googleMap.addMarker(new MarkerOptions().position(endPosition).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_car)));

                    }
                });
                valueAnimator.start();
    }
}

private interface LatLngInterpolatorNew {
    LatLng interpolate(float fraction, LatLng a, LatLng b);

    class LinearFixed implements LatLngInterpolatorNew {
        @Override
        public LatLng interpolate(float fraction, LatLng a, LatLng b) {
            double lat = (b.latitude - a.latitude) * fraction + a.latitude;
            double lngDelta = b.longitude - a.longitude;
            // Take the shortest path across the 180th meridian.
            if (Math.abs(lngDelta) > 180) {
                lngDelta -= Math.signum(lngDelta) * 360;
            }
            double lng = lngDelta * fraction + a.longitude;
            return new LatLng(lat, lng);
        }
    }
}


//Method for finding bearing between two points
private float getBearing(LatLng begin, LatLng end) {
    double lat = Math.abs(begin.latitude - end.latitude);
    double lng = Math.abs(begin.longitude - end.longitude);

    if (begin.latitude < end.latitude && begin.longitude < end.longitude)
        return (float) (Math.toDegrees(Math.atan(lng / lat)));
    else if (begin.latitude >= end.latitude && begin.longitude < end.longitude)
        return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 90);
    else if (begin.latitude >= end.latitude && begin.longitude >= end.longitude)
        return (float) (Math.toDegrees(Math.atan(lng / lat)) + 180);
    else if (begin.latitude < end.latitude && begin.longitude >= end.longitude)
        return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 270);
    return -1;
}
}
IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
Suraj Bahadur
  • 3,730
  • 3
  • 27
  • 55
  • how to do with real time locations – M.Yogeshwaran Sep 04 '18 at 12:50
  • 2
    I'm using google snap to road api and you can check this out here https://developers.google.com/maps/documentation/roads/snap – Suraj Bahadur Sep 07 '18 at 16:59
  • @SurajBahadur What is the difference between float rot = t * toRotation + (1 - t) * startRotation; marker.setRotation(-rot > 180 ? rot / 2 : rot); or marker.setRotation(toRotation); for Rotation – Ketan Ramani Nov 15 '18 at 05:09
  • I have given marker image but onAnimationUpdate it removed my map pin and I am using direction API and once I get my location I pass to API and receive my new path like uber and Ola – Riddhi Shah Mar 04 '19 at 07:36
  • destination marker is not visible after adding animation. – Ashish Patel Jul 22 '19 at 13:05
12

Since its been bit confusing for SO users to look for working code in two different posts. Here is the working code for Rotate and Move Marker which seamlessly worked for me.

in MainActivity.java

public void rotateMarker(final Marker marker, final float toRotation, final float st) {
    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    final float startRotation = st;
    final long duration = 1555;

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

            float rot = t * toRotation + (1 - t) * startRotation;

            marker.setRotation(-rot > 180 ? rot / 2 : rot);
            if (t < 1.0) {
                // Post again 16ms later.
                handler.postDelayed(this, 16);
            }
        }
    });
}


public void animateMarker(final LatLng toPosition,final boolean hideMarke) {
    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    Projection proj = googleMap.getProjection();
    Point startPoint = proj.toScreenLocation(m.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;
            m.setPosition(new LatLng(lat, lng));

            if (t < 1.0) {
                // Post again 16ms later.
                handler.postDelayed(this, 16);
            } else {
                if (hideMarke) {
                    m.setVisible(false);
                } else {
                    m.setVisible(true);
                }
            }
        }
    });
}
VipiN Negi
  • 2,994
  • 3
  • 24
  • 47
  • 1
    Thanks vipin for posting a code. I am still confused when you call all this methods and how you use them. – Nishant Rajput Sep 19 '16 at 10:56
  • i used it and i am able to move the marker but it doesnt move from one location to other using the path on map. – Nishant Rajput Sep 19 '16 at 11:25
  • The marker is suppose to move from one latlong to another. It will never follow the map path, because method doesn't know the map. You'll need to feed the destination latlong in regular interval of time (eg. 5-7sec). So practically a car will be moving on the correct path of the map, You need to fetch the latlong every 5sec from the car to the method to display the movement. – VipiN Negi Sep 19 '16 at 12:31
  • 3
    can you please elaborate on when did you call rotateMarker method and its parameters – jnapor Sep 30 '16 at 11:09
  • 1
    @jnapor did you find it? How to use rotate marker method? – Vilas Dec 11 '16 at 09:15
  • @EagleEye since I am making live map like Uber or OLA, I am calling it in every 10-15 seconds interval of time. – VipiN Negi Dec 12 '16 at 12:35
  • 1
    @VipinNegi, That's fine after 5 sec are you calling both animateMarker and rotateMarker methods? Or Can I cann rotateMarker inside animateMarker, Please tell briefly or can you place your interval code also? – Naveen Kumar M Feb 08 '17 at 11:55
  • 1
    and what is the parameters of `final float toRotation, final float st` How to get these parameters? – Naveen Kumar M Feb 08 '17 at 12:38
  • 1
    what is the parameters of final float toRotation, final float st How to get these parameters? – Nilesh Mar 10 '17 at 14:31
  • @NaveenKumarM : The parameters for 'st' and 'to' are the bearing values coming from GPS on Cab-driver's phone using json api. I am passing the values to customer side app. – VipiN Negi Mar 27 '17 at 14:45
  • Hi @VipiNNegi , how to calculate st and to in client site? – Suman Aug 22 '17 at 06:52
  • @Suman, well that's the whole idea of the approach. st and to are sent by the DriverApp to the UserApp every time interval. for eg. Driver position is A (lat & lon) is the 'to' for user app, and next new location from driver is B, now the A becomes the 'st' and B becomes 'to', similarly next time B becomes 'st' and C becomes 'to'. – VipiN Negi Aug 31 '17 at 08:08
  • @VipiNNegi, rotateMarker(final Marker marker, final float toRotation, final float st) in this function you are passing 2nd and 3 rd argument float. As per you ,2nd and 3 rd argument location type .then how to make location to float type? – Suman Sep 01 '17 at 09:53
  • @Suman, rotateMarker() is about rotating the car icon to the direction of the cab. For this the arguments will be fetched from 'bearing' of the DriverApp, which will return the values in float type. Bearing is nothing but the degree(180°) value of direction. – VipiN Negi Sep 01 '17 at 10:21
  • @Suman, for rotateMarker() I would recommend to follow the Prasad's answer, as mine is bit confusing. – VipiN Negi Sep 01 '17 at 10:28
  • @VipiNNegi, Thank you for your's recommendation. Prasad's answer is working? or if you have anything please share . – Suman Sep 01 '17 at 10:33
  • m.getPosition() what is "m" here?/ – nilesh prajapati Jan 17 '18 at 05:52
  • thanks for your quick reply have u solve this problem ? my marker/car is not moving right way it jump from one location two another location and every time it change location marker is set as default potion and rotate can u provide me source code for it? @VipiNNegi – nilesh prajapati Jan 17 '18 at 10:30
  • Above two methods rotateMarker (to rotate the car) & animateMarker (to move car from one location to another) is enough to make this functionality working. Many people were able to solve it from here. I'm sure you will too. – VipiN Negi Jan 17 '18 at 12:03
  • @VipiNNegi What is the difference between float rot = t * toRotation + (1 - t) * startRotation; marker.setRotation(-rot > 180 ? rot / 2 : rot); or marker.setRotation(toRotation); for Rotation – Ketan Ramani Nov 15 '18 at 05:07
  • @VipiNNegi when to call rotateMarker – Girish Jul 18 '19 at 13:02
4

Finally wrote the code that works exactly in the similar manner that OLA CABS does...

Here it is -

  1. Put your google maps fragment in a Relative layout and put the marker(as image view ) in the center -

  2. In your fragment's code once you have setup all the google maps basic working write the following code for the onMapReady(GoogleMap googleMap) function-

My Code is as follows -

//Step 1 -

 <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">



<fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MapsActivity_for_request_pages" />

    <ImageView
        android:layout_width="30sp"
        android:layout_height="30sp"
        android:layout_centerInParent="true"
        android:id="@+id/central_marker"
        android:src="@drawable/marker_pic"/>

</RelativeLayout>

//Step 2 -

@Override
public void onMapReady(GoogleMap googleMap) {


     central_marker = (ImageView)v.findViewById(R.id.central_marker);
     int init_loc = 0,final_loc = -300;
     mMap = googleMap;

 final  CountDownTimer timer = new CountDownTimer(300,300) {
       @Override
       public void onTick(long millisUntilFinished) {

       }

       @Override
       public void onFinish() {
           init_loc = 0;
           ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(central_marker, "translationY", final_loc, init_loc);
           objectAnimatorY.setDuration(200);
           objectAnimatorY.start();
       }
   };


    mMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
        @Override
        public void onCameraMoveStarted(int i) {

            System.out.println("Camera started moving worked");
            timer.cancel();
            ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(central_marker, "translationY", init_loc, final_loc);
            objectAnimatorY.setDuration(200);
            objectAnimatorY.start();
            init_loc = -300;

        }
    });



    mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
        @Override
        public void onCameraIdle() {
            System.out.println("Camera idle worked");
            if(initial_flag!=0)
            {
                System.out.println("Camera Setting timer now");
                timer.cancel();
                timer.start();
            }
            initial_flag++;
            System.out.println("Camera Value of initial_flag ="+initial_flag);
        }
    });

}
Shubham Arora
  • 807
  • 9
  • 10
1

Firstly,I would like to thank you both @Vipin Negi & @Prasad for such a good & awesomely working code.Since there are many pending queries above, I want to make all the above stuff a little simpler. Guys, just follow the following steps to achieve the marker rotation.

1. Define below two methods in your MainActivity.java file

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

&

private void rotateMarker(final Marker marker, final float toRotation) {
    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    final float startRotation = marker.getRotation();
    final long duration = 1000;

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

            float rot = t * toRotation + (1 - t) * startRotation;

            marker.setRotation(-rot > 180 ? rot / 2 : rot);
            if (t < 1.0) {
                // Post again 16ms later.
                handler.postDelayed(this, 16);
            }
        }
    });

}

2. After this, add the following lines to the code where you want your marker to rotate.

double bearing = bearingBetweenLocations(m.getPosition(), updatedLatLng);
rotateMarker(m, (float) bearing);

Note that "m" is your marker object that you want to rotate. And, you're done!!!

If you want marker animation related help,you can use this code.

Anshuman Parashar
  • 107
  • 1
  • 1
  • 10
0

Try google default rotation or see the detail explanation Markers Rotation

 private void updateCamera(LatLng currentLatLng, Location location) {
    //googleMap.clear();
    if (marker == null) {
        MarkerOptions options = new MarkerOptions();
        options.position(currentLatLng);
        options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_driver_car_pin_v));
        options.flat(true);
        options.anchor(0.5f, 0.5f);
        marker = googleMap.addMarker(options);
    } else {
        marker.setPosition(currentLatLng);
        marker.setRotation(location.getBearing());
    }
    CameraPosition cameraPosition = new CameraPosition.Builder(googleMap.getCameraPosition())
            .target(currentLatLng).zoom(18).build();
    googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
Mujahid Khan
  • 1,712
  • 1
  • 18
  • 24