距离,Google Maps v2 上的 gps 不准确

Posted

技术标签:

【中文标题】距离,Google Maps v2 上的 gps 不准确【英文标题】:distance, inaccurate gps on Google Maps v2 【发布时间】:2014-01-27 15:52:20 【问题描述】:

我正在创建一个应用程序,它使用谷歌地图 v2 和 gps 来计算用户步行的距离。有2个问题。 我的gps不准确。尽管周围环境是正确的,但它并没有准确地显示我在哪里。在道路,建筑物等上,但显示的位置似乎与确切位置有点偏离。 它更新位置的方式是几秒钟后蓝点会从一个地方“跳”到另一个地方。而不是平滑移动并显示用户已运行的线条。 我的距离是不准确的。我需要按开始移动以显示距离。有时我按下它后应用程序崩溃。计数值是让我确定应用程序在我的代码中运行的位置。根据我的计划,随着距离的增加,计数应该会不断增加。 抱歉,如果有一堆信息,但我想我应该提供更多信息。我在互联网上搜索,但找不到计算准确距离或提高 GPS 精度的方法

这是我的 GPS 屏幕截图

我的主要活动 Java 代码

import com.example.mypp.R; 
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.view.Menu;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
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.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MainActivity extends FragmentActivity implements LocationListener, Runnable

protected LocationManager locationManager;
private GoogleMap googleMap;
Button btnStartMove,btnPause,btnResume,btnStop;
TextView Distance;
static double n=0;
    Long s1,r1;
    double lat1,lon1,lat2,lon2;
    double dis=0.0;
    MyCount counter;
    Thread t1;
    EditText e1;
    boolean bool=false;
    int count=0;
@Override
protected void onCreate(Bundle savedInstanceState) 

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    if(isGooglePlay())
    
        //setContentView(R.layout.activity_main);
        setUpMapIfNeeded();
    
    btnStartMove=(Button)findViewById(R.id.Start);//start moving
    btnPause=(Button)findViewById(R.id.Pause);//pause
    btnResume=(Button)findViewById(R.id.Resume);//resume
    btnStop=(Button)findViewById(R.id.Stop);
    Distance=(TextView)findViewById(R.id.Distance);
    btnStartMove.setOnClickListener(new OnClickListener() 
    
        @Override
        public void onClick(View v) 
            // TODO Auto-generated method stub
            //start(v);
            Distance.setText("Distance:" + dis);
            start(v);
    

    );
    btnPause.setOnClickListener(new OnClickListener() 
    
        @Override
        public void onClick(View v) 
            // TODO Auto-generated method stub
            //start(v); 
        
    );
    btnResume.setOnClickListener(new OnClickListener() 
    
        @Override
        public void onClick(View v) 
            // TODO Auto-generated method stub
            //start(v); 
        
    );
    btnStop.setOnClickListener(new OnClickListener() 
    
        @Override
        public void onClick(View v) 
            // TODO Auto-generated method stub
            //start(v); 
        
    );




private void setUpMapIfNeeded() 

    if(googleMap == null)
    
        Toast.makeText(MainActivity.this, "Getting map",
                Toast.LENGTH_LONG).show();
        googleMap =((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.displayMap)).getMap();

        if(googleMap != null)
        
            setUpMap();
        
    



private void setUpMap() 

    //Enable MyLocation Layer of Google Map
    googleMap.setMyLocationEnabled(true);

    //Get locationManager object from System Service LOCATION_SERVICE
    //LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

    //Create a criteria object to retrieve provider
    Criteria criteria = new Criteria();

    //Get the name of the best provider
    String provider = locationManager.getBestProvider(criteria, true);
    if(provider == null)
    
        onProviderDisabled(provider);
    
    //set map type
    googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
    //Get current location
    Location myLocation = locationManager.getLastKnownLocation(provider);
    if(myLocation != null)
    
        onLocationChanged(myLocation);
           


private boolean isGooglePlay() 

    int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

    if (status == ConnectionResult.SUCCESS)
    

        Toast.makeText(MainActivity.this, "Google Play Services is available",
                Toast.LENGTH_LONG).show();
        return(true);
    
    else
    
            GooglePlayServicesUtil.getErrorDialog(status, this, 10).show();

    
    return (false);

 

@Override
public void onLocationChanged(Location myLocation) 
    //Get latitude of the current location
    double latitude = myLocation.getLatitude();
    //Get longitude of the current location
    double longitude = myLocation.getLongitude();
    //Create a LatLng object for the current location
    LatLng latLng = new LatLng(latitude, longitude);
    //Show the current location in Google Map
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    //Zoom in the Google Map
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(20));
    googleMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("You are here!"));



@Override
public void onProviderDisabled(String provider) 
    Toast.makeText(MainActivity.this,
            "Provider disabled by the user. GPS turned off",
            Toast.LENGTH_LONG).show();


@Override
public void onProviderEnabled(String provider) 
    Toast.makeText(MainActivity.this,
            "Provider enabled by the user. GPS turned on",
            Toast.LENGTH_LONG).show();


@Override
public void onStatusChanged(String provider, int status, Bundle extras) 
    Toast.makeText(MainActivity.this, "Provider status changed",
            Toast.LENGTH_LONG).show();


public void start (View v)

    switch(v.getId())
    case R.id.Start:
        Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (location != null)
        
            lat2=location.getLatitude();
            lon2=location.getLongitude();
            bool=true;
            t1=new Thread(this);
            t1.start();
            counter= new MyCount(30000,1000);
            counter.start();

        
        else
        
            Toast.makeText(MainActivity.this, "null location",
                    Toast.LENGTH_LONG).show();
        
     break;
    case R.id.Pause:
        counter.cancel();
        bool=false;
        break;
    case R.id.Resume:
        counter= new MyCount(s1,1000);
     counter.start();
     bool=true;
     break;
    case R.id.Distance:
        double time=n*30+r1;
        Distance.setText("Distance:" + dis);
        Toast.makeText(MainActivity.this,"distance in metres:"+String.valueOf(dis)+"Velocity in m/sec :"+String.valueOf(dis/time)+"Time :"+String.valueOf(time),Toast.LENGTH_LONG).show();
        Toast.makeText(MainActivity.this, "Value of Count:" + String.valueOf(count),
                Toast.LENGTH_LONG).show();
     break;        
    case R.id.Stop:
        counter.cancel();
        counter= new MyCount(30000,1000);
        bool = false;

    


public class MyCount extends CountDownTimer
    public MyCount(long millisInFuture, long countDownInterval) 
    super(millisInFuture, countDownInterval);
    
    @Override
    public void onFinish() 
        counter= new MyCount(30000,1000);
     counter.start();
     n=n+1;
    
    @Override
    public void onTick(long millisUntilFinished) 
        s1=millisUntilFinished;
        r1=(30000-s1)/1000;
        e1.setText(String.valueOf(r1));


    


public double getDistance(double lat1, double lon1, double lat2, double lon2) 
    double latA = Math.toRadians(lat1);
    double lonA = Math.toRadians(lon1);
    double latB = Math.toRadians(lat2);
    double lonB = Math.toRadians(lon2);
    double cosAng = (Math.cos(latA) * Math.cos(latB) * Math.cos(lonB-lonA)) +
                    (Math.sin(latA) * Math.sin(latB));
    double ang = Math.acos(cosAng);
    double dist = ang *6371;
    return dist;


@Override
public void run() 

    count=6;
    //LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 
    Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    lat1=location.getLatitude();
    lon1=location.getLongitude();
    while(bool==true)
    
        if(lat1!=lat2 || lon1!=lon2)
        
            dis+=getDistance(lat2,lon2,lat1,lon1);
            lat2=lat1;
            lon2=lon1;
            count =7;
            Distance.setText("Distance: " + dis + " Count: " + count);
            count++;
        

    


抱歉,我忘了过去的崩溃日志。这里是。我知道我的代码很多且令人困惑,但我不知道计算距离的有效方法。

01-28 00:36:58.820: D/dalvikvm(25535): GC_CONCURRENT freed 595K, 8% free 14911K/16135K, paused 4ms+8ms, total 56ms
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[0] is 30
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[0] is 30
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[1] is 2e
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[0] is 30
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[1] is 2e
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[2] is 30
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[0] is 30
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[0] is 30
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[1] is 2e
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[0] is 30
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[1] is 2e
01-28 00:37:06.135: D/TextLayoutCache(25535): TextLayoutCache::replaceThai, prevBuffer[2] is 30
01-28 00:37:06.140: D/AndroidRuntime(25535): Shutting down VM
01-28 00:37:06.140: W/dalvikvm(25535): threadid=1: thread exiting with uncaught exception (group=0x4178f2a0)
01-28 00:37:06.140: E/AndroidRuntime(25535): FATAL EXCEPTION: main
01-28 00:37:06.140: E/AndroidRuntime(25535): java.lang.NullPointerException
01-28 00:37:06.140: E/AndroidRuntime(25535):    at com.example.studenthealthapp.MainActivity$MyCount.onTick(MainActivity.java:262)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:124)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at android.os.Looper.loop(Looper.java:137)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at android.app.ActivityThread.main(ActivityThread.java:4898)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at java.lang.reflect.Method.invokeNative(Native Method)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at java.lang.reflect.Method.invoke(Method.java:511)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
01-28 00:37:06.140: E/AndroidRuntime(25535):    at dalvik.system.NativeStart.main(Native Method)
01-28 00:37:14.305: I/Process(25535): Sending signal. PID: 25535 SIG: 9

【问题讨论】:

你的问题不清楚,还有很多代码,你也提到了崩溃,但没有提供与这次崩溃相关的堆栈跟踪。 【参考方案1】:

获取距离使用Location.distanceBetween

您也应该使用新的 Location API 而不是旧的。那么您可以设置最小行驶距离以尝试摆脱 GPS 发回的错误位置

【讨论】:

什么是新的 Location API?我只知道不同版本的谷歌地图,我不知道有一个新的位置 API..但是之间的距离是计算起点和终点之间的最小直线距离?还是我用它来累积距离,因为新位置发生了变化。抱歉,关于 distanceTo 和 distanceBetween 的教程不多。这就是我改用手动计算的原因。 基于您的链接。传入参数后如何计算距离? 您保留一个运行总数或保留所有位置的列表,然后在最后循环通过它们获取点到点的距离。新的位置 API 在 google play services developer.android.com/google/play-services/location.html【参考方案2】:

我非常同意 tyczj 的观点,即您应该更新到最新的 google play location API,其中一个主要原因是它们显着提高了位置测量的准确性,第二个原因是它们显着简化了获取位置的过程位置数据。

多年来,我一直致力于开源 gps 跟踪器项目。我最近更新了它来处理来自 android、ios、windows phone 和 java me 手机的定期更新。它功能齐全,可以满足您的需求,并且获得 MIT 许可。

https://github.com/nickfox/GpsTracker

看看安卓客户端。还有两个服务器堆栈可供选择。

【讨论】:

它给出准确的距离吗?【参考方案3】:

按照这种方法以米为单位查找距离...我已经使用过这个方法并且对我来说工作正常...

/** * * @param lat1 * 第一个位置的纬度 * @param lng1 * 第一个位置的对数 * @param lat2 * 第二个位置的纬度 * @param lng2 * 第二个位置的经度 * @return 以浮点格式返回两个纬度之间的距离 */

public float distFrom(double lat1, double lng1, double lat2, double lng2)

    double earthRadius = 3958.75;
    double dLat = Math.toRadians(lat2 - lat1);
    double dLng = Math.toRadians(lng2 - lng1);
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
            * Math.sin(dLng / 2) * Math.sin(dLng / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double dist = earthRadius * c;

    int meterConversion = 1609;
    return new Float(dist * meterConversion).floatValue();


// This function converts decimal degrees to radians :::
private double deg2rad(double deg)

    return (deg * Math.PI / 180.0);


// This function converts radians to decimal degrees :::
private double rad2deg(double rad)

    return (rad / Math.PI * 180.0);

【讨论】:

以上是关于距离,Google Maps v2 上的 gps 不准确的主要内容,如果未能解决你的问题,请参考以下文章

android google maps v2 在服务中

Google Maps Android api v2 和当前位置

Google Maps v2 上的动画标记

如何修复 Google Maps Android v2 上的语言环境问题?

根据 Google Maps V2 Android 上的用户方向旋转标记

Google Maps Android API v2 - 检测地图上的触摸