Reputation: 53
I have used the following code to get the current location and path the route in google map. The problem i faced is that the current device location is not stable all the time. It shows correct location sometime but shows different location like 1km away from actual location.
package com.colors.organisatiom.activity.colors;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.colors.organisatiom.activity.colors.classes.ConnectionManager;
import com.colors.organisatiom.activity.colors.interfaces.PolyLineCallback;
import com.colors.organisatiom.activity.colors.json.GetDistanceFromServer;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
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.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
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.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import java.util.ArrayList;
import java.util.List;
public class LocationMap extends AppCompatActivity implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private GoogleMap map;
private String serviceCentreLongitude, serviceCentreLatitude, serviceCenhterLocation;
final private int REQUEST_CODE_ASK_PERMISSIONS = 123;
private RelativeLayout connectingParent;
private PolylineOptions polylineOptions;
private Polyline polyline;
private List<Polyline> polylines = new ArrayList<>();
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private static final long INTERVAL = 1 * 5;
private static final long FASTEST_INTERVAL = 10;
protected BroadcastReceiver mNotificationReceiver;
private Marker currentLocationMarker;
protected void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
serviceCentreLatitude = getIntent().getStringExtra("latitude");
serviceCentreLongitude = getIntent().getStringExtra("longitude");
serviceCenhterLocation = getIntent().getStringExtra("service_center_location");
setContentView(R.layout.content_google_map);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Window window = this.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark));
}
mNotificationReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!LocationMap.this.isFinishing()) {
AlertDialog.Builder builder = new AlertDialog.Builder(LocationMap.this);
builder.setTitle(intent.getStringExtra("title"));
builder.setMessage(intent.getStringExtra("message"));
builder.setPositiveButton("Dismiss", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//alertDialog.dismiss();
}
});
final AlertDialog alertDialog = builder.create();
alertDialog.show();
}
}
};
if (!isGooglePlayServicesAvailable()) {
Toast.makeText(this, "Google play service not supported", Toast.LENGTH_LONG).show();
}
createLocationRequest();
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
connectingParent = (RelativeLayout) findViewById(R.id.connecting_parent);
if (!new ConnectionManager(this).isConnectionToInternet()) {
connectingParent.setVisibility(View.GONE);
Toast.makeText(LocationMap.this, "No internet connection to route path", Toast.LENGTH_LONG).show();
}
ImageView search = (ImageView) findViewById(R.id.search);
search.setVisibility(View.INVISIBLE);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasAccessCoarseLocationPermission = checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION);
int hasAccessFineLocationPermission = checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION);
if (hasAccessCoarseLocationPermission != PackageManager.PERMISSION_GRANTED && hasAccessFineLocationPermission != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ASK_PERMISSIONS);
} else {
showMapWithLocation();
if (googleApiClient.isConnected()) {
startLocationUpdates();
}
}
} else {
showMapWithLocation();
if (googleApiClient.isConnected()) {
startLocationUpdates();
}
}
}
@Override
public void onStart() {
super.onStart();
Log.d("Started:", "onStart fired ..............");
googleApiClient.connect();
}
@Override
public void onStop() {
super.onStop();
Log.d("Stopped", "onStop fired ..............");
googleApiClient.disconnect();
Log.d("Is connected status", "isConnected ...............: " + googleApiClient.isConnected());
}
private void showMapWithLocation() {
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
LatLng latLng = new LatLng(Double.parseDouble(serviceCentreLatitude), Double.parseDouble(serviceCentreLongitude));
map.addMarker(new MarkerOptions()
.position(latLng)
.title(serviceCenhterLocation)).showInfoWindow();
map.getUiSettings().setMapToolbarEnabled(false);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 14);
map.animateCamera(cameraUpdate);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_PERMISSIONS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startLocationUpdates();
if (googleApiClient.isConnected()) {
startLocationUpdates();
}
} else {
Toast.makeText(LocationMap.this, "Cannot show map", Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private List<LatLng> decodePoly(String encoded) {
List<LatLng> poly = new ArrayList<>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
@Override
public void onConnected(Bundle bundle) {
Log.e("Connection status:", "onConnected - isConnected ...............: " + googleApiClient.isConnected());
startLocationUpdates();
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
Log.e("Update started:", "Location update started ..............: ");
}
@Override
public void onLocationChanged(Location location) {
final double myLocationlatitude = location.getLatitude();
final double myLocationlongitude = location.getLongitude();
Log.e("Latitude", String.valueOf(myLocationlatitude));
Log.e("Longitude", String.valueOf(myLocationlongitude));
LatLng latLng = new LatLng(myLocationlatitude, myLocationlongitude);
//drawing the path in google map
//zoom the camera for the first time
if (currentLocationMarker != null) {
currentLocationMarker.remove();
}
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("My current location");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
currentLocationMarker = map.addMarker(markerOptions);
if (polylines == null) {
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 14);
map.animateCamera(cameraUpdate);
}
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
new GetDistanceFromServer(String.valueOf(myLocationlatitude), String.valueOf(myLocationlongitude), serviceCentreLatitude, serviceCentreLongitude).drawPath(new PolyLineCallback() {
@Override
public void polyLinePointsHolder(String points) {
//remove the path and draw the path in google map while updating
if (polylines != null) {
for (Polyline line : polylines) {
line.remove();
}
}
List<LatLng> list = decodePoly(points);
polylineOptions = new PolylineOptions()
.addAll(list)
.width(12)
.color(Color.parseColor("#05b1fb"))
.geodesic(true);
polyline = map.addPolyline(polylineOptions);
polylines.add(polyline);
}
});
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
connectingParent.setVisibility(View.GONE);
super.onPostExecute(aVoid);
}
}.execute();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e("Connection Failed", connectionResult.getErrorMessage());
}
@Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
googleApiClient, this);
Log.d("TAG", "Location update stopped .......................");
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
@Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mNotificationReceiver, new IntentFilter("1000"));
if (googleApiClient.isConnected()) {
startLocationUpdates();
Log.d("TAG", "Location update resumed .....................");
}
}
}
Upvotes: 0
Views: 965
Reputation: 3140
The accuracy of location can be affected due to many factors including GPS coverage, device quality and wifi availability around the area. What you can do is to check the accuracy of the location you obtained and decide whether to proceed or not. For this you can use hasAccuracy()
and getAccuracy()
methods of the Location object.
Here is a quote from the documentation about getAccuracy method
Get the estimated accuracy of this location, in meters.
We define accuracy as the radius of 68% confidence. In other words, if you draw a circle centered at this location's latitude and longitude, and with a radius equal to the accuracy, then there is a 68% probability that the true location is inside the circle.
In statistical terms, it is assumed that location errors are random with a normal distribution, so the 68% confidence circle represents one standard deviation. Note that in practice, location errors do not always follow such a simple distribution.
This accuracy estimation is only concerned with horizontal accuracy, and does not indicate the accuracy of bearing, velocity or altitude if those are included in this Location.
If this location does not have an accuracy, then 0.0 is returned. All locations generated by the LocationManager include an accuracy.
In your onLocationChanged method, you can do the following
@Override
public void onLocationChanged(Location location) {
if(location.hasAccuracy() && location.getAccuracy() < 100F) {
// the location has accuracy and has an accuracy span within 100m radius
// do whatever you want with this location and stop location listener
stopLocationUpdates();
}
// if the above code did not get executed, the location listener will work
// until a location with acceptable accuracy is obtained
}
Upvotes: 1