Java 短时间更改路线,然后将路线返回正确路线的解决方案是什么?
经过多次测试,当前位置不准确,多次移动,路线改变,计算错误距离。 示例:实际距离应为23公里,但结果为49公里 上传的照片很好地描述了情况 我们使用以下库使用服务后台: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
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));
}
}
}