How to smoothly move and rotate a marker in google map

Posted By : Akash Tomer | 26-Dec-2017

This tutorial basically deals with the smooth movement and rotation of marker in google map. Lot's  of developers face problem when they develop shuttle type of application where they have to show the live tracking of the vehicle . Even when I develop such type of app, I also face this problem. So this tutorial will definitely help you to overcome this problem. First of all, you should have the good knowledge of google map and Fused location provider API. In this tutorial, I will on discuss only about the fused location API .

What is fused location provider api . 

Basically if we want to fetch the location of any android user we explicitly choose either GPS or Network Location Provider .But this api automatically switches itself to provide the best possible location of android user either through GPS or Network Location Provider.The main benefit of this provider it utilizes low power and provides high accuracy of over other options. 

Gradle

Add this dependecy in your build gradle .

com.google.android.gms:play-services-location:11.8.0

Android Manifest 

To access location we have to request access fine location and access coarse location in your android manifest file .

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

GoogleApiClient

It requries the google api client object . So we have to instantiate the object

googleApiClient = new GoogleApiClient.Builder(locationActivity)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

Instialization of this object should be done in onCreate() methode of activity. When the google api client get connected it's onConnected method will called and when the connection is break it's on disconnected method is called . When the google api onConnected() method is called we have to register location listener . Below there is a complete code of location tracking . 

public class LocationActivity extends BaseActivity implements LocationListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener, Constants, OnUpdateResponse {
    private static final int REQUEST_CHECK_SETTINGS = 25;
    private  boolean PRE_ALERT_FLAG =true ;
    private GoogleMap mMap;
    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private Location mCurrentLocation;
    private static final String TAG = "MapsActivity";
    private static final long INTERVAL = 1;
    private static final long FASTEST_INTERVAL = 1;
 
   protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
         createLocationRequest();
                 mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        }

  
    
    @Override
    public void onStart() {
        super.onStart();
        Log.e(TAG, "onStart fired ..............");
        mGoogleApiClient.connect();
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.e(TAG, "onStop fired ..............");

    }


  

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.e(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
        startLocationUpdates();

    }

    protected void startLocationUpdates() {

        PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);
        Log.e(TAG, "Location update started ..............: ");
    }

    @Override
    public void onConnectionSuspended(int i) {
        if (i == 1) {
            mGoogleApiClient.connect();
        }

    }

    @Override
    public void onLocationChanged(Location location) {
        //Toast.makeText(HopOffActivity.this,"Firing onLocationChanged", 

        moveVechile(currentMArkerPos, location);
        rotateMarker(currentMArkerPos, location.getBearing(), start_rotation);

    }

  
    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        mGoogleApiClient.connect();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "On Pause call...............................");

    }

    protected void stopLocationUpdates() {

        LocationServices.FusedLocationApi.removeLocationUpdates(
                mGoogleApiClient, this);
        Log.e(TAG, "Location update stopped .......................");
    }

    @Override
    public void onResume() {
        super.onResume();

        manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

 

        if (mGoogleApiClient.isConnected()) {
            startLocationUpdates();
        }

    }


    public void moveVechile(final Marker myMarker, final Location finalPosition) {

        final LatLng startPosition = myMarker.getPosition();

        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;
                v = interpolator.getInterpolation(t);

                LatLng currentPosition = new LatLng(
                        startPosition.latitude * (1 - t) + (finalPosition.getLatitude()) * t,
                        startPosition.longitude * (1 - t) + (finalPosition.getLongitude()) * t);
                myMarker.setPosition(currentPosition);
                // myMarker.setRotation(finalPosition.getBearing());


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


    }


    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);
                start_rotation = -rot > 180 ? rot / 2 : rot;
                if (t < 1.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                }
            }
        });
    }

    public void makeMarker(int color, String title, LatLng latLng) {

        mMap.addMarker(new MarkerOptions()
                .icon((BitmapDescriptorFactory
                        .fromResource(color)))
                .title(title)
                .position(latLng));

    }

}

In onlcationchange() method you have to provide the marker position. For this you have to ovveride the onMapReady() method of google map api and create the instances. There is a method makeMarker() you just need to call from onMapReady() method . There is two method rotateMarker() and moveVechile() to rotate and move marker.

Hope this will help you.

About Author

Author Image
Akash Tomer

Akash is an Android Developer at Oodles Technology.

Request for Proposal

Name is required

Comment is required

Sending message..