title: How can my android app draw a line or tracks of my movements with gps on google map
body: <p>I'm developing an android app that can trace the users locations and movements, using GPS and draw and save a line or the tracks that can be sent to a receiver who can open and see the saved tracks on Google map. </p>
  
  <p>I already have a working code that can send the location but the receiver can only see the single position where the user sent from with a marker. </p>
  
  <p>But I want it to track the movement and send so that the receiver can see all the places the user went when the app was on.</p>
  
  <p>I would be really grateful if anyone can help me with this. </p>
  
  <p>This is the code, @Ranjith or if anyone can help me detect the problem here. My tracks/lines are still not drawing </p>
  
  <pre><code>import android.content.Intent;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.graphics.Paint;
  import android.graphics.Path;
  import android.graphics.Point;
  import android.location.Location;
  import android.location.LocationManager;
  import android.os.Bundle;
  import android.support.v4.app.FragmentActivity;
  import android.view.View;
  import android.widget.Button;
  import android.widget.TextView;
  import android.widget.Toast;
  
  import com.google.android.gms.common.ConnectionResult;
  import com.google.android.gms.common.api.GoogleApiClient;
  import com.google.android.gms.location.LocationListener;
  import com.google.android.gms.location.LocationRequest;
  import com.google.android.gms.location.LocationServices;
  import com.google.android.gms.maps.GoogleMap;
  import com.google.android.gms.maps.MapView;
  import com.google.android.gms.maps.OnMapReadyCallback;
  import com.google.android.gms.maps.Projection;
  import com.google.android.gms.maps.StreetViewPanorama;
  import com.google.android.gms.maps.SupportMapFragment;
  import com.google.android.gms.maps.model.LatLng;
  import com.google.android.gms.maps.model.MarkerOptions;
  import com.google.android.gms.maps.model.Polyline;
  import com.google.android.gms.maps.model.PolylineOptions;
  
  import java.text.DateFormat;
  import java.util.ArrayList;
  import java.util.Date;
  
  public class MapsActivity extends FragmentActivity implements
          GoogleApiClient.ConnectionCallbacks,
          GoogleApiClient.OnConnectionFailedListener,
          LocationListener,
          GoogleMap.OnMyLocationButtonClickListener,
          OnMapReadyCallback {
  
      /**
       * The desired interval for location updates. Inexact. Updates may be more or less frequent.
       */
      public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
  
      /**
       * The fastest rate for active location updates. Exact. Updates will never be more frequent
       * than this value.
       */
      public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
              UPDATE_INTERVAL_IN_MILLISECONDS / 2;
  
      // Keys for storing activity state in the Bundle.
      protected final static String REQUESTING_LOCATION_UPDATES_KEY = "requesting-location-updates-key";
      protected final static String LOCATION_KEY = "location-key";
      protected final static String LAST_UPDATED_TIME_STRING_KEY = "last-updated-time-string-key";
  
      private GoogleMap mMap; // Might be null if Google Play services APK is not available.
      private GoogleApiClient mGoogleApiClient;
      private Location mCurrentLocation;
  
      /**
       * Tracks the status of the location updates request. Value changes when the user presses the
       * Start Updates and Stop Updates buttons.
       */
      protected Boolean mRequestingLocationUpdates;
  
      protected Button mStartUpdatesButton;
      protected Button mStopUpdatesButton;
      protected Button mSendPositionButton;
      protected TextView mLastUpdateTimeTextView;
      protected TextView mLatitudeTextView;
      protected TextView mLongitudeTextView;
  
      /**
       * Stores parameters for requests to the FusedLocationProviderApi.
       */
      protected LocationRequest mLocationRequest;
  
      /**
       * Time when the location was updated represented as a String.
       */
      protected String mLastUpdateTime;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_maps);
  
          // Locate the UI widgets.
          mStartUpdatesButton = (Button) findViewById(R.id.start_updates_button);
          mStopUpdatesButton = (Button) findViewById(R.id.stop_updates_button);
          mSendPositionButton = (Button) findViewById(R.id.send_position_button);
          mLatitudeTextView = (TextView) findViewById(R.id.latitude_text);
          mLongitudeTextView = (TextView) findViewById(R.id.longitude_text);
          mLastUpdateTimeTextView = (TextView) findViewById(R.id.last_update_time_text);
  
          mRequestingLocationUpdates = false;
          mLastUpdateTime = "";
  
          SupportMapFragment mapFragment =
                  (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
          mapFragment.getMapAsync(this);
  
          mMap = mapFragment.getMap();
  
          // Update values using data stored in the Bundle.
          updateValuesFromBundle(savedInstanceState);
  
          mGoogleApiClient = new GoogleApiClient.Builder(this)
                  .addApi(LocationServices.API)
                  .addConnectionCallbacks(this)
                  .addOnConnectionFailedListener(this)
                  .build();
  
          createLocationRequest();
      }
  
      @Override
      protected void onResume() {
          super.onResume();
          mGoogleApiClient.connect();
      }
  
      @Override
      public void onPause() {
          super.onPause();
          mGoogleApiClient.disconnect();
      }
  
      @Override
      public void onMapReady(GoogleMap map) {
          map.setMyLocationEnabled(true);
          map.setOnMyLocationButtonClickListener(this);
      }
  
      /**
       * Implementation of {@link LocationListener}.
       */
      @Override
      public void onLocationChanged(Location location) {
  
          /**
  
          if (location.distanceTo(mCurrentLocation) &gt; 10)
              mMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(),
                      location.getLongitude())).title("Marker"));
  
          mCurrentLocation = location;
          mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
          updateUI();
          Toast.makeText(this, getResources().getString(R.string.location_updated_message),
                  Toast.LENGTH_SHORT).show();
           */
      }
  
      public void handleGetDirectionsResult(ArrayList&lt;LatLng&gt; directionPoints) {
          PolylineOptions rectLine = new PolylineOptions().width(15).color(Color.RED);
          Polyline routePolyline = null;
          for (int i = 0; i &lt; directionPoints.size(); i++) {
              rectLine.add(directionPoints.get(i));
          }
          if (routePolyline != null){
              routePolyline.remove();
          }
  
          routePolyline = mMap.addPolyline(rectLine);
      }
  
      @Override
      public void onConnected(Bundle connectionHint) {
          if (mCurrentLocation == null) {
              mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
              mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
          }
  
          updateUI();
      }
  
      @Override
      public void onConnectionSuspended(int cause) {
          // Do nothing
      }
  
      @Override
      public void onConnectionFailed(ConnectionResult result) {
          // Do nothing
      }
  
      @Override
      public boolean onMyLocationButtonClick() {
          Toast.makeText(this, mCurrentLocation.toString(), Toast.LENGTH_SHORT).show();
          // Return false so that we don't consume the event and the default behavior still occurs
          // (the camera animates to the user's current position).
          return false;
      }
  
      /**
       * Sets up the location request. Android has two location request settings:
       * {@code ACCESS_COARSE_LOCATION} and {@code ACCESS_FINE_LOCATION}. These settings control
       * the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
       * the AndroidManifest.xml.
       * &lt;p/&gt;
       * When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
       * interval (5 seconds), the Fused Location Provider API returns location updates that are
       * accurate to within a few feet.
       * &lt;p/&gt;
       * These settings are appropriate for mapping applications that show real-time location
       * updates.
       */
      protected void createLocationRequest() {
          mLocationRequest = new LocationRequest();
  
          // Sets the desired interval for active location updates. This interval is
          // inexact. You may not receive updates at all if no location sources are available, or
          // you may receive them slower than requested. You may also receive updates faster than
          // requested if other applications are requesting location at a faster interval.
          mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
  
          // Sets the fastest rate for active location updates. This interval is exact, and your
          // application will never receive updates faster than this value.
          mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
  
          mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
      }
  
      public void sendPositionButtonHandler(View view)
      {
          Intent sendIntent = new Intent();
          sendIntent.setAction(Intent.ACTION_SEND);
          sendIntent.putExtra(Intent.EXTRA_TEXT, "http://maps.google.com/?q=" +
                  mCurrentLocation.getLatitude() + "," + mCurrentLocation.getLongitude());
          sendIntent.setType("text/plain");
          startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
      }
  
      /**
       * Handles the Start Updates button and requests start of location updates. Does nothing if
       * updates have already been requested.
       */
      public void startUpdatesButtonHandler(View view) {
          if (!mRequestingLocationUpdates) {
              mRequestingLocationUpdates = true;
              setButtonsEnabledState();
              startLocationUpdates();
          }
      }
  
      /**
       * Handles the Stop Updates button, and requests removal of location updates. Does nothing if
       * updates were not previously requested.
       */
      public void stopUpdatesButtonHandler(View view) {
          if (mRequestingLocationUpdates) {
              mRequestingLocationUpdates = false;
              setButtonsEnabledState();
              stopLocationUpdates();
          }
      }
  
      /**
       * Ensures that only one button is enabled at any time. The Start Updates button is enabled
       * if the user is not requesting location updates. The Stop Updates button is enabled if the
       * user is requesting location updates.
       */
      private void setButtonsEnabledState() {
          if (mRequestingLocationUpdates) {
              mStartUpdatesButton.setEnabled(false);
              mStopUpdatesButton.setEnabled(true);
          } else {
              mStartUpdatesButton.setEnabled(true);
              mStopUpdatesButton.setEnabled(false);
          }
      }
  
      /**
       * Requests location updates from the FusedLocationApi.
       */
      protected void startLocationUpdates() {
          // The final argument to {@code requestLocationUpdates()} is a LocationListener
          // (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
          LocationServices.FusedLocationApi.requestLocationUpdates(
                  mGoogleApiClient, mLocationRequest, this);
      }
  
      /**
       * Removes location updates from the FusedLocationApi.
       */
      protected void stopLocationUpdates() {
          // It is a good practice to remove location requests when the activity is in a paused or
          // stopped state. Doing so helps battery performance and is especially
          // recommended in applications that request frequent location updates.
  
          // The final argument to {@code requestLocationUpdates()} is a LocationListener
          // (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
          LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
      }
  
      /**
       * Updates the latitude, the longitude, and the last location time in the UI.
       */
      private void updateUI() {
          if (mCurrentLocation != null) {
              mLatitudeTextView.setText(String.valueOf(mCurrentLocation.getLatitude()));
              mLongitudeTextView.setText(String.valueOf(mCurrentLocation.getLongitude()));
              mLastUpdateTimeTextView.setText(mLastUpdateTime);
              mMap.addMarker(new MarkerOptions().position(new LatLng(mCurrentLocation.getLatitude(),
                      mCurrentLocation.getLongitude())).title("Marker"));
          }
      }
  
      /**
       * Updates fields based on data stored in the bundle.
       *
       * @param savedInstanceState The activity state saved in the Bundle.
       */
      private void updateValuesFromBundle(Bundle savedInstanceState) {
          if (savedInstanceState != null) {
              // Update the value of mRequestingLocationUpdates from the Bundle, and make sure that
              // the Start Updates and Stop Updates buttons are correctly enabled or disabled.
              if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
                  mRequestingLocationUpdates = savedInstanceState.getBoolean(
                          REQUESTING_LOCATION_UPDATES_KEY);
                  setButtonsEnabledState();
              }
  
              // Update the value of mCurrentLocation from the Bundle and update the UI to show the
              // correct latitude and longitude.
              if (savedInstanceState.keySet().contains(LOCATION_KEY)) {
                  // Since LOCATION_KEY was found in the Bundle, we can be sure that mCurrentLocation
                  // is not null.
                  mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY);
              }
  
              // Update the value of mLastUpdateTime from the Bundle and update the UI.
              if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) {
                  mLastUpdateTime = savedInstanceState.getString(LAST_UPDATED_TIME_STRING_KEY);
              }
              updateUI();
          }
      }
  }
  </code></pre>