位置 api 有时在 android 中使用 google fused api 不给出确切的当前位置
Posted
技术标签:
【中文标题】位置 api 有时在 android 中使用 google fused api 不给出确切的当前位置【英文标题】:location api does not give exact current location sometime in android using google fused api 【发布时间】:2016-05-19 03:17:33 【问题描述】:我使用以下代码在谷歌地图中获取当前位置和路径。我面临的问题是当前设备位置一直不稳定。它有时会显示正确的位置,但会显示不同的位置,例如距离实际位置 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 .....................");
【问题讨论】:
【参考方案1】:位置的准确性可能会受到许多因素的影响,包括 GPS 覆盖范围、设备质量和该地区周围的 wifi 可用性。您可以做的是检查您获得的位置的准确性并决定是否继续。为此,您可以使用 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
【讨论】:
以上是关于位置 api 有时在 android 中使用 google fused api 不给出确切的当前位置的主要内容,如果未能解决你的问题,请参考以下文章