Android GPS超时

时间:2010-06-07 19:44:55

标签: android gps

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

有时,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() ...

}

5 个答案:

答案 0 :(得分:6)

这不是真的如何运作。在大多数情况下,一直需要很长时间才能获得GPS定位。但是从每个更新的那一点开始(代码中每2秒)将是该人的当前位置。你获得的第一个修正将是该人的当前位置,因此数据不会“过时”。

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

查看Google I/O 2010 app,查看活动应如何与服务配合使用的一个很好的示例。它使用服务来提取数据,并在服务正在进行某些工作时显示标题的进度。并且仍然允许您在应用程序中执行其他操作。

答案 1 :(得分:4)

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

您无法控制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

答案 2 :(得分:3)

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

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

答案 3 :(得分:1)

我一直在努力解决类似问题,并且最近从计时器切换到AlarmManager,这看起来更加强大。这可能对你的情况有点过分(我使用它来重复进行位置采样),但你可能想要至少使用Handler而不是计时器。 (使用Handler.postDelayed。)

答案 4 :(得分:-7)

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