距离,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 不准确的主要内容,如果未能解决你的问题,请参考以下文章