【问题标题】:Android GPS timeout安卓 GPS 超时
【发布时间】:2010-06-07 19:44:55
【问题描述】:

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

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

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

因为我知道获得 GPS 定位不是即时的,而且我知道它可能需要几分钟或几小时(在此期间用户移动了很远的距离),所以我需要为此功能编写超时代码。对于此功能,在用户单击按钮后(例如)三分钟后上传用户的 GPS 位置是不可接受的。如果需要 45 秒就可以,如果需要 75 秒就不行。如果该功能未能足够快地获取位置,则可以向用户发出错误通知。

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

我的原始代码如下。自从发布它以来,我已经改变了一些东西。我在 onStartCommand() 方法中添加了一个 Timer。我启动了一个 TimerTask,它会在 60 秒后调用我的 stop() 方法。在 onLocationChanged() 方法的开头,我取消了 TimerTask。

我的问题是:Timer 方案是实现此超时的好方法吗?有没有更好的办法?

原问题:

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

但是,如果 GPS 坐标无法快速获得,我的服务将继续运行,直到获得一些坐标。它通过进度对话框支撑 UI,这很烦人。更糟糕的是,如果用户在启动服务后移动了,第一个 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() ...

}

【问题讨论】:

  • 那么你到底做了什么来解决这个问题?我有同样的问题。

标签: android gps


【解决方案1】:

实际上并不是这样。在大多数情况下,始终需要很长时间才能获得 GPS 定位。但从那时起,每次更新(代码中每 2 秒)将是此人的当前位置。您得到的第一个修复将是此人的当前位置,因此数据不会“过时”。

另一件事。如果您在服务中运行此代码,则不应使用进度对话框阻止 UI,并且绝对不应从服务中阻止。那是等待发生的内存泄漏。只有在最多可能需要 5 秒并且在 Activity 的线程中运行的情况下,您才应该显示进度。另一种选择是在标题栏中显示进度对话框,并且仍然让用户与应用程序交互(这就是您使用服务的原因)。长时间显示进度确实不是用户友好的。特别是如果他们以某种方式改变方向(可能是意外),然后您的应用程序由于对话框的服务句柄而崩溃,他们必须重新开始。

查看Google I/O 2010 app 以了解活动应如何与服务一起使用的一个很好的示例。它使用服务来拉回数据,并在服务进行某些工作时在标题中显示进度。并且仍然可以让您在应用中执行其他操作。

【讨论】:

  • 感谢您的帮助。我需要做的是在用户选择上下文菜单选项时获得一个位置。因此,如果获得 GPS 定位需要 15 分钟(有时在我的手机上),那么该位置将过时。基本上,我想知道用户单击按钮时在哪里以及是否花费了太长时间(无论可能是什么),那么我需要告诉用户该功能失败了。在大多数情况下,用户会坐在那里看手机,看看它是否有效。我不能让他们在没有 GPS 信号的情况下坐几个小时 :)
  • 如果是这种情况,那您为什么不在应用程序启动时立即启动 gps,然后每当他们按下按钮时,它很可能已经修复了。就像我之前说的。使用 GPS,位置不会过时。它得到了修复,位置更新将是手机的当前位置。
  • 好的。因此,如果您只想要用户按下按钮时的位置,为什么不注册 gps 更新并仅在修复后才启用按钮?所以当他们点击它时,你已经有了修复。
【解决方案2】:

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

您无法控制 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 个 SATELLITE_STATUS 事件报告了 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,true,26.0,57.0,73.0" 06-08 23:23:25.147,D,GPS,22427,"onGpsStatusChanged(): 4,true,30.0,46.0,27.0" 06-08 23:23:25.147,D,GPS,22427,"onGpsStatusChanged(): 5,true,19.0,144.0,25.0" 06-08 23:23:25.155,D,GPS,22427,"onGpsStatusChanged(): 9,true,22.0,202.0,22.0" 06-08 23:23:25.155,D,GPS,22427,"onGpsStatusChanged(): 10,true,17.0,109.0,32.0" 06-08 23:23:25.155,D,GPS,22427,"onGpsStatusChanged(): 12,true,32.0,320.0,80.0" 06-08 23:23:25.155,D,GPS,22427,"onGpsStatusChanged(): 29,true,21.0,278.0,21.0" 06-08 23:23:25.155,D,GPS,22427,"onGpsStatusChanged(): 30,true,31.0,312.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】:

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

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

【讨论】:

  • 链接是日文的。
【解决方案4】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    相关资源
    最近更新 更多