0

J'ai une certaine expérience avec Android, mais je suis nouveau à l'utilisation de l'API Google Maps et des services de localisation. J'essaie de montrer le mouvement de l'utilisateur sur un MapFragment en déplaçant le tracker et en dessinant un Polyline là où l'utilisateur a été, un peu comme MapMyRun. D'après ce que j'ai vu sur mon débogueur, j'obtiens un emplacement après la reprise du Fragment, et il est ajouté à la liste des LatLngs. Ce dont j'ai besoin, c'est que la carte soit mise à jour toutes les quelques secondes, ou chaque fois que l'emplacement change d'un dixième de mile environ.Suivre l'emplacement de l'utilisateur en temps réel à l'aide de polylignes dans Google Maps (Android)

Voici ce que j'ai pour l'activité contenant le MapFragment. Mon instinct me dit que je dois faire quelque chose à l'intérieur de la méthode handleNewLocation qui mettrait à jour la carte ... soit cela soit peut-être faire quelque chose dans le LocationProvider qui mettrait à jour l'emplacement plus souvent.

Toute aide, conseil ou lien serait grandement apprécié! Mon but est d'apprendre pour que je comprenne comment je peux faire mieux à l'avenir :)!

package com.seniorproject.trafton.trackrecordrace; 

//Import statements not shown for readability 
import... 

public class MapsActivity extends AppCompatActivity implements LocationProvider.LocationCallback { 

public static final String TAG = "cloudsTraf"; 
     //MapsActivity.class.getSimpleName(); 

private GoogleMap mMap; // Might be null if Google Play services APK is not available. 

private LocationProvider mLocationProvider; 

//variable for toggle buttons 
private boolean isRunning = false; 

//ArrayList to store geopoints for current run 
private ArrayList<LatLng> geoPoints; 

//Array of distances 
private ArrayList<Float> distances; 

//total distance 
private float totalDistance; 

//polyline that represented the route 
Polyline tracker; 

/*Load up widgets for tracking */ 
private ImageButton mPlayButton; 
private ImageButton mPauseButton; 

private TextView mRunTimeText; 
private TextView mRunSpeedText; 
private TextView mRunDistText; 
private TextView mRunCalsText; 

private Boolean mIsPlayButtonClicked; 

//Handler to control timer tracking 
//Thank you to Nikos Maravitsas for the tutorial on timers 

private Handler timeHandler = new Handler(); 

private long startTime = 0L; 
long timeInMillis = 0L; 
long timeSwapBuffer = 0L; 
long updatedTime = 0L; 





@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_maps); 
    setUpMapIfNeeded(); 

    mLocationProvider = new LocationProvider(this, this); 
    geoPoints = new ArrayList<LatLng>(); //added 

    //Add in code to inflate the tracking modules 
    mRunTimeText = (TextView) findViewById(R.id.run_time_text); 
    mRunDistText = (TextView) findViewById(R.id.run_dist_text); 
    mRunSpeedText = (TextView) findViewById(R.id.run_speed_text); 

    Toolbar runToolbar= (Toolbar) findViewById(R.id.toolbar_run); 
    runToolbar.setTitle("Run on " + getDate()); 
    runToolbar.setTitleTextColor(Color.WHITE); 
    setSupportActionBar(runToolbar); 

} 

//Inflate the menu for the toolbar 
public boolean onCreateOptionsMenu(Menu menu) { 
    Log.e("XXX", "Menu created"); 
    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.menu_maps_run, menu); 
    return super.onCreateOptionsMenu(menu); 
} 

//Handles possibilities of menu items being selected. 
@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle item selection 
    switch (item.getItemId()) { 
     case R.id.action_begin_run: 
      if (!isRunning) { 
       startTime = SystemClock.uptimeMillis(); 
       timeHandler.postDelayed(updateTimerThread,0); 
       item.setIcon(R.drawable.ic_pause_white_24dp); 
       isRunning = true; 
      } 
      else { 
       timeSwapBuffer += timeInMillis; 
       timeHandler.removeCallbacks(updateTimerThread); 
       item.setIcon(R.drawable.ic_play_arrow_white_24dp); 
       isRunning = false; 

      } 
      return true; 

     case R.id.action_stop_run: 
      //stop run, save run, and transport user to the stats for that run 

      return true; 
     default: 
      return super.onOptionsItemSelected(item); 
    } 
} 

/*Code to update the timer, begins a new timer thread.*/ 
private Runnable updateTimerThread = new Runnable() { 
    public void run(){ 
     timeInMillis = SystemClock.uptimeMillis() - startTime; 
     updatedTime = timeSwapBuffer + timeInMillis; 

     //Get integer value from time update and put into textView 
     int seconds = (int) (updatedTime/1000); 
     //need two seconds variables for formatting purposes. 
     int secs = seconds % 60; 
     int mins = (seconds/60); 
     int hours = (mins/60); 

     mRunTimeText.setText("" + hours + ":" + 
       String.format("%02d", mins) + ":" + 
       String.format("%02d", secs)); 
     timeHandler.postDelayed(this, 0); 
    } 

}; 

/* */ 

@Override 
protected void onResume() { 
    super.onResume(); 
    setUpMapIfNeeded(); 
    mLocationProvider.connect(); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    mLocationProvider.disconnect(); 
} 

/** 
* Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly 
* installed) and the map has not already been instantiated.. This will ensure that we only ever 
* call {@link #setUpMap()} once when {@link #mMap} is not null. 
* <p/> 
* If it isn't installed {@link SupportMapFragment} (and 
* {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to 
* install/update the Google Play services APK on their device. 
* <p/> 
* A user can return to this FragmentActivity after following the prompt and correctly 
* installing/updating/enabling the Google Play services. Since the FragmentActivity may not 
* have been completely destroyed during this process (it is likely that it would only be 
* stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this 
* method in {@link #onResume()} to guarantee that it will be called. 
*/ 
private void setUpMapIfNeeded() { 
    // Do a null check to confirm that we have not already instantiated the map. 
    if (mMap == null) { 
     // Try to obtain the map from the SupportMapFragment. 
     mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) 
       .getMap(); 
     // Check if we were successful in obtaining the map. 
     if (mMap != null) { 
      setUpMap(); 
     } 
    } 
} 

/** 
* This should only be called once and when we are sure that {@link #mMap} is not null. 
*/ 
private void setUpMap() { 
    //mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker")); 
} 

//handle new location 
public void handleNewLocation(Location location) { 
    Log.d(TAG, location.toString()); 

    double currentLatitude = location.getLatitude(); 
    double currentLongitude = location.getLongitude(); 
    LatLng latLng = new LatLng(currentLatitude, currentLongitude); 

    //Get the new geopoints to redraw the line on each iteration 
    geoPoints.add(latLng); 
    //get the latest distance update 
    if (geoPoints.size() > 2) { 
     calculateDistance(); 
    } 
    //set the distance test 
    mRunDistText.setText(Float.toString(totalDistance) + " Meters"); 
    mRunSpeedText.setText((location.getSpeed() + " m/s")); 

    //draw the polyline 
    drawRoute(); 
    MarkerOptions options = new MarkerOptions() 
      .position(latLng) 
      .title("I am here!"); 
    mMap.addMarker(options); 
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,15)); 
} 

/* 
*Methods to calculate metrics. All measurements returned are approximations. 
*/ 
//returns the latest distance between geoPoints. Append to total number 
public void calculateDistance(){ 
    Location newLoc = new Location("Latest Location"); 
    Location oldLoc = new Location("Last known Location"); 
    LatLng newPt = geoPoints.get(geoPoints.size()- 1); 
    LatLng oldPt = geoPoints.get(geoPoints.size()-2); 
    distances.add(oldLoc.distanceTo(newLoc)); 
    //add to the distance variable 
    totalDistance = totalDistance + oldLoc.distanceTo(newLoc); 
    Log.d(TAG, "distance between points is: " + oldLoc.distanceTo(newLoc)); 
} 

//calculates the current KCals being burned 
public void calculateKcals(){ 

} 

//get today's date in a simple format 
public String getDate(){ 
    Date today = Calendar.getInstance().getTime(); 
    SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd"); 
    String todaysDate = formatter.format(today); 
    return todaysDate; 
} 

//method to draw polyline. Uses the recorded geopoints. 
public void drawRoute(){ 
    mMap.clear(); 
    PolylineOptions options = new PolylineOptions().width(5).color(android.R.color.holo_blue_dark).geodesic(true).visible(true); 
    for(int i = 0; i < geoPoints.size(); i++){ 
     LatLng pt = geoPoints.get(i); 
     options.add(pt); 
    } 
    Log.d(TAG,"GeoPoints recorded: " + geoPoints); 
    mMap.addPolyline(options); 
} 

}

Je suis preneuse l'emplacement dans un autre fichier (Parce que, tu sais, la modularité est bonne.). S'il y a des données supplémentaires que je peux fournir, je serais plus qu'heureux de l'inclure!

package com.seniorproject.trafton.trackrecordrace; 

import android.app.Activity; 
import android.content.Context; 
import android.content.IntentSender; 
import android.location.Location; 
import android.os.Bundle; 
import android.util.Log; 

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; 


public class LocationProvider implements 
    GoogleApiClient.ConnectionCallbacks, 
    GoogleApiClient.OnConnectionFailedListener, 
    LocationListener { 

public abstract interface LocationCallback { 
    public void handleNewLocation(Location location); 
} 

public static final String TAG = LocationProvider.class.getSimpleName(); 

/* 
* Define a request code to send to Google Play services 
* This code is returned in Activity.onActivityResult 
*/ 
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; 

private LocationCallback mLocationCallback; 
private Context mContext; 
private GoogleApiClient mGoogleApiClient; 
private LocationRequest mLocationRequest; 


public LocationProvider(Context context, LocationCallback callback) { 
    mGoogleApiClient = new GoogleApiClient.Builder(context) 
      .addConnectionCallbacks(this) 
      .addOnConnectionFailedListener(this) 
      .addApi(LocationServices.API) 
      .build(); 

    mLocationCallback = callback; 

    // Create the LocationRequest object 
    mLocationRequest = LocationRequest.create() 
      .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) 
      .setInterval(3 * 1000)  // 10 seconds, in milliseconds 
      .setFastestInterval(1 * 1000); // 1 second, in milliseconds 

    mContext = context; 
} 

public void connect() { 
    mGoogleApiClient.connect(); 
} 

public void disconnect() { 
    if (mGoogleApiClient.isConnected()) { 
     LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 
     mGoogleApiClient.disconnect(); 
    } 
} 

@Override 
public void onConnected(Bundle bundle) { 
    Log.i(TAG, "Location services connected."); 

    Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
    if (location == null) { 
     LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 
    } 
    else { 
     mLocationCallback.handleNewLocation(location); 
    } 
} 

@Override 
public void onConnectionSuspended(int i) { 

} 

@Override 
public void onConnectionFailed(ConnectionResult connectionResult) { 
    /* 
    * Google Play services can resolve some errors it detects. 
    * If the error has a resolution, try sending an Intent to 
    * start a Google Play services activity that can resolve 
    * error. 
    */ 
    if (connectionResult.hasResolution() && mContext instanceof Activity) { 
     try { 
      Activity activity = (Activity)mContext; 
      // Start an Activity that tries to resolve the error 
      connectionResult.startResolutionForResult(activity, CONNECTION_FAILURE_RESOLUTION_REQUEST); 
     /* 
     * Thrown if Google Play services canceled the original 
     * PendingIntent 
     */ 
     } catch (IntentSender.SendIntentException e) { 
      // Log the error 
      e.printStackTrace(); 
     } 
    } else { 
     /* 
     * If no resolution is available, display a dialog to the 
     * user with the error. 
     */ 
     Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode()); 
    } 
} 

@Override 
public void onLocationChanged(Location location) { 
    mLocationCallback.handleNewLocation(location); 
    Log.i(TAG, "New location received "); 
} 

}

+0

Essayez de lire ce [SO question] (http://stackoverflow.com/questions/19407929/ dynamiquement-tracer-une-route-en-temps-réel-using-google-maps-api-pour-android). Ceci est une copie possible de votre question. – abielita

Répondre

0

Pour dessiner une polyligne sur la carte faire dans OnLocationChanged

Polyline route = mMap.addPolyline(new PolylineOptions()); 
route.setPoints(mGeoPoints);`