在我的应用程序中,可以跟踪一个人被移动的距离。有一个服务类可以获得当前的lat和长期的perorically。有些时候获得的点很好。其他时间不是。我从一个开始并且走了大约500米并回到了同一点,但计算的距离是3.5公里 为了找到行进的距离,我在当前和之前的位置之间取差异。这些值加上新的值并一直持续到最后。问题发生了,有些时候gps点的距离比前一个很远(有时候得到点数将超过前一个700米。
这是我的班级。如果我做错了,请告诉我。
public class LocationUpdateService extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
protected static final String TAG = "LocationUpdateService";
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 3; // 10 meters
public static Boolean mRequestingLocationUpdates;
protected String mLastUpdateTime;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
protected Location mCurrentLocation;
protected Location mLastLocation;
Location currentLocation, previousLocation;
public static boolean isEnded = false;
private Context mContext;
ServiceListener listener;
SharedPreferences sharedPreferences;
double latitude; // latitude
double longitude; // longitude
private String locationProvider; // source of fetched location
LocationManager locationManager;
private IBinder mBinder = new MyBinder();
public LocationUpdateService() {
super();
}
public void setListener(ServiceListener listener) {
this.listener = listener;
}
@Override
public void onCreate() {
super.onCreate();
// Kick off the process of building a GoogleApiClient and requesting the LocationServices
mContext = getApplicationContext();
//locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
sharedPreferences = mContext.getSharedPreferences(WebServiceHelper.PREFS_NAME, 0);
System.out.println("GPS TRACKER STARTED");
deletefile("asap_distance.csv");
}
// @Override
// public IBinder onBind(Intent intent) {
// return null;
// }
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Within {@code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
System.out.println(TAG + "onStartCommand");
Log.d("LOC", "Service init...");
isEnded = false;
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
buildGoogleApiClient();
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
return Service.START_REDELIVER_INTENT;
}
@Override
public void onConnected(Bundle bundle) {
System.out.println(TAG + "onConnected");
startLocationUpdates();
}
@Override
public void onConnectionSuspended(int i) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended==");
mGoogleApiClient.connect();
}
@Override
public void onLocationChanged(Location location) {
System.out.println(TAG + "onLocationChanged");
if (location == null) {
getLastKnownLocation();
} else {
mCurrentLocation = location;
if (mCurrentLocation.hasAccuracy() && mCurrentLocation.getAccuracy() > MIN_DISTANCE_CHANGE_FOR_UPDATES)
setLocationData(mCurrentLocation);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
}
//
// updateUI();
// Toast.makeText(this, "Location changed",
// Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
/**
* Builds a GoogleApiClient. Uses the {@code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient===");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
public void setLocationData(Location location) {
if (location != null) {
currentLocation = location;
double previous_latitude, previous_longitude, current_lat, current_long;
latitude = location.getLatitude();
longitude = location.getLongitude();
// Toast.makeText(mContext, "Current lattitude:" + latitude + "Current Longitude:" + longitude, Toast.LENGTH_LONG).show();
previous_latitude = previousLocation.getLatitude();
previous_longitude = previousLocation.getLongitude();
current_lat = currentLocation.getLatitude();
current_long = currentLocation.getLongitude();
Log.d(TAG, "Previous lattitude:" + previous_latitude + "Previous Longitude:" + previous_longitude);
Log.d(TAG, "Current lattitude:" + current_lat + "Current Longitude:" + current_long);
sharedPreferences.edit().putFloat("lastSavedLat", (float) current_lat).apply();
sharedPreferences.edit().putFloat("lastSavedLon", (float) current_long).apply();
if (previousLocation != null && sharedPreferences.contains("sdeMarkedStartLocLat")) {
if (current_lat == previous_latitude && current_long == previous_longitude) {
Log.d(TAG, "No Displacement");
} else {
Log.d(TAG, "Device Displaced");
// double d = getDistance(previous_latitude, previous_longitude, current_lat, current_long);
double d = ((int) (previousLocation.distanceTo(currentLocation) * 1000)) / 1000;
Log.d(TAG, "Distance calculated in between previousLocation and currentLocation is" + d);
if (d < 5000) {
d = d + sharedPreferences.getFloat("sum_dist", 0);
sharedPreferences.edit().putFloat("sum_dist", (float) d).apply();
// Toast.makeText(mContext, "Total Distance travelled is " + d + "km", Toast.LENGTH_LONG).show();
// Log.d("Distance Calculator ON", "distance" + d);
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
writeToFile(sdf.format(new Date()) + "," + currentLocation.getLatitude() + "," + currentLocation.getLongitude() + ", " + d + " meters" + "\n", "asap.csv");
writeToFile(currentLocation.getLatitude() + "," + currentLocation.getLongitude() + "\n", "asap_distance.csv");
}
}
}
if (listener != null)
listener.onLocationReceived(location);
System.out.println("GPS TRACKER " + latitude + " " + longitude);
previousLocation = currentLocation;
} else {
Log.d(TAG, "Location is null");
return;
}
}
public double getDistance(double start_lat, double start_long, double dest_lat, double dest_long) {
double dist = 0;
Location locationA = new Location("point A");
locationA.setLatitude(start_lat);
locationA.setLongitude(start_long);
Location locationB = new Location("point B");
locationB.setLatitude(dest_lat);
locationB.setLongitude(dest_long);
dist = locationA.distanceTo(locationB);
if (dist != 0) {
dist = dist / 1000;
}
return dist;
}
/**
* Updates the latitude, the longitude, and the last location time in the UI.
*/
private void updateUI() {
Toast.makeText(this, "Latitude: =" + mCurrentLocation.getLatitude() + " Longitude:=" + mCurrentLocation
.getLongitude(), Toast.LENGTH_SHORT).show();
System.out.println("updateUI");
Log.d(TAG, "Latitude:==" + mCurrentLocation.getLatitude() + "\n Longitude:==" + mCurrentLocation.getLongitude
());
}
/**
* 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.
* <p/>
* 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.
* <p/>
* These settings are appropriate for mapping applications that show real-time location
* updates.
*/
protected void createLocationRequest() {
mGoogleApiClient.connect();
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);
mLocationRequest.setSmallestDisplacement(MIN_DISTANCE_CHANGE_FOR_UPDATES);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
// 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);
Log.i(TAG, " startLocationUpdates===");
isEnded = true;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
previousLocation = mLastLocation;
if (mLastLocation != null) {
onLocationChanged(mLastLocation);
}
}
/**
* Function to get latitude
*/
public double getLatitude() {
if (mCurrentLocation != null) {
latitude = mCurrentLocation.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
*/
public double getLongitude() {
if (mCurrentLocation != null) {
longitude = mCurrentLocation.getLongitude();
}
// return longitude
return longitude;
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
if (mRequestingLocationUpdates) {
mRequestingLocationUpdates = false;
// 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.
Log.d(TAG, "stopLocationUpdates();==");
// 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);
}
}
@Override
public void onDestroy() {
super.onDestroy();
stopLocationUpdates();
System.out.println("GPS TRACKER STOPPED");
}
public Location getLastKnownLocation() {
// locationProvider = LocationManager.GPS_PROVIDER;
Location lastKnownLocation = null;
// Or use LocationManager.GPS_PROVIDER
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return lastKnownLocation;
}
try {
//lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
lastKnownLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
return lastKnownLocation;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return lastKnownLocation;
}
@Override
public IBinder onBind(Intent intent) {
Log.v("GPS", "in onBind");
return mBinder;
}
@Override
public void onRebind(Intent intent) {
Log.v("GPS", "in onRebind");
super.onRebind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
Log.v("GPS", "in onUnbind");
return true;
}
public void deletefile(String filename) {
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File(sdCard.getAbsolutePath() + "/ASAPLog");
//Now delete the file in the above directory and write the contents into it
try {
File file = new File(directory.getAbsolutePath() + "/" + filename);
if (file.exists()) {
boolean deleted = file.delete();
System.out.println("deleted" + deleted);
} else {
System.out.println("File Doesnot Exists");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeToFile(String text, String filename) {
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File(sdCard.getAbsolutePath() + "/ASAPLog");
if (!directory.exists())
directory.mkdirs();
// String savedText = readFromFile(filename).toString();
//Now create the file in the above directory and write the contents into it
try {
File file = new File(directory.getAbsolutePath() + "/" + filename);
FileOutputStream fOut = new FileOutputStream(file, true);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
osw.append(text);
osw.flush();
osw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public class MyBinder extends Binder {
LocationUpdateService getService() {
return LocationUpdateService.this;
}
}
}