0

我使用以下代码在谷歌地图中获取当前位置和路径。我面临的问题是当前设备位置一直不稳定。它有时会显示正确的位置,但会显示不同的位置,例如距离实际位置 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 .....................");
        }
    }
}
4

1 回答 1

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
}
于 2016-02-09T08:58:31.447 回答