我使用以下代码获取谷歌地图中路线的当前位置和路径。我遇到的问题是当前的设备位置始终不稳定。它显示正确的位置,但显示不同的位置,如距实际位置1公里。
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 .....................");
}
}
}
答案 0 :(得分:1)
由于许多因素(包括GPS覆盖范围,设备质量和该地区的无线网络可用性),位置的准确性会受到影响。您可以做的是检查您获得的位置的准确性,并决定是否继续。为此,您可以使用Location对象的hasAccuracy()
和getAccuracy()
方法。
以下是有关getAccuracy方法
的文档中的引用获取此位置的估计精确度,以米为单位。
我们将准确度定义为68%置信度的半径。换句话说,如果 你画一个以这个位置为中心的圆圈经度和纬度, 并且半径等于精度,那么有68% 真实位置在圆圈内的概率。
在统计学术语中,假设位置误差是随机的 具有正态分布,因此68%置信圆代表 一个标准偏差。请注意,实际上,位置错误不会 总是遵循这样简单的分配。
此准确度估算仅涉及水平精度, 并且如果没有表明轴承,速度或高度的准确性 这些都包含在这个位置。
如果此位置没有准确性,则返回0.0。所有 LocationManager生成的位置包括准确性。
在onLocationChanged方法中,您可以执行以下操作
@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
}