代码之家  ›  专栏  ›  技术社区  ›  Scott Saunders

Android GPS超时

  •  12
  • Scott Saunders  · 技术社区  · 15 年前

    编辑: 我重写这个问题是因为我显然不清楚。

    有时Android手机上的GPS服务需要很长时间才能得到修复。有时很快,有时需要几个小时。我知道并接受这个。

    我有一个可以做很多事情的应用程序。它必须做的一件事是允许用户单击一个按钮将当前坐标发送到服务器。我需要的是电话的坐标 当用户单击按钮时 或在此后的一段相当短的时间内。

    因为我知道获得GPS定位不是即时的,而且我知道可能需要几分钟或几小时(在此期间用户移动了很长的距离),所以我需要为此功能编写超时代码。对于此功能,用户单击按钮三分钟后(例如)上传GPS位置是不可接受的。45秒没问题,75秒没问题。如果这个功能不能足够快地得到一个位置,可以给用户一个错误通知。

    我需要一个功能来“获取GPS位置并将其发送到服务器, 除非超过一分钟 '.

    我的原始代码如下。自从贴了以后,我改变了一些事情。我在onStartCommand()方法中添加了一个计时器。我启动一个TimerTask,60秒后将调用stop()方法。在onlocationChanged()方法的开头,我取消了timertask。

    我的问题是:计时器方案是实现这个超时的好方法吗?有更好的方法吗?

    原始问题:

    我正在编写一个Android应用程序,其中一个需要将当前的GPS坐标发送到服务器,当用户告诉它的时候。从上下文菜单中,我运行下面的服务。该服务是一个locationListener,并从locationManager请求更新。当它得到一个位置(onlocationChanged())时,它会将自己作为侦听器删除,并将坐标发送到服务器。所有这些都有效。

    但是,如果GPS坐标不能很快获得,我的服务就会一直运行直到得到一些。它用一个进度对话框来支持用户界面,这很烦人。更糟糕的是,如果用户在启动服务后移动,第一个GPS坐标可能是错误的,应用程序将向服务器发送错误数据。

    我需要暂停服务。有什么好办法吗?我对线头不是很有经验。我想我可以在onStartCommand()方法中运行一个runnable,它将以某种方式倒数30秒,然后,如果还没有GPS结果,调用我的服务的stop()方法。这听起来是最好的方法吗?

    或者,是否可以判断GPS是否无法获得定位?我该怎么做呢?

    编辑: 为了进一步澄清,我正在寻找在一段时间后“放弃”一个地点的最佳方式。

    public class AddCurrentLocation extends Service implements LocationListener {
    
        Application app;
        LocationManager mLocManager;
        ProgressDialog mDialog;
    
        @Override
        public int onStartCommand(Intent intent, int arg0, int arg1) {
            app = getApplication();
    
            // show progress dialog
            if (app.getScreen() != null) {
                mDialog = ProgressDialog.show(app.getScreen(), "", "Adding Location. Please wait...", true);
            }
    
            // find GPS service and start listening
            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            mLocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            String bestProvider = mLocManager.getBestProvider(criteria, true);
            mLocManager.requestLocationUpdates(bestProvider, 2000, 0, this);
    
            return START_NOT_STICKY;
        }
    
        private void stop() {
            mLocManager.removeUpdates(this);
            if (mDialog != null) {
                mDialog.dismiss();
            }
            stopSelf();
        }
    
        @Override
        public void onLocationChanged(Location location) {
            // done with GPS stop listening
            mLocManager.removeUpdates(this);
    
            sendLocation(location); // method to send info to server
            stop();
        }
    
        // other required methods and sendLocation() ...
    
    }
    
    5 回复  |  直到 12 年前
        1
  •  6
  •   Robby Pond    15 年前

    这不是真正的工作原理。在大多数情况下,要想得到一个GPS定位,通常需要这么长的时间。但从那时起,每次更新(代码中每2秒)都将是此人当前的位置。你得到的第一个修正就是这个人的当前位置,所以数据不会“过时”。

    另外一件事。如果在服务中运行此代码,则不应使用进度对话框阻止UI,而绝对不应使用服务。这是一个等待发生的内存泄漏。只有当进度可能最多需要5秒,并且正在活动中的线程中运行时,才应显示进度。另一个选项是在标题栏中显示进度对话框,并且仍然允许用户与应用程序交互(这就是为什么您仍然使用服务)。在很长一段时间内显示进度真的不太方便用户。尤其是如果他们以某种方式改变方向(可能是偶然的),然后你的应用程序因为对话框的服务处理而崩溃,他们必须重新开始。

    看看 Google I/O 2010 app 以了解活动如何与服务一起工作的一个很好的示例。它使用服务来提取数据,并在服务执行某些工作时显示标题中的进度。还可以让你在应用程序中做其他事情。

        2
  •  4
  •   DJC    13 年前

    斯科特,有很多因素会影响第一次修复需要多长时间,甚至影响修复是否可以实现,最常见的是设备和卫星之间的物理障碍(如:建筑物、峡谷壁等)。

    您无法控制GPS引擎提供修复所需的时间,但您可以了解它的工作方式,包括第一次修复的时间:

    locationManager.addGpsStatusListener(gpsListener);
    
        // this reports on the status of the GPS engine, but does not enable additional controls 
        private static final GpsStatus.Listener gpsListener = new GpsStatus.Listener() {
            public void onGpsStatusChanged(int event) {
                GpsStatus gpsStatus = locationManager.getGpsStatus(null);
                switch (event) {
                    case GpsStatus.GPS_EVENT_STARTED: 
                        Log.i(TAG, "onGpsStatusChanged(): GPS started");
                        break;
                    case GpsStatus.GPS_EVENT_FIRST_FIX: 
                        Log.i(TAG, "onGpsStatusChanged(): time to first fix in ms = " + gpsStatus.getTimeToFirstFix());
                        break;
                    case GpsStatus.GPS_EVENT_SATELLITE_STATUS: 
                        // int maxSatellites = gpsStatus.getMaxSatellites();    // appears fixed at 255
                        // if (H.DEBUG) Log.d(TAG, "onGpsStatusChanged(): max sats = " + maxSatellites);
                        if (H.VERBOSE) Log.d(TAG, "onGpsStatusChanged(): ##,used,s/n,az,el");
                        Iterable<GpsSatellite>satellites = gpsStatus.getSatellites();
                        Iterator<GpsSatellite>satI = satellites.iterator();
                        while (satI.hasNext()) {
                            GpsSatellite satellite = satI.next();
                            if (H.VERBOSE) Log.d(TAG, "onGpsStatusChanged(): " + satellite.getPrn() + "," + satellite.usedInFix() + "," + satellite.getSnr() + "," + satellite.getAzimuth() + "," + satellite.getElevation()); 
                            // http://en.wikipedia.org/wiki/Global_Positioning_System: the almanac consists of coarse orbit and status information for each satellite
                            // http://en.wikipedia.org/wiki/Ephemeris: the positions of astronomical objects in the sky at a given time
                            // + "," + satellite.hasAlmanac() + "," + satellite.hasEphemeris());
                        }
                        break;
                    case GpsStatus.GPS_EVENT_STOPPED: 
                        Log.i(TAG, "onGpsStatusChanged(): GPS stopped");
                        break;
                }       
            }
        };
    

    当引擎尝试监听可用的卫星时,将生成事件。在最近的一次用光障碍物进行的测试中,我发现需要22.4秒才能得到一个初始修复,在此期间,24个卫星状态事件报告了8个卫星的逐渐访问,然后收到足够干净的信号来实现修复。这是最后一个事件:

    06-08 23:23:25.147,D,GPS,22427,“ongpsStatusChanged():,used,s/n,az,el” 06-08 23:23:25.147,D,GPS,22427,“OngPSStatusChanged():2,真,26.0,57.0,73.0” 06-08 23:23:25.147,D,GPS,22427,“OngPSStatusChanged():4,真,30.0,46.0,27.0” 06-08 23:23:25.147,D,GPS,22427,“OngPSStatusChanged():5,真,19.0144.0,25.0” 06-08 23:23:25.155,D,GPS,22427,“OngPSStatusChanged():9,真,22.0202.0,22.0” 06-08 23:23:25.155,D,GPS,22427,“ongpsStatusChanged():10,真,17.0109.0,32.0” 06-08 23:23:25.155,D,GPS,22427,“OngPSStatusChanged():12,真,32.0320.0,80.0” 06-08 23:23:25.155,D,GPS,22427,“OngPSStatusChanged():29,真,21.0278.0,21.0” 06-08 23:23:25.155,D,GPS,22427,“OngPSStatusChanged():30,真,31.0312.0,43.0” 06-08 23:23:25.163,D,gpslocationprovider,1039,ttff:22457 06-08 23:23:25.194,I,GPS,22427,ongpsStatusChanged():首次固定时间ms=22457

    请注意,在固定时间,您将获得当前位置,而不是您曾经去过的位置。我想除了你已经拥有的东西,你现在可以到达那里。或者,看看职业选手是怎么做到的 here .

        3
  •  3
  •   Shawn    14 年前

    有一个关于获取带超时的GPS位置的示例。

    http://sikazi.blogspot.com/2010/09/android-gps-timeout.html#more

        4
  •  1
  •   John R.B. Palmer    12 年前

    我一直在努力解决类似的问题,最近我从计时器切换到了 AlarmManager 这似乎更为有力。对于您的情况来说,这可能是杀伤力过大的(我将此用于重复的位置采样),但您可能希望至少使用 Handler 而不是计时器。(使用) Handler.postDelayed )

        5
  •  -7
  •   Jeff Bootsholz    12 年前

    根据对Shawn的回答,将参数打包到JSON中,并将JSON对象发送到服务器中。