Java 短时间更改路线,然后将路线返回正确路线的解决方案是什么?

Java 短时间更改路线,然后将路线返回正确路线的解决方案是什么?,java,android,google-maps,mobile,background-service,Java,Android,Google Maps,Mobile,Background Service,经过多次测试,当前位置不准确,多次移动,路线改变,计算错误距离。 示例:实际距离应为23公里,但结果为49公里 上传的照片很好地描述了情况 我们使用以下库使用服务后台: implementation 'com.yayandroid:LocationManager:2.4.1' 库的配置为: @Override public LocationConfiguration getLocationConfiguration() { LocationRequest locationRequ

经过多次测试,当前位置不准确,多次移动,路线改变,计算错误距离。 示例:实际距离应为23公里,但结果为49公里 上传的照片很好地描述了情况

我们使用以下库使用服务后台:

implementation 'com.yayandroid:LocationManager:2.4.1' 
库的配置为:

 @Override
public LocationConfiguration getLocationConfiguration() {
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(1000);
    locationRequest.setFastestInterval(1000);
    LocationConfiguration locationConfiguration = new LocationConfiguration.Builder()
            .keepTracking(true)
            .useGooglePlayServices(new GooglePlayServicesConfiguration.Builder()
                    .fallbackToDefault(true)
                    .askForGooglePlayServices(false)
                    .askForSettingsApi(false)
                    .failOnSettingsApiSuspended(false)
                    .ignoreLastKnowLocation(false)
                    .setWaitPeriod(1000)
                    .locationRequest(locationRequest)
                    .build())
            .useDefaultProviders(new DefaultProviderConfiguration.Builder()
                    .requiredTimeInterval(1000)
                    .requiredDistanceInterval(1)
                    .acceptableAccuracy(5.0f)
                    .acceptableTimePeriod(1000)
                    .gpsMessage("Turn on GPS?")
                    .setWaitPeriod(ProviderType.GPS, 1000)
                    .setWaitPeriod(ProviderType.NETWORK, 1000)
                    .build())
            .build();

    return locationConfiguration;
}
后台服务的类别为:

public class LocationService extends LocationBaseService {
public static final int LOCATION_SERVICE_ID = 175;
public static final String ACTION_START_LOCATION_SERVICE = "startLocationService";
public static final String ACTION_STOP_LOCATION_SERVICE = "stopLocationService";

public static CountDownTimer countDownTimerTrip = null;
public static CountDownTimer countDownTimerAwite = null;
public static MySharedPreferences mySharedPreferences;
DatabaseReference databaseReferenceCaptainCoordinates;
DatabaseReference databaseReferenceOrders;
Map<String, String> tripDetails = new HashMap<>();

private boolean isLocationRequested = true;
public static Location lastLocation = null;
private static int seconds = 0;
private static int minutes = 0;
private static int hours = 0;

@Nullable
@Override
public IBinder onBind(Intent intent) {
    throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public void onCreate() {
    super.onCreate();
    mySharedPreferences = new MySharedPreferences(getApplicationContext());
    databaseReferenceCaptainCoordinates = FirebaseDatabase.getInstance().getReference().child("captain").child(String.valueOf(mySharedPreferences.getUserId())).child("coordinates");
}

@Override
public LocationConfiguration getLocationConfiguration() {
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(1000);
    locationRequest.setFastestInterval(1000);
    LocationConfiguration locationConfiguration = new LocationConfiguration.Builder()
            .keepTracking(true)
            .useGooglePlayServices(new GooglePlayServicesConfiguration.Builder()
                    .fallbackToDefault(true)
                    .askForGooglePlayServices(false)
                    .askForSettingsApi(false)
                    .failOnSettingsApiSuspended(false)
                    .ignoreLastKnowLocation(false)
                    .setWaitPeriod(1000)
                    .locationRequest(locationRequest)
                    .build())
            .useDefaultProviders(new DefaultProviderConfiguration.Builder()
                    .requiredTimeInterval(1000)
                    .requiredDistanceInterval(1)
                    .acceptableAccuracy(5.0f)
                    .acceptableTimePeriod(1000)
                    .gpsMessage("Turn on GPS?")
                    .setWaitPeriod(ProviderType.GPS, 1000)
                    .setWaitPeriod(ProviderType.NETWORK, 1000)
                    .build())
            .build();

    return locationConfiguration;
}

@Override
public void onLocationChanged(Location location) {
    if (location != null && location.getLatitude() != 0.0D && location.getLongitude() != 0.0D) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            if (!location.isFromMockProvider()) {
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                Log.d("Location :", location.getLatitude() + "," + location.getLongitude()
                        + "  Accuracy :" + location.getAccuracy()
                        + "  Speed :" + location.getSpeed()*3.4
                        + "  SpeedAccuracyMetersPerSecond :" + location.getSpeedAccuracyMetersPerSecond()
                        + "  VerticalAccuracyMeters :" + location.getVerticalAccuracyMeters()
                        + "  BearingAccuracyDegrees :" + location.getBearingAccuracyDegrees());
                mySharedPreferences.setLocation(location == null ? "" : new Gson().toJson(location));
                databaseReferenceCaptainCoordinates.setValue(location.getLatitude() + "," + location.getLongitude());
                tripDetails = mySharedPreferences.getTripDetails() == "" ? null : new Gson().fromJson(mySharedPreferences.getTripDetails(), Map.class);
                if (mySharedPreferences.getTripStatus().equals("Finished")) {
                    if(location.getAccuracy() < 100){
                        databaseReferenceOrders = FirebaseDatabase.getInstance().getReference().child("orders").child(tripDetails.get("order_id")).child("info");
                        HashMap<String, String> orderData = new HashMap<>();
                        orderData.put("coordinates", location.getLatitude() + "," + location.getLongitude());
                        orderData.put("speed", new DecimalFormat("###.#").format(location.getSpeed() * 3.4));
                        databaseReferenceOrders.push().setValue(orderData);
                        if (lastLocation != null) {
                            if (lastLocation.getLongitude() != 0 && lastLocation.getLongitude() != 0) {
                                double distance = location.distanceTo(lastLocation) / 1000;
                                double totalDistance = Double.parseDouble(mySharedPreferences.getTraveledDistance()) + distance;
                                Log.d("distance", distance + "");
                                Log.d("totalDistance", totalDistance + "");
                                mySharedPreferences.setTraveledDistance(totalDistance + "");
                                HomeFragment.textViewTraveledDistance.setText(new DecimalFormat("###.##").format(totalDistance));
                            }
                        }
                        lastLocation = location;
                    } else {

                    }
                }
            } else {

            }
        }
    }
}

@Override
public void onLocationFailed(int type) {
    Log.d("onLocationFailed", type+"");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    if (this.isLocationRequested) {
        this.isLocationRequested = false;
        getLocation();
    }
    if (intent != null) {
        String action = intent.getAction();
        if (action.equals(ACTION_START_LOCATION_SERVICE)) {
            startLocationService();
        } else if (action.equals(ACTION_STOP_LOCATION_SERVICE)) {
            stopLocationService();
        }
    }
    return flags;
}
private void startLocationService() {
    String channelId = "location_notification_channel";
    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    Intent resultIntent = new Intent();
    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), channelId);
    builder.setSmallIcon(R.drawable.notification_gold1)
            .setContentTitle("Location Service")
            .setContentText("App is running in background and tracking location")
            .setColor(getResources().getColor(R.color.colorPrimary))
            .setDefaults(NotificationCompat.DEFAULT_ALL)
            .setContentIntent(pendingIntent)
            .setAutoCancel(false)
            .setPriority(NotificationCompat.PRIORITY_MAX);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if (notificationManager != null && notificationManager.getNotificationChannel(channelId) == null) {
            NotificationChannel notificationChannel = new NotificationChannel(channelId, "Location Service", NotificationManager.IMPORTANCE_HIGH);
            notificationChannel.setDescription("This Channel is used by location service");
            notificationChannel.enableLights(false);
            notificationChannel.enableVibration(false);
            notificationManager.createNotificationChannel(notificationChannel);
        }
    }
    startForeground(LOCATION_SERVICE_ID, builder.build());
}

private void stopLocationService() {
    stopForeground(true);
    stopSelf();
}

public static void startTimeTrip(){
    countDownTimerTrip = new CountDownTimer(36000000, 1000){
        @Override
        public void onTick(long millisUntilFinished) {
            seconds += 1;
            if(seconds == 60){
                seconds = 0;
                minutes += 1;
                if(minutes == 60){
                    minutes = 0;
                    hours += 1;
                }
            }
            HomeFragment.textViewTimeTrip.setText(getTime(seconds, minutes, hours));
        }
        @Override
        public void onFinish() {
            seconds = 0;
            minutes = 0;
            hours = 0;
        }
    };
    countDownTimerTrip.start();
}

private static String getTime(int seconds, int minutes, int hours){
    String time = "";
    if(hours > 0){
        if(hours < 10){
            if(minutes < 10){
                if(seconds < 10){
                    time = "0"+hours+":0"+minutes+":0"+seconds;
                } else {
                    time = "0"+hours+":0"+minutes+":"+seconds;
                }
            } else {
                if(seconds < 10){
                    time = "0"+hours+":"+minutes+":0"+seconds;
                } else {
                    time = "0"+hours+":"+minutes+":"+seconds;
                }
            }
        } else {
            if(minutes < 10){
                if(seconds < 10){
                    time = hours+":0"+minutes+":0"+seconds;
                } else {
                    time = hours+":0"+minutes+":"+seconds;
                }
            } else {
                if(seconds < 10){
                    time = hours+":"+minutes+":0"+seconds;
                } else {
                    time = hours+":"+minutes+":"+seconds;
                }
            }
        }
    } else {
        if(minutes < 10){
            if(seconds < 10){
                time = "0"+minutes+":0"+seconds;
            } else {
                time = "0"+minutes+":"+seconds;
            }
        } else {
            if(seconds < 10){
                time = minutes+":0"+seconds;
            } else {
                time = minutes+":"+seconds;
            }
        }
    }
    return time;
}

public static void stopTimeTrip(){
    if(countDownTimerTrip != null){
        countDownTimerTrip.cancel();
        seconds = 0;
        minutes = 0;
        hours = 0;
    }
}

public static void startTimeAwite(int waiteTime){
    countDownTimerAwite = new CountDownTimer(60000 * waiteTime, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            HomeFragment.materialButtonCancel.setText(new SimpleDateFormat("mm:ss").format(new Date(millisUntilFinished)));
        }
        @Override
        public void onFinish() {
            mySharedPreferences.setTimeCancel("done");
            HomeFragment.materialButtonCancel.setEnabled(true);
            HomeFragment.materialButtonCancel.setText(R.string.cancel);
        }
    };
    countDownTimerAwite.start();
}

public static void stopTimeAwite(){
    if(countDownTimerAwite != null)
        countDownTimerAwite.cancel();
}

public double CalculationByDistance(LatLng latLngStart, LatLng latLngEnd) {
    int Radius = 6371;// radius of earth in Km
    double lat1 = latLngStart.latitude;
    double lat2 = latLngEnd.latitude;
    double lon1 = latLngStart.longitude;
    double lon2 = latLngEnd.longitude;
    double dLat = Math.toRadians(lat2 - lat1);
    double dLon = Math.toRadians(lon2 - lon1);
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
    double c = 2 * Math.asin(Math.sqrt(a));
    double valueResult = Radius * c;
    double km = valueResult / 1.0;
    double meter = valueResult * 1000;
    DecimalFormat newFormat = new DecimalFormat("####.###");
    String kmInDec = newFormat.format(km);
    String meterInDec = newFormat.format(meter);
    Log.i("Radius Value",   valueResult + " KM : " + kmInDec + " Meter : " + meterInDec);
    return meter;
}
公共类LocationService扩展LocationBaseService{
公共静态最终int位置\服务\ ID=175;
公共静态最终字符串操作\u开始\u位置\u服务=“startLocationService”;
公共静态最终字符串操作\u停止\u位置\u服务=“停止位置服务”;
公共静态CountDownTimer countDownTimerTrip=null;
公共静态CountDownTimer countDownTimerAwite=null;
公共静态MySharedPreferences MySharedPreferences;
数据库参考数据库参考Captain坐标;
数据库引用数据库引用订单;
Map tripDetails=新建HashMap();
私有布尔值isLocationRequested=true;
公共静态位置lastLocation=null;
专用静态整数秒=0;
私有静态整数分钟=0;
专用静态整数小时=0;
@可空
@凌驾
公共IBinder onBind(意向){
抛出新的UnsupportedOperationException(“尚未实现”);
}
@凌驾
public void onCreate(){
super.onCreate();
mySharedPreferences=新的mySharedPreferences(getApplicationContext());
databaseReferenceCaptainCoordinates=FirebaseDatabase.getInstance().getReference().child(“船长”).child(String.valueOf(mySharedPreferences.getUserId()).child(“坐标”);
}
@凌驾
公共位置配置getLocationConfiguration(){
LocationRequest LocationRequest=LocationRequest.create();
locationRequest.setPriority(locationRequest.PRIORITY\u高精度);
位置请求设置间隔(1000);
locationRequest.SetFastTestInterval(1000);
LocationConfiguration LocationConfiguration=新建LocationConfiguration.Builder()
.keepTracking(正确)
.useGooglePlayServices(新的GooglePlayServicesConfiguration.Builder()
.fallbackToDefault(真)
.askForGooglePlayServices(错误)
.askForSettingsApi(错误)
.failOnSettingsApiSuspended(错误)
.ignoreLastKnowLocation(false)
.setWaitPeriod(1000)
.locationRequest(locationRequest)
.build())
.useDefaultProviders(新的DefaultProviderConfiguration.Builder()
.所需时间间隔(1000)
.所需距离间隔(1)
.可接受精度(5.0f)
.可接受时间段(1000)
.gpsMessage(“打开GPS?”)
.setWaitPeriod(ProviderType.GPS,1000)
.setWaitPeriod(ProviderType.NETWORK,1000)
.build())
.build();
返回位置配置;
}
@凌驾
已更改位置上的公共无效(位置){
if(location!=null&&location.getLatitude()!=0.0D&&location.getLatitude()!=0.0D){
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.JELLY\u BEAN\u MR2){
如果(!location.isFromMockProvider()){
LatLng LatLng=新LatLng(location.getLatitude(),location.getLongitude());
Log.d(“Location:,Location.getLatitude()+”,“+Location.getLatitude())
+“精度:”+location.getAccurance()
+“速度:”+location.getSpeed()*3.4
+“SpeedAccuracyMetersPerSecond:+位置。getSpeedAccuracyMetersPerSecond()
+“垂直精度测量仪:”+location.getVerticalAccuracyMeters()
+“BearingAccuracyDegrees:+location.getBearingAccuracyDegrees());
setLocation(location==null?“:new Gson().toJson(location));
databaseReferenceCaptainCoordinates.setValue(location.getLatitude()+”,“+location.getLatitude());
tripDetails=mySharedPreferences.getTripDetails()==“”?null:new Gson().fromJson(mySharedPreferences.getTripDetails(),Map.class);
if(mySharedPreferences.getTripStatus().equals(“Finished”)){
if(location.getAccurance()<100){
databaseReferenceOrders=FirebaseDatabase.getInstance().getReference().child(“订单”).child(tripDetails.get(“订单id”)).child(“信息”);
HashMap orderData=新HashMap();
放置(“坐标”,location.getLatitude()+,“+location.getLatitude());
orderData.put(“speed”,新的十进制格式(“location.getSpeed()*3.4”);
databaseReferenceOrders.push().setValue(orderData);
if(lastLocation!=null){
if(lastLocation.getLongitude()!=0&&lastLocation.getLongitude()!=0){
双倍距离=位置。距离(上次位置)/1000;
double totalDistance=double.parseDouble(mySharedPreferences.getTravelDistance())+distance;
对数d(“距离”,距离+”);
Log.d(“总距离”,总距离+”);
mySharedPreferences.setTraveledDistance(总距离+“”);
HomeFragment.textViewTraveledDistance.setText(新的十进制格式(“#####.####”)。格式(总距离));
}
}
lastLocation=位置;
}否则{
}
}
}否则{
}
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mGoogleMap;
    private MapFragment mapFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mapFragment = (MapFragment) getFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;

        List<LatLng> sourcePoints = new ArrayList<>();
        sourcePoints.add(new LatLng(-35.27801,149.12958));
        sourcePoints.add(new LatLng(-35.28032,149.12907));
        sourcePoints.add(new LatLng(-35.28099,149.12929));
        sourcePoints.add(new LatLng(-35.28144,149.12984));
        sourcePoints.add(new LatLng(-35.28194,149.13003));
        sourcePoints.add(new LatLng(-35.28282,149.12956));
        sourcePoints.add(new LatLng(-35.28302,149.12881));
        sourcePoints.add(new LatLng(-35.28473,149.12836));

        PolylineOptions polyLineOptions = new PolylineOptions();
        polyLineOptions.addAll(sourcePoints);
        polyLineOptions.width(5);
        polyLineOptions.color(Color.BLUE);
        mGoogleMap.addPolyline(polyLineOptions);

        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(sourcePoints.get(0), 15));

        List<LatLng> snappedPoints = new ArrayList<>();
        new GetSnappedPointsAsyncTask().execute(sourcePoints, null, snappedPoints);
    }


    private String buildRequestUrl(List<LatLng> trackPoints) {
        StringBuilder url = new StringBuilder();
        url.append("https://roads.googleapis.com/v1/snapToRoads?path=");

        for (LatLng trackPoint : trackPoints) {
            url.append(String.format("%8.5f", trackPoint.latitude));
            url.append(",");
            url.append(String.format("%8.5f", trackPoint.longitude));
            url.append("|");
        }
        url.delete(url.length() - 1, url.length());
        url.append("&interpolate=true");
        url.append(String.format("&key=%s", <your_Google_Maps_API_key>);

        return url.toString();
    }


    private class GetSnappedPointsAsyncTask extends AsyncTask<List<LatLng>, Void, List<LatLng>> {

        protected void onPreExecute() {
            super.onPreExecute();
        }

        protected List<LatLng> doInBackground(List<LatLng>... params) {

            List<LatLng> snappedPoints = new ArrayList<>();

            HttpURLConnection connection = null;
            BufferedReader reader = null;

            try {
                URL url = new URL(buildRequestUrl(params[0]));
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();

                InputStream stream = connection.getInputStream();

                reader = new BufferedReader(new InputStreamReader(stream));
                StringBuilder jsonStringBuilder = new StringBuilder();

                StringBuffer buffer = new StringBuffer();
                String line = "";

                while ((line = reader.readLine()) != null) {
                    buffer.append(line+"\n");
                    jsonStringBuilder.append(line);
                    jsonStringBuilder.append("\n");
                }

                JSONObject jsonObject = new JSONObject(jsonStringBuilder.toString());
                JSONArray snappedPointsArr = jsonObject.getJSONArray("snappedPoints");

                for (int i = 0; i < snappedPointsArr.length(); i++) {
                    JSONObject snappedPointLocation = ((JSONObject) (snappedPointsArr.get(i))).getJSONObject("location");
                    double lattitude = snappedPointLocation.getDouble("latitude");
                    double longitude = snappedPointLocation.getDouble("longitude");
                    snappedPoints.add(new LatLng(lattitude, longitude));
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
                try {
                    if (reader != null) {
                        reader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            return snappedPoints;
        }

        @Override
        protected void onPostExecute(List<LatLng> result) {
            super.onPostExecute(result);

            PolylineOptions polyLineOptions = new PolylineOptions();
            polyLineOptions.addAll(result);
            polyLineOptions.width(5);
            polyLineOptions.color(Color.RED);
            mGoogleMap.addPolyline(polyLineOptions);

            LatLngBounds.Builder builder = new LatLngBounds.Builder();
            builder.include(result.get(0));
            builder.include(result.get(result.size()-1));
            LatLngBounds bounds = builder.build();
            mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds,10));

        }
    }

}