如何使用 GPS 高精度计算每 15 秒的距离

How to calculate distance every 15 sec with using GPS heavy accuracy

我通过 Map.getMyLocation().getLatitude()locationManagermGoogleApiClient 等 3 种方式获取 GPS 位置。 但是这些对我每 15 秒计算一次距离没有帮助。 问题是位置纬度和经度不准确,即我使用这些距离计算方式步行 1-2 米。计算距离为 400 m-600 米,有时也显示 1 公里GPS 位置在 20 米到 600 米之间变化。 请提供一些更好的想法,以了解如何通过在 android 中每 15 秒计算一次距离来使我的位置非常准确.

这是我的代码

//get current location
try {
    locationManager = (LocationManager) getApplicationContext()
            .getSystemService(LOCATION_SERVICE);

    // getting GPS status
    isGPSEnabled = locationManager
            .isProviderEnabled(LocationManager.GPS_PROVIDER);

    // getting network status
    isNetworkEnabled = locationManager
            .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

    if (!isGPSEnabled && !isNetworkEnabled) {
        // no network provider is enabled
    } else {
        canGetLocation = true;
        // First get location from Network Provider
        if (isNetworkEnabled) {
            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

            Log.d("Network", "Network");
            if (locationManager != null) {

                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                if (location != null) {
                    old_latitude = location.getLatitude();
                    old_longitude = location.getLongitude();
                }
            }
        }
        // if GPS Enabled get lat/long using GPS Services
        if (isGPSEnabled) {
            if (location == null) {
                locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);


                if (locationManager != null) {
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                    if (location != null) {
                        old_latitude = location.getLatitude();
                        old_longitude = location.getLongitude();

                        Log.d("GPS Enabled", "GPS Enabled");
                    }
                }
            }
        }

    }
    //  Toast.makeText(this, "Current location"+current_latitude+","+current_longitude , Toast.LENGTH_LONG).show();
} catch (Exception e) {
    e.printStackTrace();
}

       /* GPSTracker gpsTracker = new GPSTracker(Activity_Map_Advance_Tracking.this);

        if (gpsTracker.getIsGPSTrackingEnabled()) {
            old_latitude=gpsTracker.latitude;
           old_longitude=gpsTracker.longitude;
        }*/
old_latitude = mMap.getMyLocation().getLatitude();
old_longitude = mMap.getMyLocation().getLongitude();

if (trip_status.equals("trip"))
    ha.postDelayed(new Runnable() {

        @Override
        public void run() {


            //get current location
            try {
                locationManager = (LocationManager) getApplicationContext()
                        .getSystemService(LOCATION_SERVICE);

                // getting GPS status
                isGPSEnabled = locationManager
                        .isProviderEnabled(LocationManager.GPS_PROVIDER);

                // getting network status
                isNetworkEnabled = locationManager
                        .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

                if (!isGPSEnabled && !isNetworkEnabled) {
                    // no network provider is enabled
                } else {
                    canGetLocation = true;
                    // First get location from Network Provider
                    if (isNetworkEnabled) {
                        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

                        Log.d("Network", "Network");
                        if (locationManager != null) {

                            location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                            if (location != null) {
                                new_latitude = location.getLatitude();
                                new_longitude = location.getLongitude();
                            }
                        }
                    }
                    // if GPS Enabled get lat/long using GPS Services
                    if (isGPSEnabled) {
                        if (location == null) {
                            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);


                            if (locationManager != null) {
                                location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                                if (location != null) {
                                    new_latitude = location.getLatitude();
                                    new_longitude = location.getLongitude();

                                    Log.d("GPS Enabled", "GPS Enabled");
                                }
                            }
                        }
                    }

                }
                //  Toast.makeText(this, "Current location"+current_latitude+","+current_longitude , Toast.LENGTH_LONG).show();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // check if GPS enabled
               /* GPSTracker gpsTracker = new GPSTracker(Activity_Map_Advance_Tracking.this);

                if (gpsTracker.getIsGPSTrackingEnabled()) {
                    new_latitude = gpsTracker.latitude;
                    new_longitude =gpsTracker.longitude;
                }*/
            new_latitude = mMap.getMyLocation().getLatitude();
            new_longitude = mMap.getMyLocation().getLongitude();


            double GPS_jump = 0.000100;

            if (Math.abs(old_latitude - new_latitude) < GPS_jump && Math.abs(old_longitude - new_longitude) < GPS_jump) {
                waiting_sec = waiting_sec + 15;
                if (waiting_sec >= (waiting_time * 60)) {
                    if (wait == 0) {
                        waitng_charge = (waiting_amnt_per_sec * waiting_sec) + waitng_charge;
                        wait = 15;
                        //waiting_sec=0;
                    } else {
                        waitng_charge = (waiting_amnt_per_sec * wait) + waitng_charge;
                    }
                }

                // total_distance=meterDistanceBetweenPoints(13.020876, 80.222541,13.021301, 80.222881)+total_distance;
                // client_info.setText("TOTAL DISTANCE:"+total_distance/1000);
                System.out.println("vehicle not move" + Math.abs((float) old_latitude - (float) new_latitude) + "," + Math.abs((float) old_longitude - (float) new_longitude));
                Toast.makeText(Activity_Map_Advance_Tracking.this, "vehicle not move" + Math.abs((float) old_latitude - (float) new_latitude) + "," + Math.abs((float) old_longitude - (float) new_longitude), Toast.LENGTH_LONG).show();


                // assuming doubles are equals
            } else {

                System.out.println("vehicle moved" + Math.abs((float) old_latitude - (float) new_latitude) + "," + Math.abs((float) old_longitude - (float) new_longitude));
                if ((waiting_sec) >= (waiting_time * 60)) {
                    waitng_charge = waiting_amnt_per_sec + waitng_charge;
                }
                total_distance = meterDistanceBetweenPoints(old_latitude, old_longitude, new_latitude, new_longitude) + total_distance;
                waiting_sec = 0;
                wait = 0;

                Toast.makeText(Activity_Map_Advance_Tracking.this, "vehicle moved" + Math.abs((float) old_latitude - (float) new_latitude) + "," + Math.abs((float) old_longitude - (float) new_longitude), Toast.LENGTH_LONG).show();
                Toast.makeText(Activity_Map_Advance_Tracking.this, "****TOTAL DISTANCE*****->" + total_distance, Toast.LENGTH_LONG).show();
                client_info.setText("TOTAL DISTANCE:" + total_distance);
            }


            delay_sec = delay_sec + 15;
            System.out.println("After " + delay_sec + " sec \n waiting sec" + waiting_sec + " sec\n waitng charge" + waitng_charge + "rs \n currunt lat and lng" + new_latitude + " , " + new_longitude + "" +
                    "\n___old lat lng" + old_latitude + " , " + old_longitude);


            Toast.makeText(Activity_Map_Advance_Tracking.this, "After " + delay_sec + " sec \n waiting sec" + waiting_sec + " sec\n waitng charge" + waitng_charge + "rs \n currunt lat and lng" + new_latitude + " , " + new_longitude + "" +
                    "\n___old lat lng" + old_latitude + " , " + old_longitude + ", \ntotal distance: " + total_distance, Toast.LENGTH_LONG).show();


            old_latitude = new_latitude;
            old_longitude = new_longitude;

            //call function
            ha.postDelayed(this, 15000);
        }
    }, 15000);

这是我的距离计算方法 但是这个方法不是问题

 private float meterDistanceBetweenPoints(double lat_a, double lng_a, double lat_b, double lng_b) {
    /*Location locationA = new Location("point A");

    locationA.setLatitude(lat_a);
    locationA.setLongitude(lng_a);

    Location locationB = new Location("point B");

    locationB.setLatitude(lat_b);
    locationB.setLongitude(lng_b);

    float distance = locationA.distanceTo(locationB);*/
    double earthRadius = 6371000; //meters
    double dLat = Math.toRadians(lat_b - lat_a);
    double dLng = Math.toRadians(lng_b - lng_a);
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(Math.toRadians(lat_a)) * Math.cos(Math.toRadians(lat_b)) *
                    Math.sin(dLng / 2) * Math.sin(dLng / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    float dist = (float) (earthRadius * c);


    System.out.println("**********this is distance calculation**********" + dist);
    return dist;
}

您可以使用 requestLocation update 开始获取位置更新:

mylistener = new MyLocationListener();
locationManager.requestLocationUpdates(provider, 150000, 1, mylistener);

这里你会在每 15 秒和 1 米位置变化后得到更新:

当 locationmanager 获取位置更新时,它会调用 onLocationChanged() 方法。您将在那里获得更新的位置。

private class MyLocationListener implements LocationListener {

    @Override
    public void onLocationChanged(Location location) {
    }
         //Do your code with this updated location
}

您可以设置条件位置收集。如果你想获得准确的位置,我建议你只使用 GPS_PROVIDER。请记住,虽然 GPS 在屋内无法正常工作。

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setPowerRequirement(Criteria.POWER_HIGH);
    provider = locationManager.getBestProvider(criteria, true);
    previouslocation = locationManager.getLastKnownLocation(provider);

全局声明 -

 float distanceInMeters = 0; 

在 onLocationChanged() 中添加距离:

public void onLocationChanged(Location location) {
      distanceInMeters += previousLocation.distanceTo(location);  
      Toast.makeText(YourActivity.this, "Distance" + distanceInMeters,Toast.LENGTH_SHORT).show();    // Showing the distance in meter
      previousLocation = location;
   }

注意: 我已将第一个位置值更改为 previousLocation 以避免混淆。

正如评论部分中有人发布的那样,使用 LocationManager /FusedLocationApi。您可以额外做的是:

  1. 即使您每 15 秒需要一次位置,也可以以较小的间隔或连续获取一次,然后进行计算。这会给设备的电池带来压力。
  2. 如果您获得的新位置与上一个位置相距很远,请忽略它。有些设备可能 return 错误的值(有一个 Nexus5 现在可以工作,下一秒就会显示 4-5 公里以外的地方)。
  3. 如果电池有问题,请将间隔设置为 15 秒,也许 PRIORITY_BALANCED_POWER_ACCURACY,但请确保您有后备。如果两个位置之间的距离太大或读数的准确性不好,请忽略 it/request 另一个位置。

请检查这个 点赞

   criteria.setPowerRequirement(Criteria.POWER_HIGH);

MainActivity.java

public class MainActivity extends AppCompatActivity {

LocationManager locationManager;
Criteria criteria;
String provider;
Location location;
double old_latitude; // latitude
double old_longitude; // longitude
TextView distance;
double new_latitude; // latitude
double new_longitude; // longitude
float total_distance = 0.0f;
String details;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    distance = (TextView) findViewById(R.id.distance);

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setPowerRequirement(Criteria.POWER_HIGH);
    provider = locationManager.getBestProvider(criteria, true);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    location = locationManager.getLastKnownLocation(provider);

    try {
        old_latitude = location.getLatitude();
        old_longitude = location.getLongitude();
    } catch (Exception e) {

    }

    locationManager.requestLocationUpdates(provider, 15000, 1, new LocationListener() {


        @Override
        public void onLocationChanged(Location location) {
            if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            location = locationManager.getLastKnownLocation(provider);
            new_latitude = location.getLatitude();
            new_longitude = location.getLongitude();

            total_distance = meterDistanceBetweenPoints(old_latitude, old_longitude, new_latitude, new_longitude) + total_distance;

            if (details == null) {
                details = "current location:" + new_latitude + ", " + new_longitude;
                details = details + "\n" + "old location:" + old_latitude + ", " + old_longitude;
                details = details + "\n" + "\n" + "total distance:" + total_distance + " m";
                details = details + "\n" + "----------------------------------------------" + "\n";
            } else {

                details = details + "\n" + "current location:" + new_latitude + ", " + new_longitude;
                details = details + "\n" + "old location:" + old_latitude + ", " + old_longitude;
                details = details + "\n" + "\n" + "total distance:" + total_distance + " m";
                details = details + "\n" + "----------------------------------------------" + "\n";
            }

            distance.setText(details);

            old_latitude = new_latitude;
            old_longitude = new_longitude;

            System.out.println("**********this is LocationChanged**********" + 15000);
            Toast.makeText(MainActivity.this, "current location" + new_latitude + new_longitude, Toast.LENGTH_LONG).show();
            Toast.makeText(MainActivity.this, "old location" + old_latitude + old_longitude, Toast.LENGTH_LONG).show();
            Toast.makeText(MainActivity.this, "LocationChanged" + Math.abs((float) old_latitude - (float) new_latitude) + "," + Math.abs((float) old_longitude - (float) new_longitude), Toast.LENGTH_LONG).show();

        }

        @Override
        public void onStatusChanged(String s, int i, Bundle bundle) {
            System.out.println("**********this is StatusChanged**********" + 15000);
            Toast.makeText(MainActivity.this, "StatusChanged" + Math.abs((float) old_latitude - (float) new_latitude) + "," + Math.abs((float) old_longitude - (float) new_longitude), Toast.LENGTH_LONG).show();

        }

        @Override
        public void onProviderEnabled(String s) {
            System.out.println("**********this is ProviderEnabled**********" + 15000);
            Toast.makeText(MainActivity.this, "ProviderDisabled" + Math.abs((float) old_latitude - (float) new_latitude) + "," + Math.abs((float) old_longitude - (float) new_longitude), Toast.LENGTH_LONG).show();

        }

        @Override
        public void onProviderDisabled(String s) {
            System.out.println("**********this is ProviderDisabled**********" + 15000);
            Toast.makeText(MainActivity.this, "ProviderDisabled" + Math.abs((float) old_latitude - (float) new_latitude) + "," + Math.abs((float) old_longitude - (float) new_longitude), Toast.LENGTH_LONG).show();

        }
    });


    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}
private float meterDistanceBetweenPoints(double lat_a, double lng_a, double lat_b, double lng_b) {
    double earthRadius = 6371000; //meters
    double dLat = Math.toRadians(lat_b - lat_a);
    double dLng = Math.toRadians(lng_b - lng_a);
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(Math.toRadians(lat_a)) * Math.cos(Math.toRadians(lat_b)) *
                    Math.sin(dLng / 2) * Math.sin(dLng / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    float dist = (float) (earthRadius * c);
    Toast.makeText(MainActivity.this, "calculated distance" + dist + "," + Math.abs((float) old_longitude - (float) new_longitude), Toast.LENGTH_LONG).show();
    System.out.println("**********this is distance calculation**********" + dist);
    return dist;
}}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.rmadeandroid.lcation_change_listioner.MainActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_main" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin"
    app:srcCompat="@android:drawable/ic_dialog_email" /</android.support.design.widget.CoordinatorLayout>

content_main.xml

<?xml version="1.0" encoding="utf-8"?><ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.rmadeandroid.lcation_change_listioner.MainActivity"
tools:showIn="@layout/activity_main"><RelativeLayout
android:id="@+id/content_main"
android:layout_width="match_parent"
android:layout_height="match_parent"><TextView
    android:id="@+id/distance"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="device not move" /></RelativeLayout></ScrollView>

清单中的权限

 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

输出

在一个答案中,代码:

distanceInMeters += previousLocation.distanceTo(location);

很好,但我建议 - 除非有人发现它有问题,否则只需使用:

locationManager.requestLocationUpdates(provider, 0, DISTANCE, mylistener); 

并累积DISTANCE(前提是它是一个相对较小的DISTANCE)。对不起,我不能把它放在评论中,因为他们删除了很多积分。

编辑:但 distanceInMeters += previousLocation.distanceTo(location) 比我上面建议的更准确。